Skip to content
From Mapbox

Migrate from Mapbox to Maptoolkit

Most of a Mapbox integration ports over. Maptoolkit serves the same kinds of things Mapbox does, in the same formats, to the same libraries, so the basemap is usually a style URL swap and the service APIs are a rewrite of request and response shapes rather than a rethink.

The two parts that are real work are replacing Mapbox GL JS with MapLibre GL JS, and anything built on Mapbox Studio or the Tilesets API. Both are covered below.

What maps to what

MapboxMaptoolkitWhat differs
Mapbox GL JSMaps JS or plain MapLibre GL JSMapLibre is the open fork of Mapbox GL JS v1, so most code is unchanged
Mapbox Streets vector tilesVector TilesDifferent schema. See the Schema Reference for layer and field names
Raster Tiles APIRaster TilesSame XYZ scheme
Static Images APIStatic Maps APIDifferent parameter names
Mapbox Terrain-RGBTerrain TilesTerrarium encoding, not terrain-rgb. See below
Directions APIRouting APICar, bike, foot and transit profiles
Isochrone APIIsochrone APISame idea, different response envelope
Matrix APIMatrix APITravel times and distances between origins and destinations
Geocoding APIGeocoding APIForward and reverse
Mobile SDKsMapLibre GL NativeOpen source, and the same style URLs work

Maptoolkit also has no Mapbox counterpart for two things you may want anyway: a Weather API, and Route Enhancement, which adds elevation profiles and surface tags to an existing track.

What does not map

Read this section before planning the work.

  • Mapbox Studio. There is no self-service visual style editor on a Maptoolkit account. Custom cartography is an Enterprise arrangement. If your product depends on end users designing their own styles, this is the blocker, not the tiles.
  • Tilesets API, Uploads API and Datasets API. There is no path for uploading your own data and having Maptoolkit serve it back as tiles. Your own data stays on your side, added to the map as GeoJSON or as your own tile source.
  • Navigation SDK. No Maptoolkit equivalent. The MapLibre Navigation SDK, itself a fork of Mapbox’s, works with Maptoolkit routes.
  • Optimization API. No equivalent. Vehicle routing and stop ordering are not offered.
  • Tilequery API. No equivalent. Query features from the rendered map on the client instead.
  • Boundaries, Movement and the other Mapbox data products. No equivalent.
  • Search Box and Places-style autocomplete. The Geocoding API resolves addresses and place names. It is not a drop-in replacement for a session-based autocomplete product.

The library change

There are three options, and only two of them actually leave Mapbox.

Move to Maps JS. This is the one to pick. Maps JS is MapLibre GL JS with the Maptoolkit services already wired in: the API key is a constructor option rather than a query string you thread through every URL, and the style switcher, terrain toggle, weather layers and isochrone control are controls rather than code you write. The class names and the whole style spec are unchanged from Mapbox GL JS v1, so the diff is the script tag, the token line and the style URL:

- <script src="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
- <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css" />
+ <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
+ <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
- mapboxgl.accessToken = "YOUR_MAPBOX_TOKEN";
- const map = new mapboxgl.Map({
+ const map = new maptoolkit.Map({
    container: "map",
+   apiKey: "YOUR_API_KEY",
-   style: "mapbox://styles/mapbox/streets-v12",
+   style: "https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=YOUR_API_KEY",
    center: [12.805988, 47.310897],
    zoom: 11
  });

Everything after those lines stays as it is. Map, Marker, Popup, LngLat, LngLatBounds, the camera methods, the event names and the expression syntax are all the same, and coordinates remain [longitude, latitude].

The migrated map, running, with the complete diff sits beside this guide: a Mapbox GL JS map with a marker, a popup, a GeoJSON line and a data-driven circle layer, ported over, with every changed line marked and the rest shown untouched.

Move to plain MapLibre GL JS. The community fork of Mapbox GL JS v1, BSD licensed, with no token and no per-load billing. The same diff applies with maplibregl in place of maptoolkit and no apiKey option, since the key then lives only in the style and tile URLs. Choose this when you are already committed to a MapLibre wrapper of your own, or want no Maptoolkit code in the bundle.

Keep Mapbox GL JS. Pointing the style URL at us is a quick way to prove the tiles work, but two things make this a test rather than a migration. Mapbox GL JS v2 and later is licensed by Mapbox and billed per map load, so you still need an access token and are still billed by Mapbox. And our styles do not load in it unpatched: sprite is an array, the MapLibre extension for several sprite sheets, and Mapbox GL JS rejects the style with Error: sprite: string expected, array found. See Mapbox GL JS for the workaround and what it costs.

What does not come across, whichever you pick:

  • Anything using a mapbox:// URL. Styles, sprites, glyphs and tile sources all need real HTTPS URLs.
  • Mapbox GL JS v2 and v3 additions that MapLibre does not implement, most visibly the Standard style with its lighting model, and Mapbox’s 3D building and landmark layers.
  • Custom layers written against the Mapbox v3 rendering internals.

Terrain, the one that silently renders noise

Mapbox encodes elevation as terrain-rgb. Maptoolkit uses Terrarium encoding. The source config is otherwise identical, so a copied Mapbox terrain block will load tiles, decode them with the wrong formula, and produce a landscape of noise rather than an error.

  map.addSource("terrain", {
    type: "raster-dem",
-   url: "mapbox://mapbox.mapbox-terrain-dem-v1",
-   encoding: "mapbox",
+   url: "https://tiles.maptoolkit.net/terrainrgb.json?api_key=YOUR_API_KEY",
+   encoding: "terrarium",
    tileSize: 256
  });
  map.setTerrain({ source: "terrain", exaggeration: 1.5 });

See Terrain Tiles for the zoom range and the full source config.

Style and schema

Maptoolkit styles are plain MapLibre style JSON served over HTTPS, so https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=YOUR_API_KEY goes straight into the style option. Seven styles ship: Summer, Winter, Hiking, Cycling, Street, Light and Dark.

If you wrote custom layers against Mapbox Streets, the source-layer names and the field names are different, and every one of those layers needs remapping. The Schema Reference lists every layer, field and allowed value. Budget real time for this if your map is heavily customised. It is usually the largest single item in a migration, and it is the one most often underestimated.

Vector tiles are 512px. Setting tileSize: 256 on the vector source produces rendering artifacts.

The service APIs

Directions to Routing, Isochrone to Isochrone, Matrix to Matrix and Geocoding to Geocoding are one-to-one in purpose. Request parameters and response shapes differ in every case, so treat each as a small rewrite rather than a URL swap, and read the reference for the one you are moving:

Coordinate order is longitude,latitude, the same as Mapbox, so that class of bug does not apply to this migration.

What bites on day one

  • Errors are text/plain. A missing key returns 403 Access denied!, an unrecognised key returns 403 Api-key not found!, and a key without access to that service returns 403 Api-key not authorized!. Mapbox returns JSON error bodies, so code that assumes JSON will throw on the first failure rather than report it.
  • There are no rate-limit headers. No RateLimit-*, no Retry-After. Quotas are monthly and tied to the plan rather than per second, so there is nothing to back off from at runtime.
  • Attribution is a license condition. Maptoolkit and OpenStreetMap stay visible. In MapLibre, AttributionControl defaults to compact: true, which collapses the credit behind a button as soon as the map is dragged. Set compact: false to keep it readable.
  • Billing is per request, not per map load. A Mapbox bill is dominated by map loads; a Maptoolkit bill is tiles plus API calls, metered separately. A like-for-like estimate needs your tile volume, which a map-load count does not give you.

Doing it in stages

  1. Get an API key and load one Maptoolkit style into your existing Mapbox GL JS map. Nothing else changes. This proves the tiles and the key.
  2. Replace mapbox-gl with maplibre-gl. Fix whatever depends on mapbox:// URLs and on v2 or v3 features. Drop the Mapbox token.
  3. Remap custom layers against the Maptoolkit schema.
  4. Move terrain, and switch the encoding to terrarium.
  5. Move the service APIs one at a time, keeping both providers live behind a flag.
  6. Check attribution renders on every map, at every breakpoint, after a drag.
  7. Watch the request counts for a full billing period before cancelling anything.

Pricing

Self-service plans are billed through RapidAPI. See RapidAPI for how to subscribe and authenticate. Plan allowances and prices are on the Maptoolkit pricing page. Enterprise customers call the native hosts with a Maptoolkit API key.

Tile requests and API requests are metered separately and at different rates, so a map-heavy application and an API-heavy one are budgeted differently.