Sending a query
Post the query as data to https://geo.runningcat.dev/v1/overpass/interpreter with your key.
Python
import requests
query = """
[out:json][timeout:25];
node["amenity"="drinking_water"](around:2000,46.204,6.143);
out center;
"""
answer = requests.post(
"https://geo.runningcat.dev/v1/overpass/interpreter",
data={"data": query},
headers={"Authorization": "Bearer YOUR_KEY"},
timeout=60,
)
answer.raise_for_status()
for element in answer.json()["elements"]:
print(element["id"], element.get("tags", {}).get("name"))
JavaScript
const query = `[out:json];
node["amenity"="cafe"](50.05,19.92,50.07,19.96);
out;`
const answer = await fetch('https://geo.runningcat.dev/v1/overpass/interpreter', {
method: 'POST',
headers: { Authorization: 'Bearer YOUR_KEY' },
body: new URLSearchParams({ data: query }),
})
const { elements } = await answer.json()
A client that cannot send headers can put the key in the address: /v1/overpass/interpreter?key=YOUR_KEY.
Around a point
Drinking water within 2 km of Geneva station: 185 fountains in under 2 seconds. With nwr instead of node, out center gives fountains mapped as areas a single point too.
[out:json][timeout:25];
node["amenity"="drinking_water"](around:2000,46.204,6.143);
out center;
In a box
Cafés in central Kraków. The box is south, west, north, east, as in Overpass. 234 cafés in under half a second.
[out:json];
node["amenity"="cafe"](50.05,19.92,50.07,19.96);
out;
The [bbox] setting applies one box to every query in the script; here it counts picnic tables instead of listing them.
[out:json][bbox:50.0,19.8,50.1,20.1];
node["leisure"="picnic_table"];
out count;
Inside a city or a park
area[...] finds an administrative boundary or a protected area by its tags, and (area.name) keeps what lies inside it. Bakeries inside the city of Kraków: 408 shops in about 3 seconds.
[out:json][timeout:60];
area["name"="Kraków"]["admin_level"="8"]->.city;
nwr["shop"="bakery"](area.city);
out center;
Adding admin_level or boundary=protected_area to the area filter makes the lookup faster. Area ids work too: 3600000000 plus a relation id, or 2400000000 plus a way id.
To go the other way and ask which boundaries contain a point:
[out:json];
is_in(46.204,6.143);
out tags;
Along a line
around with several coordinate pairs measures the distance to the line through them. Toilets and drinking water within 300 m of a ride from Geneva to Chamonix, in one union:
[out:json];
(
node["amenity"="toilets"](around:300,46.204,6.143,46.07,6.40,45.924,6.869);
node["amenity"="drinking_water"](around:300,46.204,6.143,46.07,6.40,45.924,6.869);
);
out;
For a long recorded route, the POI along a route endpoint takes the GeoJSON line and returns each stop with its kilometre.
Route relations with geometry
Hiking routes in the Chamonix valley, the first three with their geometry. Each member is a way that carries its geometry, so you can draw the route without fetching nodes.
[out:json];
rel["route"="hiking"](45.85,6.8,46.0,6.95);
out geom 3;
Regular expressions
Names starting with "saint" in any case, with ,i:
[out:json];
nwr["name"~"^saint",i]["amenity"="place_of_worship"](45.85,6.8,46.0,6.95);
out center;
Named sets
A query can save its result with ->.name, and the next query can filter that set. A set on its own inside a union, such as (.a; .b;);, is not supported; put the two queries in the union instead.
[out:json];
node["amenity"="bicycle_parking"](46.19,6.12,46.22,6.16)->.parking;
node.parking["covered"="yes"];
out;
Places open at a given time
Add open_at to the address as a local date and time, YYYY-MM-DDTHH:MM in each place's own time zone, and the answer keeps only the places whose opening_hours tag says they are open then. This is not part of Overpass. Bakeries in Vienna open at 06:59 on a Tuesday, which is how to ask for the ones that open before 7:
POST /v1/overpass/interpreter?open_at=2026-11-10T06:59
[out:json][timeout:60];
area["name"="Wien"]["admin_level"="4"]->.city;
nwr["shop"="bakery"](area.city);
out center;
Places without an opening_hours tag, or with one that cannot be read, are left out. The open_at object in the answer counts the places that were open, closed and unknown, so you can see how many had no hours. Rules for public and school holidays (PH, SH) are read without the holidays.
When a query is refused
A query the endpoint cannot answer gets status 400 and a remark that names the reason, for example static error: line 3: recursion ">" is not supported: ways come without their nodes; use out geom or out center. A query that runs longer than 30 seconds, or would return more elements than the plan allows (10,000 on Free, 25,000 on Developer, 50,000 on Pro), gets status 200 with no elements and a runtime error: remark, as Overpass sends. The guide to Overpass errors covers 429 and 504.