3D maps

3D terrain in one URL, buildings in the Street style

Add -3d to any style name and the map has terrain, configured against a global elevation model. Street already draws buildings in 3D. No API key, no sign-up.

The Matterhorn rendered in 3D on the Winter style, labelled at 4478 metres: its pyramid rising in the centre of the frame with the Matterhorngletscher below and the Aosta valley receding to the horizon behind.
map.setStyle("https://styles.maptoolkit.org/winter-3d.json");
Terrain

One suffix, and the map has relief

All seven styles have a -3d variant. The variant carries its own raster-dem source and sets it as the map terrain, so there is nothing to add on your side beyond a camera pitch to look across it.

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://styles.maptoolkit.org/winter-3d.json', // 👈 -3d
  center: [7.6586, 45.9763],
  zoom: 11.8,
  pitch: 70,
  bearing: 180,
  maxPitch: 85, // the default caps pitch at 60
  // Required: the copyright line must stay visible, and the compact
  // control collapses it behind a button on narrow screens.
  attributionControl: { compact: false }
});

Every style, not a separate product

summer-3d, winter-3d, hiking-3d, cycling-3d, street-3d, light-3d and dark-3d. Same cartography, same tiles, terrain added.

A global elevation model

512 px WebP tiles in terrarium encoding, from Copernicus DEM worldwide with higher-resolution national models where they are published openly. The exaggeration is set to 1, so the relief is true to life.

Relief without the terrain mesh

The flat styles already draw hillshading and contour lines from the same elevation data. Hiking and Winter use four hillshade passes, the others one. You get mountains that read as mountains before turning any 3D on.

Every map using these tiles keeps the Maptoolkit logo and the copyright line visible. The attribution guide covers the exact requirement and the drop-in plugins for MapLibre and Leaflet.

Buildings

Street draws buildings in 3D already

The Street style ships a fill-extrusion layer from zoom 14, driven by the height and min_height attributes in the tiles. Pitch the camera and the city stands up.

Central London rendered with extruded buildings on the Street style: County Hall and the South Bank blocks standing up at varying heights, the London Eye extruded as a curved structure, Westminster and Waterloo bridges crossing the Thames, seen at a steep camera pitch.

The other six styles draw buildings flat. Adding the extrusion is one layer, and the attributes are already in the tiles: height, min_height, an extrude flag, colour_index for varying the fill, and roof shape, angle, orientation, material, colour and levels.

map.addLayer({
  id: 'buildings-3d',
  type: 'fill-extrusion',
  source: 'mtk',
  'source-layer': 'building',
  minzoom: 14,
  // Not every footprint is meant to stand up: building parts carry
  // extrude=false, and the Street style filters on the same flag.
  filter: ['==', ['get', 'extrude'], true],
  paint: {
    'fill-extrusion-color': '#cfd8dc',
    'fill-extrusion-height': ['get', 'height'],
    'fill-extrusion-base': ['get', 'min_height'],
    'fill-extrusion-opacity': 0.9
  }
});

The complete runnable example also inserts the layer below the labels, so place names stay readable at pitch. For the mobile SDKs and deck.gl, the support matrix lists what each library can and cannot do.

MapMaker

Recolour the skyline

Open the Street style in MapMaker and change the building fill, the roof treatment or the whole palette. Relief Settings control the terrain and hillshading, and Map Settings covers 3D views and lights. Easy Mode needs no JSON at all, Expert Mode opens the style code directly. In our opinion MapMaker is among the best map style editors available right now, and it is free to use with these tiles.

The Street style open in MapMaker, showing the style editor beside a central London view.
Questions

Frequently asked questions about 3D maps

Does turning terrain on cost extra tile requests?

Less than you would expect. Every style already fetches the elevation model for its hillshading, including the flat ones, so switching to a -3d variant does not add a new host or a new source. What it adds is the terrain mesh built from tiles you were largely requesting anyway.

Can I change the terrain exaggeration?

Yes. The -3d styles set an exaggeration of 1, which is true to life. Call map.setTerrain with the same source name, rgb-tiles, and your own value to push it further. Anything much above 1.5 starts to look like a relief model rather than a landscape.

Why is my terrain flat with nothing in the console?

An older client skips a layer type it does not understand instead of throwing, so you get a map that renders correctly and simply has no relief, with no error to chase. Check the SDK version first. MapLibre GL JS needs 5.6.0 or newer for the elevation shading, and MapLibre Native does not implement terrain at all: setTerrain raises an UnsupportedError there, which also covers the Flutter and React Native wrappers.

Can I combine 3D with a language version?

No. There is no combined form: summer-3d-en.json and summer-en-3d.json both return 404. The -3d variants are built on the base styles only, so it is either localised labels or terrain. If you need both, start from a -3d style and override the label layers yourself, or host your own style JSON.

How high does the building data go?

The building layer runs from zoom 13 to zoom 15, and 15 is the maximum zoom of the whole tileset. Past that the tiles overzoom, so the extrusions stay sharp and no new footprints arrive. For city and district views that is enough; for anything needing individual parcels it is not.

Can I read heights out of the terrain tiles for calculations?

Technically yes, they are terrarium-encoded so the maths is documented, but it is the wrong tool. Decoding tiles client side to sample elevation is slow and imprecise at the zooms you will have loaded. Elevation per coordinate is the Elevation API on maptoolkit.com, a separate paid service.

Do I get 3D buildings on the other styles?

Only Street ships the extrusion layer. Summer, Winter, Hiking, Cycling, Light and Dark draw buildings flat, and adding them is one fill-extrusion layer using the height and min_height attributes already in the tiles. Filter on the extrude flag, which is what Street itself filters on.

What are the rate limits?

Unregistered traffic gets 120 tiles per second sustained and 200 in burst per website, with a 40 tiles per second cap per visitor IP. Cached tiles do not count, and the edge cache absorbs most requests. There is no SLA on the community service, so it is not the right choice behind anything life-safety or billing-critical.

More styles

The rest of the range

Hiking maps

Waymarked route shields, SAC and via ferrata grades, nine path layers and four hillshade passes.

Cycling maps

Numbered node networks, separated cycleways, on-road lanes and MTB trails on their own layers.

Ski and winter maps

Colour-coded piste difficulty, nordic trails, eight lift types and run numbers.