Raster maps guide
A practical guide with examples: raster tiles with Leaflet and MapLibre, switching to the orthophoto, a WMTS connection in QGIS, and the EPSG:3301 layers with OpenLayers.
https://pump.elemroot.com (like the geoservices): not at
api.elemroot.com, which hosts the vector maps.
Authentication
Every request needs the key parameter and the key must include
the raster service. Without a key, or with an invalid one, the
service responds with 403 (body {"error":"invalid_api_key"}).
A key may be bound to an origin: then it only works from the allowed web page
(the browser sends Origin/Referer). The docs_โฆ key
used in the examples is a rate-limited demo key (too many requests โ 429); for your own application request a personal key.
curl -s -o tile.png \
'https://pump.elemroot.com/xyz/eestig/12/2329/1202.png?key=docs_382d376eaaa6d004b7b93b7d'
Layers and grids
| Layer | Contents | Grid | Format | Max zoom |
|---|---|---|---|---|
eestig | Elemroot map of Estonia | EPSG:3857 | png | 18 |
eestio3857 | Maa-amet orthophoto | EPSG:3857 | jpeg | 18 |
eesti | Elemroot map of Estonia | EPSG:3301 (L-EST97) | png | 18 |
eestio | Maa-amet orthophoto | EPSG:3301 (L-EST97) | jpeg | 15 |
Which grid should I pick? On the web use the EPSG:3857
layers (eestig, eestio3857); they use the
standard Web Mercator grid that Leaflet and MapLibre understand without
extra libraries. The EPSG:3301 layers use the Estonian national L-EST97
grid: you need them in GIS software (via WMTS) or when your application
works in L-EST97 coordinates; on the web they require OpenLayers + proj4 or
Leaflet + Proj4Leaflet (see below).
Quickstart: Leaflet
The simplest way to put a raster map on a page (working full example: Leaflet + EPSG:3301):
<div id="map" style="height: 400px"></div>
<script>
const map = L.map('map').setView([59.437, 24.7536], 12); // Tallinn
L.tileLayer('https://pump.elemroot.com/xyz/eestig/{z}/{x}/{y}.png?key=docs_382d376eaaa6d004b7b93b7d', {
maxZoom: 18,
attribution: 'ยฉ Elemroot'
}).addTo(map);
</script>
For the orthophoto switch the layer: eestio3857/{z}/{x}/{y}.jpeg
(attribution ยฉ Maa-amet).
MapLibre GL JS
In MapLibre raster tiles are a raster-type source. This works
well when you want to show the orthophoto next to (or under) the vector map:
const map = new maplibregl.Map({
container: 'map',
style: {
version: 8,
sources: {
orto: {
type: 'raster', tileSize: 256, maxzoom: 18,
tiles: ['https://pump.elemroot.com/xyz/eestio3857/{z}/{x}/{y}.jpeg?key=docs_382d376eaaa6d004b7b93b7d'],
attribution: 'ยฉ Maa-amet'
}
},
layers: [{ id: 'orto', type: 'raster', source: 'orto' }]
},
center: [24.7536, 59.4370],
zoom: 12
});
Live demo with a layer switcher (map โ orthophoto): the "Raster map with layer switcher" example.
WMTS and QGIS
WMTS is a self-describing standard: the capabilities document lists the layers, grids and tile URLs. Give your GIS software the capabilities URL with your key: the key is carried into the tile URLs automatically:
https://pump.elemroot.com/wmts/1.0.0/WMTSCapabilities.xml?key=docs_382d376eaaa6d004b7b93b7d
In QGIS:
- Layer โ Add Layer โ Add WMS/WMTS Layer โ New
- Paste the capabilities URL above (with your own key) into the URL field
- Connect: pick a layer (e.g.
eestiwith theest3301grid, oreestigwithwebmerc) โ Add
The EPSG:3301 layers arrive in QGIS in their native projection without reprojection; prefer them for an L-EST97 workflow.
The WMTS REST tile URL is /wmts/{layer}/{grid}/{z}/{x}/{y}.{ext}
(TileMatrix/TileCol/TileRow; in the capabilities the
TileMatrix IDs are zero-padded 00โฆ20, but a plain 6 works too).
Unlike the XYZ endpoint, the extension is mandatory here and must match the layer
format: .png for map layers, .jpeg for the orthophoto
(eestio, eestio3857). A wrong extension, wrong grid,
unknown layer or a tile outside the grid returns 400 with an OGC
ExceptionReport XML (InvalidParameterValue / TileOutOfRange).
The interface is REST-only (no KVP GetTile); the capabilities document carries the
key into the tile templates.
EPSG:3301 layers on the web (OpenLayers)
eesti and eestio live in the Estonian national
grid: bbox [-211000, 5732000, 1325000, 7268000], initial
resolution 6000 m/px, halving at every zoom level. XYZ axis order (row 0
is in the north). An OpenLayers + proj4 example (working full example:
OpenLayers + EPSG:3301;
the same grid with Leaflet: Leaflet
+ Proj4Leaflet):
proj4.defs('EPSG:3301',
'+proj=lcc +lat_1=59.33333333333334 +lat_2=58 +lat_0=57.51755393055556 ' +
'+lon_0=24 +x_0=500000 +y_0=6375000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
ol.proj.proj4.register(proj4);
const extent = [-211000, 5732000, 1325000, 7268000];
const resolutions = [];
for (let z = 0; z <= 18; z++) resolutions[z] = 6000 / Math.pow(2, z);
const map = new ol.Map({
target: 'map',
layers: [new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://pump.elemroot.com/xyz/eesti/{z}/{x}/{y}.png?key=docs_382d376eaaa6d004b7b93b7d',
projection: 'EPSG:3301',
tileGrid: new ol.tilegrid.TileGrid({
extent, resolutions, tileSize: 256,
origin: [extent[0], extent[3]] // NW corner = XYZ axis order
}),
attributions: 'ยฉ Elemroot'
})
})],
view: new ol.View({
projection: 'EPSG:3301',
center: [542000, 6589000], // Tallinn in L-EST97
resolution: 6000 / Math.pow(2, 12)
})
});
Parameters
* = required; the tables are generated from the OpenAPI YAML.
XYZ: /xyz/{layer}/{z}/{x}/{y}.png
| Param | Meaning | Allowed values / example | Default |
|---|---|---|---|
{layer} * | Layer | eestig, eestio3857 (EPSG:3857) ยท eesti, eestio (EPSG:3301); unknown โ 404 | โ |
{z} * | Zoom level (row 0 in the north) | 0โฆmax zoom (layer table; eestio 15, others 18) | โ |
{x} * | Tile column (XYZ) | integer; outside the grid โ 404 | โ |
{y} * | Tile row (XYZ, y grows southwards) | integer; outside the grid โ 404 | โ |
key * | API key (with the raster service); missing/invalid โ 403 JSON | docs_382d376eaaa6d004b7b93b7d (demo, rate-limited) | โ |
WMTS REST: /wmts/{layer}/{grid}/{z}/{x}/{y}.{ext}
| Param | Meaning | Allowed values / example | Default |
|---|---|---|---|
{layer} * | Layer | eestig, eestio3857 (grid webmerc) ยท eesti, eestio (grid est3301); unknown โ 400 | โ |
{grid} * | TileMatrixSet: must match the layer | webmerc or est3301; wrong โ 400 | โ |
{z} * | TileMatrix (zoom) | 6 or zero-padded 06 | โ |
{x} * | TileCol | integer; outside โ 400 TileOutOfRange | โ |
{y} * | TileRow (row 0 in the north) | integer; outside โ 400 TileOutOfRange | โ |
{ext} * | File extension: mandatory, must match the layer format | png (eestig, eesti) or jpeg (eestio3857, eestio); wrong โ 400 | โ |
key * | API key (with the raster service); missing/invalid โ 403 JSON | docs_382d376eaaa6d004b7b93b7d (demo, rate-limited) | โ |
When to use what
The most common tasks and the layer/endpoint for each. All rows are verified live.
| Task | Combination | Why |
|---|---|---|
| Map on a web page (Leaflet, MapLibre, OpenLayers) | /xyz/eestig/{z}/{x}/{y}.png?key=โฆ | standard Web Mercator, no extra libraries |
| Orthophoto on the web | /xyz/eestio3857/{z}/{x}/{y}.jpeg?key=โฆ | Maa-amet orthophoto in EPSG:3857, JPEG |
| Orthophoto under or next to the vector map | MapLibre raster source eestio3857 | see the MapLibre example |
| GIS software (QGIS etc.) | WMTS capabilities URL with your key | layers, grids and tile templates come automatically |
| L-EST97 application / EPSG:3301 grid | /xyz/eesti/โฆ or /xyz/eestio/โฆ + OpenLayers proj4 / Leaflet Proj4Leaflet | no reprojection |
| Sharp, styleable and lighter map | vector maps | raster only when you need the orthophoto, the L-EST97 grid or a client without WebGL |
.jpeg for the orthophoto).
(2) Row 0 is in the north and y grows southwards: also on the EPSG:3301 grid (the NW corner is the origin).
(3) The keyless 403 body is JSON although the Content-Type is the image type; don't parse the response by extension.
(4) Tiles come with a 7-day Cache-Control: map updates reach the browser with a delay.
Error handling
| Situation | Code | Message |
|---|---|---|
Key missing, invalid or without the raster service | 403 | JSON {"error":"invalid_api_key"} |
| XYZ: unknown layer | 404 | unknown layer: โฆ (text) |
| XYZ: tile outside the grid | 404 | The requested tile is outside the bounding box of the tile map. (text, not an image) |
| WMTS: wrong extension | 400 | OGC ExceptionReport invalid format (png). this tile set only supports (jpeg) |
WMTS: wrong grid / unknown layer | 400 | InvalidParameterValue: unknown tilematrixset โฆ / unknown layer โฆ |
| WMTS: tile outside the grid | 400 | TileOutOfRange |
| Too many requests (demo key) | 429 | Too Many Requests |
| Temporary source failure (e.g. the Maa-amet WMS not responding) | 500 | no image returned from source WMS โฆ; retry later |
Formats and notes
- On the XYZ endpoint the file extension is optional and not checked: the actual
format always comes from the layer (map layers PNG, orthophotos JPEG);
.png,.jpeg,.jpgor no extension all return the same tile. On the WMTS endpoint the extension is mandatory and must match the layer format (see WMTS). - Caching: tiles and the capabilities document come with
Cache-Control: max-age=604800(7 days),ETagandLast-Modified; clients may cache them for 7 days. - Attribution:
ยฉ Elemrootfor the Elemroot layers,ยฉ Maa-ametfor the Maa-amet layers. - Tiles are 256ร256 px.
- All responses carry the
Access-Control-Allow-Origin: *header; they also suit CORS-requiring clients (e.g. a MapLibre raster source). - For a sharper, styleable and lighter map see the Vector maps service; raster is the right choice when you need the orthophoto, the L-EST97 grid, or clients without WebGL.