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.
map.setStyle("https://styles.maptoolkit.org/winter-3d.json");
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.
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.
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.
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.
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.
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.