Elevation API for points, routes and areas

Heights above sea level for one point, for up to 10,000 points at once, as a profile along a route with its total climb, or as a grid over a box. Terrain tiles for 3D maps come from the same data.

curl "https://geo.runningcat.dev/v1/elevation?lon=6.869&lat=45.924" -H "Authorization: Bearer YOUR_KEY"
{"ele": 1036.9}

curl https://geo.runningcat.dev/v1/elevation -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"points": [[6.869, 45.924], [6.143, 46.204]]}'
{"elevations": [1036.9, 375.1]}
Example request

One point or many

Heights are in metres. A batch takes up to 10,000 points and counts as one request.

Elevation profile of a route

POST /v1/route/profile takes a GeoJSON route and samples it every stepM metres (10 to 1,000; by default about 2,000 samples). The total climb is worked out after smoothing the heights over about 100 m, so the noise of a terrain model does not add up to climbing that is not there. On bridges and in tunnels the heights follow the road rather than the valley below or the mountain above, and the answer lists those stretches; send "heights": "terrain" for the ground under every point. A profile has at most 5,000 samples, so on long routes the step grows past the one asked for. For a recorded track, "at": "points" gives a height at each of its own points instead, up to 50,000, and keeps the track's distances. Each bridge and tunnel comes with its clearance where OpenStreetMap has it, and POST /v1/route/surfaces lists every height limit along a track, passages under bridges included.

{
  "routeLengthKm": 86.311, "stepM": 500,
  "ascentM": 1020, "descentM": 358, "minM": 374.5, "maxM": 1109.4,
  "profile": [
    { "km": 0,   "lon": 6.143006, "lat": 46.204,    "ele": 375.1 },
    { "km": 0.5, "lon": 6.148751, "lat": 46.202742, "ele": 374.5 },
    ...
  ]
}

That is a road ride from Geneva to Chamonix. The profile also comes with POST /v1/route/report, together with the weather along the route and the time zones it crosses.

A grid over an area

GET /v1/area?bbox=west,south,east,north&include=elevation&cells=400 returns the height at the centre of each cell of a grid of up to 400 cells, row by row from the north-west corner, on the same grid as the weather and air quality of that area.

{ "rows": 2, "cols": 2, "lon": [6.8375, 6.9125], "lat": [45.9625, 45.8875],
  "elevation": { "values": [2145.8, 1237.3, 1426.5, 3257.8] } }

Terrain tiles

Tiles for hillshading and 3D terrain are at /v1/dem/{z}/{x}/{y}.png (256 px, Terrarium encoding, zoom 0 to 13) and .webp (512 px, zoom 0 to 12). They load as plain images in MapLibre and similar libraries, under any base map style: base map tiles, styles and fonts are not part of the API. Every 50 tiles count as one request, and tiles do not take one of your at-once slots.

Price

The free plan gives 500 requests a day, also for commercial apps; Developer is $14.99 a month for 5,000 a day. Map data, weather, air quality, river levels and routing are on the same key.

Credits: terrain from Mapterhorn.

The free plan gives 500 requests a day, for commercial apps too. Create an account with Google or your email and make your keys right away.