Elevation API
Query terrain elevation (metres above sea level) for any coordinate or a batch of coordinates. Powered by the hillshading DEM source.
| Billing | 1 unit per request (single or batch, regardless of point count) |
| Plan | Paid plans only (Starter, Pro, Enterprise). Free-plan keys get 403. |
| Coverage | Matches the hillshading source — Europe, Oceania, and expanding |
Single coordinate
/elevation/{lat}/{lng}?apiKey=<key>| Parameter | Type | Description |
|---|---|---|
lat | float | Latitude (WGS 84) |
lng | float | Longitude (WGS 84) |
Example
/elevation/50.732669/14.984353?apiKey=<key>Response
{
"long": 14.984353,
"lat": 50.732669,
"elevation": 1008,
"z": 12,
"x": 2218,
"y": 1376,
"pixelX": 250,
"pixelY": 34
}| Field | Description |
|---|---|
elevation | Altitude in metres above sea level |
z, x, y | DEM tile coordinates that were sampled |
pixelX, pixelY | Pixel position within the sampled tile |
Returns 204 No Content (empty body) if the DEM has no data at that point.
Note: 204 No Content means the DEM has no data at that point (outside coverage), not an error.
Batch
Query multiple coordinates in a single request.
POST /elevation?apiKey=<key>
Content-Type: application/jsonRequest body:
{
"points": [
{ "lat": 50.732669, "lon": 14.984353, "z": 12 },
{ "lat": 50.0755, "lon": 14.4378, "z": 12 },
{ "lat": 49.1951, "lon": 16.6068, "z": 12 }
]
}| Field | Type | Description |
|---|---|---|
lat | float | Latitude (WGS 84) |
lon | float | Longitude (WGS 84) |
z | int | Required. DEM tile zoom to sample at — see What z does. Send 12. |
All three fields are required on every point, and the longitude field is lon, not lng. The Content-Type: application/json header is required too.
Response — a bare array of elevation values in input order (null where no data is available):
[1008, 247.20000000000073, 216.8000000000011]Values are floats and are not rounded — round client-side if you want whole metres.
Rejected request bodies all return 400 with a plain-text message:
| Body | Message |
|---|---|
[[50.0755, 14.4378]] | Missing or empty points array |
{"points": []} | Missing or empty points array |
a point using lng instead of lon | Invalid point at index 0: lon must be a finite number |
a point with no z | Invalid point at index 0: z must be a finite number |
A rejected request still costs 1 unit, so validate the body client-side.
What z does
z is the DEM tile zoom level used for the lookup, not a property of your coordinate. The server turns each point into a DEM tile plus one pixel inside it and reads the elevation from that pixel, so a higher z means a smaller patch of ground per pixel and a more precise answer.
z is clamped to the DEM’s zoom range (5–12), so values outside it are not an error — they behave as 5 or 12. One pixel covers roughly:
z | Ground resolution at 50° N |
|---|---|
| 5 | ~1,570 m |
| 8 | ~200 m |
| 10 | ~50 m |
| 12 | ~12 m |
The difference is real. Sampling Sněžka’s summit (1,603 m) at z=5 returns 1,299 m, at z=8 1,559 m, at z=10 1,597 m and at z=12 1,601 m. Values above 12 return exactly the same answer as 12.
Send z: 12. The only reason to go lower is throughput on a very dense track — points are grouped by tile, so a lower z fetches fewer tiles — and the accuracy cost above is usually not worth it.
Notes
- Coverage matches the hillshading source — not worldwide. Returns
204(single) ornullin the array (batch) for uncovered regions. - Resolution depends on the
zparameter —z=12gives the best available resolution (~12 m at Czech latitudes) - Coordinate order is always latitude, longitude in the URL; in the batch body the fields are named
latandlon - Batch bodies are capped at 1 MB. A larger body returns
413and is not billed