With out geom;, every point in the geometry of a way gets its own elevation. For a lift, the first and last points are the two stations, so their difference is its vertical rise.
This query finds the aerial lifts around Zermatt. The table sorts them by vertical rise.
The query
[out:json][timeout:25]; way["aerialway"~"^(cable_car|gondola|chair_lift|mixed_lift|drag_lift|t-bar)$"](45.93,7.65,46.05,7.82); out geom;
Run it
Live result from overpass.ch, cached for up to 12 hours. Map data © OpenStreetMap contributors (ODbL). Heights produced using Copernicus WorldDEM™-90 © DLR e.V. 2010-2014 and © Airbus Defence and Space GmbH 2014-2018 provided under COPERNICUS by the European Union and ESA; all rights reserved. Sea depths: GEBCO Compilation Group (2026) GEBCO 2026 Grid.
How it works
- The regular expression matches the common kinds of lifts. Stations (
aerialway=station) and pylons are separate features and are left out. out geom;returns the line of each lift, andelevation=1adds a height to each of its points.- Lifts are usually drawn uphill, but not always: the Glacier Ride here starts at the top. Take the difference between the end points without its sign.
- The largest rise in the area is Furi – Trockener Steg, about 1,060 m.
Variations
- Many lifts also carry
aerialway:capacity(people per hour) andaerialway:duration(minutes). - All lifts, drawn without heights: ski lifts and cable cars.
Run it from your code
The query is unchanged; elevation=1 in the URL adds the heights. Each height uses one lookup from your elevation allowance.
curl 'https://api.overpass.ch/v1/YOUR_API_KEY/interpreter?elevation=1' \
--data-urlencode 'data@query.overpassql'
import requests
query = open("query.overpassql").read()
r = requests.post("https://api.overpass.ch/v1/YOUR_API_KEY/interpreter",
params={"elevation": 1}, data={"data": query}, timeout=120)
r.raise_for_status()
for el in r.json()["elements"]:
if "geometry" in el: # lines: a height for every point
first, last = el["geometry"][0]["elevation"], el["geometry"][-1]["elevation"]
print(el["tags"].get("name"), first, last, abs(last - first))
const res = await fetch("https://api.overpass.ch/v1/YOUR_API_KEY/interpreter?elevation=1", {
method: "POST",
body: new URLSearchParams({ data: query }),
});
if (!res.ok) throw new Error(await res.text());
const { elements } = await res.json();
for (const el of elements.filter((e) => e.geometry)) {
const [first, last] = [el.geometry[0].elevation, el.geometry.at(-1).elevation];
console.log(el.tags?.name, first, last, Math.abs(last - first));
}
Save the query as query.overpassql. It works the same in Overpass Turbo, QGIS and JOSM.