Getting Started
Accessing AccuTerra Maps
Welcome to AccuTerra Maps. Adding AccuTerra Maps to your mobile or web applications is a great way to empower your users with access to the most complete outdoor recreation maps avaliable.
AccuTerra provides multiple map styles for you to choose from, see the Map Styles section below for more information on each style. Each map style supports both raster and vector tiles.
Each map service requires a API key to work. You can manage your API keys within the API Keys section of your Account page.
Get started developing with AccuTerra today, create your free account.
Map Styles
Accuterra Outdoors
AccuTerra Outdoors showcases the unique map content AccuTerra has to offer. Our public lands data, combined with . We show in bright and bold color America’s many public land types so you always know who manages the land you’re on. When combined with our extensive road and trail network and overlaid on our highly detailed terrain data, AccuTerra Outdoors is the perfect companion for your next outdoor adventure. This map is available in both metric and imperial elevation units.
'Imperial: https://maps.accuterra.com/v1/styles/accuterra-outdoors.json?apiKey=YOUR-MAP-API-KEY-HERE',
'Metric: https://maps.accuterra.com/v1/styles/accuterra-outdoors-m.json?apiKey=YOUR-MAP-API-KEY-HERE',
'https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/{z}/{x}/{y}.jpg?key=YOUR-MAP-API-KEY-HERE',
Web Code Samples
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.17/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.17/"></script>
<title>ArcGIS JavaScript</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/Basemap",
"esri/layers/VectorTileLayer",
"esri/layers/WebTileLayer",
], function(Map, MapView, Basemap, VectorTileLayer, WebTileLayer) {
const myAPIKey = 'YOUR-MAP-API-KEY-HERE';
//override all XHRs (used in 3.x) to append api key
(function() {
var proxyOpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function() {
var args = Array.prototype.slice.call(arguments);
if (args[1].indexOf("accuterra.com")>0){
args[1] += (args[1].indexOf("?") == -1 ? "?" : "&") + \`key=YOUR-MAP-API-KEY-HERE`;
}
return proxyOpen.apply(this, [].slice.call(args));
};})();
//override all fetch() calls (used in 4.x) to append api key
(function () {
var originalFetch = fetch;
fetch = function() {
var args = Array.prototype.slice.call(arguments);
if (args[0].indexOf("accuterra.com")>0){
args[0] += (args[0].indexOf("?") == -1 ? "?" : "&") + \`key=YOUR-MAP-API-KEY-HERE`;
}
return originalFetch.apply(this, args).then(function(data) {
// someFunctionToDoSomething();
return data;
});
};
})();
// base vector layer
var basemap = new Basemap({
baseLayers: [
new VectorTileLayer({
style: "esri-accuterra.json"
})
]
});
var map = new Map({
basemap: basemap
});
// contours vector layer
var contourLayer = new VectorTileLayer({
style: "esri-accuterra-contours.json"
});
map.add(contourLayer);
// hill shade raster layer
var hillShadeLayer = new WebTileLayer({
urlTemplate: \`https://maps.accuterra.com/v1/data/hillshade/{level}/{col}/{row}.jpg?key=YOUR-MAP-API-KEY-HERE`,
opacity: 0.2
});
map.add(hillShadeLayer);
var view = new MapView({
container: "viewDiv",
map: map,
center: [-105.0053989, 39.6500327], // longitude, latitude
zoom: 10
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
<html>
<head>
<title>Google Maps API with AccuTerra raster as base layer</title>
<style>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script
type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?sensor=false&key=AIzaSyBy9114j99nP1KuB4P_bAIrLhNR2JFiS8Y"
></script>
<script type="text/javascript">
var myAPIKey = 'YOUR-MAP-API-KEY-HERE';
var element = document.getElementById('map');
/*
Build list of map types.
You can also use var mapTypeIds = ["roadmap", "satellite", "hybrid", "terrain", "AccuTerra"]
but static list is dangerous because Google might update the default list of map types.
*/
var mapTypeIds = [];
for (var type in google.maps.MapTypeId) {
mapTypeIds.push(google.maps.MapTypeId[type]);
}
mapTypeIds.push('AccuTerra');
var map = new google.maps.Map(element, {
center: { lat: 39.6500327, lng: -105.0053989 },
zoom: 10,
mapTypeId: 'AccuTerra',
mapTypeControlOptions: {
mapTypeIds: mapTypeIds,
},
});
map.mapTypes.set(
'AccuTerra',
new google.maps.ImageMapType({
getTileUrl: function (coord, zoom) {
return `https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/${zoom}/${coord.x}/${coord.y}.jpg?key=${myAPIKey}`;
},
tileSize: new google.maps.Size(256, 256),
name: 'AccuTerra',
maxZoom: 18,
})
);
</script>
</body>
</html>
<html>
<head>
<meta charset="utf-8" />
<title>Display a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const myAPIKey = 'YOUR-MAP-API-KEY-HERE';
var map = new maplibregl.Map({
container: 'map', // container id
style: `https://maps.accuterra.com/v1/styles/accuterra-outdoors/style.json?key=${myAPIKey}`,
center: [0, 0], // starting position [lng, lat]
zoom: 1 // starting zoom
});
</script>
</body>
</html>
<head>
<title>Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossOrigin="" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossOrigin=""></script>
<style>
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
#map {
/* configure the size of the map */
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// initialize Leaflet
var map = L.map('map').setView({
lon: -105.00,
lat: 39.65
}, 10);
var myKey = "YOUR-MAP-API-KEY-HERE";
L.tileLayer(
`https://{s}.accuterra.com/v1/data/accuterra-outdoors-raster/{z}/{x}/{y}.jpg?key=${myKey}`, {
maxZoom: 16,
attribution: '© AccuTerra Maps',
subdomains: [
"maps-d1",
"maps-d2",
"maps-d3",
"maps-d4",
]
}).addTo(map);
</script>
</body>
</html>
<html>
<head>
<title>MapBox GL</title>
<script
type="text/javascript"
src="https://api.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.js"
></script>
<link
rel="stylesheet"
type="text/css"
href="https://api.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.css"
/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
#my-map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="my-map"></div>
<script type="text/javascript">
var myKey = 'YOUR-MAP-API-KEY-HERE';
var map = new mapboxgl.Map({
container: 'my-map',
style: `https://maps.accuterra.com/v1/styles/accuterra-outdoors/style.json?key=${myKey}`,
center: [-105.0, 39.65],
zoom: 10,
attributionControl: false,
}).addControl(
new mapboxgl.AttributionControl({
compact: false,
customAttribution: '© AccuTerra Maps',
})
);
map.addControl(new mapboxgl.NavigationControl());
</script>
</body>
</html>
<html>
<head>
<title>OpenLayers</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css"
type="text/css"
/>
<style type="text/css">
html,
body,
#my-map {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
<script
type="text/javascript"
src="https://unpkg.com/ol-mapbox-style@6.1.4/dist/olms.js"
></script>
</head>
<body>
<div id="my-map"></div>
<script type="text/javascript">
var myKey = 'YOUR-MAP-API-KEY-HERE';
olms(
'my-map',
`https://maps.accuterra.com/v1/styles/accuterra-outdoors/style.json?key=${myKey}`
).then((map) => {
let view = map.getView();
view.setCenter(ol.proj.fromLonLat([-105.0053989, 39.6500327]));
view.setZoom(10);
map.setView(view);
});
</script>
</body>
</html>
Mobile Code Samples
Accuterra Mapbox Android
package com.accuterra.arcgis_accuterra_maps_demo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.geometry.Point
import com.esri.arcgisruntime.geometry.SpatialReferences
import com.esri.arcgisruntime.layers.WebTiledLayer
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.Basemap
import com.esri.arcgisruntime.mapping.view.MapView
class MainActivity : AppCompatActivity() {
lateinit var mapView: MapView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Get reference to map view
mapView = findViewById(R.id.mapView)
// Visit https://accuterra.com and create your free account to get a map API key.
val accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
val url = "https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/{level}/{col}/{row}.jpg?key=$accuterraMapsKey"
val webTiledLayer = WebTiledLayer(url)
// Use web tiled layer as Basemap
val map = ArcGISMap(Basemap(webTiledLayer))
mapView.map = map
// Custom attributes
webTiledLayer.attribution = "Map tiles by AccuTerra Maps"
// Set custom view point
val point = Point(-104.861077, 39.375239, SpatialReferences.getWgs84())
mapView.setViewpointCenterAsync(point, 5000.0)
}
override fun onPause() {
super.onPause()
mapView.pause()
}
override fun onResume() {
super.onResume()
mapView.resume()
}
override fun onDestroy() {
super.onDestroy()
mapView.dispose()
}
}
import UIKit
import ArcGIS
class ViewController: UIViewController {
@IBOutlet weak var mapView: AGSMapView!
override func viewDidLoad() {
super.viewDidLoad()
title = "ArcGIS SDK with AccuTerra Maps"
// Visit https://accuterra.com and create your free account to get a map API key.
let accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
let url = "https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/{level}/{col}/{row}.jpg?key=\(accuterraMapsKey)"
let webTiledLayer = AGSWebTiledLayer(urlTemplate: url)
webTiledLayer.attribution = "Map tiles by AccuTerra Maps"
let basemap = AGSBasemap(baseLayer: webTiledLayer)
mapView.map = AGSMap(basemap: basemap)
let viewpoint = AGSViewpoint(latitude: 39.375239, longitude: -104.861077, scale: 6000)
mapView.setViewpoint(viewpoint)
}
}
package com.accuterra.google_maps_accuterra_maps_demo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.*
import java.net.MalformedURLException
import java.net.URL
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Visit https://accuterra.com and create your free account to get a map API key.
val accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
mMap.mapType = GoogleMap.MAP_TYPE_NONE
val tileProvider: TileProvider = object : UrlTileProvider(256, 256) {
override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
/* Define the URL pattern for the tile images */
val url = "https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/$zoom/$x/$y.jpg?key=$accuterraMapsKey"
return if (!checkTileExists(x, y, zoom)) {
null
} else try {
URL(url)
} catch (e: MalformedURLException) {
throw AssertionError(e)
}
}
/*
* Check that the tile server supports the requested x, y and zoom.
* Complete this stub according to the tile range you support.
* If you support a limited range of tiles at different zoom levels, then you
* need to define the supported x, y range at each zoom level.
*/
private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean {
val minZoom = 8
val maxZoom = 18
return zoom in minZoom..maxZoom
}
}
mMap.addTileOverlay(TileOverlayOptions().tileProvider(tileProvider))
val centerPoint = LatLng(39.375239, -104.861077)
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(centerPoint, 14f))
}
}
import UIKit
import GoogleMaps
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Visit https://accuterra.com and create your free account to get a map API key.
let accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
let camera = GMSCameraPosition.camera(withLatitude: 39.375239, longitude: -104.861077, zoom: 14.0)
let mapView = GMSMapView.map(withFrame: view.frame, camera: camera)
let urls: GMSTileURLConstructor = { (x, y, zoom) in
let url = "https://maps.accuterra.com/v1/data/accuterra-outdoors-raster/\(zoom)/\(x)/\(y).jpg?key=\(accuterraMapsKey)"
return URL(string: url)
}
let layer = GMSURLTileLayer(urlConstructor: urls)
layer.zIndex = 100
layer.map = mapView
view.addSubview(mapView)
}
}
package com.accuterra.mapbox_accuterra_maps_demo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.mapboxsdk.Mapbox
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMapOptions
class MainActivity : AppCompatActivity() {
private var mapView: MapView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Mapbox.getInstance(this, getString(R.string.mapbox_access_token))
val options = MapboxMapOptions.createFromAttributes(this, null)
.camera(
CameraPosition.Builder()
.target(LatLng(39.375239, -104.861077))
.zoom(14.0)
.build()
)
mapView = MapView(this, options)
mapView?.onCreate(savedInstanceState)
// Visit https://accuterra.com and create your free account to get a map API key.
val accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
mapView?.getMapAsync { mapboxMap ->
mapboxMap.setStyle("https://maps.accuterra.com/v1/styles/accuterra-outdoors/style.json?key=$accuterraMapsKey") {
// Map is set up and the style has loaded. Now you can add data or make other map adjustments.
}
}
setContentView(mapView)
}
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onResume() {
super.onResume()
mapView?.onResume()
}
override fun onPause() {
super.onPause()
mapView?.onPause()
}
override fun onStop() {
super.onStop()
mapView?.onStop()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView?.onSaveInstanceState(outState)
}
override fun onLowMemory() {
super.onLowMemory()
mapView?.onLowMemory()
}
override fun onDestroy() {
super.onDestroy()
mapView?.onDestroy()
}
}
import UIKit
import Mapbox
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Visit https://accuterra.com and create your free account to get a map API key.
let accuterraMapsKey = "YOUR-MAP-API-KEY-HERE"
let url = URL(string: "https://maps.accuterra.com/v1/styles/accuterra-outdoors/style.json?key=\(accuterraMapsKey)")
let mapView = MGLMapView(frame: view.bounds, styleURL: url)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.setCenter(CLLocationCoordinate2D(latitude: 39.375239, longitude: -104.861077), zoomLevel: 14, animated: false)
view.addSubview(mapView)
}
}