Guide

A Google Elevation API alternative

The Google Elevation API is easy to use but expensive at volume, and its terms restrict what you may do with the results. The overpass.ch elevation API takes the same requests and returns the same JSON, so switching is mostly a change of URL.

Replace the Google URL and key parameter with your overpass.ch URL. The locations, path and samples parameters and the response stay the same:
https://maps.googleapis.com/maps/api/elevation/json?locations=46.0207,7.7491&key=GOOGLE_KEY
→ https://api.overpass.ch/v1/YOUR_API_KEY/elevation?locations=46.0207,7.7491

The same request, the same answer

curl 'https://api.overpass.ch/v1/YOUR_API_KEY/elevation?locations=46.0207,7.7491|35.95,-5.6'
{
  "status": "OK",
  "results": [
    { "elevation": 1606.3, "location": { "lat": 46.0207, "lng": 7.7491 },
      "resolution": 90, "surface": "land", "dataset": "copernicus-glo90" },
    { "elevation": -678.3, "location": { "lat": 35.95, "lng": -5.6 },
      "resolution": 460, "surface": "sea", "dataset": "gebco-2026" }
  ],
  "lookups": 2
}
Google Elevation APIoverpass.ch
locations=lat,lng|…yesyes
Encoded polylines (enc:…)yesyes
path with samplesyesyes, and each result has its distance from the start
status, results[].elevation, location.lat/lng, resolutionyesyes
Locations per request512, GET only10'000 (1,000 on Free); GET, or POST with JSON or a GPX file
Route profile with ascent and descentno/elevation/profile
Land or sea in the answernosurface and dataset
ErrorsHTTP 200 with status such as INVALID_REQUESTHTTP status codes (400, 401, 429) with error and message

Code that checks status == "OK" and reads results still works. If your code branches on the Google error statuses, check the HTTP status code instead.

Switching your code

import os
import requests

URL = f"https://api.overpass.ch/v1/{os.environ['OVERPASS_CH_KEY']}/elevation"

def elevations(points):              # [(lat, lng), …]
    out = []
    for i in range(0, len(points), 1000):
        r = requests.post(URL, json={"locations": points[i:i + 1000]}, timeout=30)
        r.raise_for_status()
        out += [res["elevation"] for res in r.json()["results"]]
    return out

print(elevations([(46.0207, 7.7491), (45.9763, 7.6586)]))
  • The key goes into the path, or into an X-API-Key header, instead of key=.
  • Batches: you no longer need to split at 512 locations. Up to 1,000 fit into one request on the free plan, 10'000 on paid plans.
  • In the browser: the ElevationService of the Maps JavaScript API cannot be pointed at another server. Call the endpoint with fetch as above, with a key restricted to your own domain in the dashboard.

What it costs

Google bills per request, of up to 512 locations: 5,000 requests a month are free, then USD 5 per 1,000 up to 100,000 requests, with lower rates above. overpass.ch counts lookups, one per location, and the free plan includes 1 million a month.

Locations per monthIn batches of 512 or moreOne location per request
Googleoverpass.chGoogleoverpass.ch
1 millionfree (about 2,000 requests)Free plan, or Elevation for CHF 5about USD 3,575Elevation, CHF 5
10 millionabout USD 73Elevation, CHF 5about USD 11,500Medium, CHF 59
50 millionabout USD 465Elevation, CHF 5about USD 26,700Large, CHF 149

Google list prices for the Elevation API in October 2026: 5,000 free requests a month, then USD 5.00 per 1,000 up to 100,000, USD 4.00 to 500,000, USD 3.00 to 1 million, USD 1.50 to 5 million and USD 0.38 above. One location per request is the typical case of an app that looks up a point per click or per user. On overpass.ch that case is limited by requests per minute rather than by lookups: 120 a minute on the Elevation plan, 600 on Medium and 1200 on Large. Prices in CHF; the same amounts in EUR. The free plan is for evaluation and prototypes.

If you batch a few hundred thousand locations a month, the free allowance from Google may be enough. The costs differ for single-point lookups and at high volume.

Storing results and showing them on a map

  • Google: its Elevation API policies say content should not be pre-fetched, cached or stored, and results shown on a map must be shown on a Google Map. Without a map, you show the Google logo and attribution.
  • overpass.ch: you may store the results and show them on any map, for example OpenStreetMap with Leaflet or MapLibre. When you publish or display them, credit the data sources, as described in the documentation and the terms.

Resolution and accuracy

Land heights come from the Copernicus GLO-90 model, a worldwide grid with 90 m spacing; sea depths from the GEBCO grid (about 460 m). Google combines several sources and is often finer, especially in cities and in steep mountains. With 90 m data:

  • villages, valleys, roads and rolling terrain are typically within a few metres (Zermatt reads 1,606 m);
  • sharp summits read low: the Matterhorn 4,210 m instead of 4,478 m;
  • forests and large buildings are part of the surface.

It is a good fit for altitude bands, route profiles, enriching places and analysis over regions. For engineering, aviation or anything where a few metres matter, use a finer, local model. The Elevation API page has more measurements.