The Overpass API offers a variety of search possibilities. This is also known as querying. The results of those searches or queries can be displayed directly on a map, but it is also possible to retrieve only the data. On this page we will focus on examples that have to be displayed on a map. This means that all queries can be inserted in the code editor of Overpass turbo. From there the query can be executed and the result will be shown on a map.

Simply click on the Icon next to each query to try it in overpass turbo!

Introduction

The simplest way to get started with Overpass API is to use Taginfo and to navigate to the tag you are interested in.
Take post boxes as an example.
Push the Overpass Turbo button there in the upper right.
This will start the Overpass Turbo user interface and produce the following query

/*This query looks for nodes, ways and relations with the given key/value combination.Choose your region and hit the Run button above!*/[out:json][timeout:25];// gather results(// query part for: “amenity=post_box”node["amenity"="post_box"]({{bbox}});way["amenity"="post_box"]({{bbox}});relation["amenity"="post_box"]({{bbox}}););// print resultsoutbody;>;outskelqt;

The Overpass Turbo user interface has a lot of capabilities.
For the moment it should suffice that you have in the upper left corner of the map view a textfield.
Type in your favorite location.
It will then, with the use of Nominatim move the map view to that location.
Type in e.g. Manhattan and choose the first hit.
The map then jumps to the upper end of the Central Park in Manhattan.
Zoom out two levels to see some of the built area.
Run the query by hitting Run.

The Taginfo Example

Now we can start to understand the query.

Most of the previous query are comments - everything after // and between /* and */.
Hence, a more concise variant of the query is

And we can remove most of the cryptic syntax that mostly tells what to do with ways and relations.
We can get the same result as before with only two lines.

node["amenity"="post_box"]({{bbox}};out;

All these steps work with an tag from Taginfo.
There is no magic involved.
It just replaces amenity = post_box with the respective value.

Some Standard Features

Now what about the extra syntax?
Let us review them bit by bit.
To see an effect, we switch to query for restaurants instead of post boxes,
because then you can see the effect in adding support for ways.

node["amenity"="restaurant"]({{bbox}});out;

Not all restaurants are mapped as nodes.
Hence we want to search for ways and relations too:

way["amenity"="restaurant"]({{bbox}});out;

Running this query will result in a message that geometry is missing.
This is because the OpenStreetMap data model does not directly associate coordinates to ways and relations.
Ways and relations instead get their geometry by resolving their node references.

The out statment has various modes to address this problem in a more convenient way:
You can choose for example out geom to let Overpass API resolve the coordinates for you.
Or you use out center to collapse the geometry to a single coordinate per object:

way["amenity"="restaurant"]({{bbox}});outcenter;

We can put all these requests simply one after another.
Then we get the results one after another
and Overpass Turbo displays them all at once.

The Taginfo generated queries use instead the sequence out body, >, out skel qt.
This is merely for historical reasons.
This does essentially the same as out geom but delivers elements strictly from the OpenStreetMap data model.
Overpass Turbo nowadays can directly process the results of out geom and out center
and the delivered raw data is more concise.

This still has the same result as before.
But we have brought the bounding box to a single place in the beginning of the query.
An important reason to do so is that you should develop the habit of having always a bounding box
unless you really want results from all over the planet.

The Taginfo generated query also uses two other global settings:
The first is [out:json].
This might be an advantage if you want to directly read the returned data.
You can do so on the Data tab over the map view.

The second one is [timeout:25].
This limits the runtime of the query to 25 seconds.
If something goes wrong then the limit assures that neither the server nor you waste time.
Like the Global Bounding Box it is a useful precaution.

Understanding Data

This section is about queries that answer the question whether specific data situations exist.

There is no sharp boundary to the Building Blocks section below.
The general criterion is that the examples here are from a geographic point of view,
but the Building Blocks are from a database point of view and may be purely technical criteria.

The difference to Quality Assurance is that the queries here usually have valid results,
whereas results of Quality Assurance queries usually need to be fixed one way or another.

Tagging

To make sense, an OpenStreetMap object always needs to have a type.
Usually, humans need in addtion a handle to refer to such an object
- this is what is called a name.
With respect to KISS, this handle is almost always in the name tag.
But sometimes there is a valid reason to have it in another tag like ref or name:fr.

One of the standard assumptions when dealing with OpenStreetMap data is
that named objects have a type.
This is opposed to unnamed elements of the OpenStreetMap database.
They may be part of another object and then do not constitute an object on their own.

Conversely, at least certain types of objects always have names - there is no unnamed museum.
However, is there no unnamed bus service?
Has every restaurant a name?

Tagged Nodes

The following query returns all nodes in the current bbox having at least one tag:

Nodes with exactly one specific tag

The aim of the following query is to find out all nodes with a specific tag and no other tag.

Since 0.7.54 you can use a filter expression:

node({{bbox}})[name](if:count_tags()==1);outgeom;

Please replace the name with whatever tag may fit your needs.
The pitfall of this approach is that you will not find objects that have a meaningless second tag.
If you want to do so then you should filter out all acceptable tags.
A simple example is in the Building Blocks.
More examples are in the Overpass API dev blog.

Count Pharmacies per County (updated 0.7.54)

The following example returns the number of pharmacies per county with regional key starting with "057". The output is in CSV format.

/* CSV-Format: To load the query results in LibreOffice, click on "Export" -> "Open Raw Data directly from Overpass API" in overpass turbo. Fields are tab-separated.*/// Define fields for csv output[out:csv(::type,"de:regionalschluessel",name,::count,::"count:nodes",::"count:ways",::"count:relations")];//All areas with regional key (German: "Regionalschlüssel") starting with 057area["de:regionalschluessel"~"^057"];// Count the pharmacies in each areaforeach->.regio(// display details for the current area.regioout;// Collect all Nodes, Ways and Relations with amenity=pharmacy in the current area(node(area.regio)[amenity=pharmacy];way(area.regio)[amenity=pharmacy];rel(area.regio)[amenity=pharmacy];);// Count the elements in the current area Area outcount;);

Since 0.7.54 we can merge the two separate lines for the area and statistical counts into a single line:

[out:csv("de:regionalschluessel",name,total,nodes,ways,relations)];//All areas with regional key (German: "Regionalschlüssel") starting with 057area["de:regionalschluessel"~"^057.*"];// Count the pharmacies in each areaforeach->.regio(// Collect all Nodes, Ways and Relations wth amenity=pharmacy in the current area(node(area.regio)[amenity=pharmacy];way(area.regio)[amenity=pharmacy];rel(area.regio)[amenity=pharmacy];);makecount"de:regionalschluessel"=regio.set(t["de:regionalschluessel"]),name=regio.set(t["name"]),total=count(nodes)+count(ways)+count(relations),nodes=count(nodes),ways=count(ways),relations=count(relations);out;);

Count number of addr:housenumber in an area

The following query counts the number of addr:housenumber=* nodes/ways/relations in an area. Duplicate addresses (i.e. multiple occurrences of the same address) are not filtered out. The query result is in csv format starting with the total number of addresses, followed by the number of nodes, ways and finally relations.

Find relations with identical wikidata tags (since 0.7.54)

The following query determines all relations with admin_level=2 and wikidata=* tag, where the same wikidata value is used across several relations.
As an example relations 1111111 is tagged as wikidata=Q183, which is also the case for relations 51477 and 62781.

<?xml version="1.0" encoding="UTF-8"?><osmversion="0.6"generator="Overpass API"><note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note><metaosm_base="2017-03-29T19:04:03Z"/><relid="11980"><tagk="wikidata"v="Q142"/><tagk="all_relation_ids"v="11980;2202162"/></rel><relid="36990"><tagk="wikidata"v="Q235"/><tagk="all_relation_ids"v="1124039;36990"/></rel><relid="51477"><tagk="wikidata"v="Q183"/><tagk="all_relation_ids"v="1111111;51477;62781"/></rel><relid="87565"><tagk="wikidata"v="Q258"/><tagk="all_relation_ids"v="1252792;87565"/></rel></osm>

To speed up processing, an alternative approach is to export relevant fields relation id and wikidata in CSV format and post-process the file via some shell script or similar:

[out:csv(wikidata,::id;false;";")];rel[admin_level][wikidata];out;

Find deviating tagging

I'd like to find Objects where certain Keys have the same value. Irish streets normally have two names, one in Irish and one in English. In osm the have three tags for that, name, name:en and name:ga. I'd like to find all objects having all three tags where name doesn't match with name:en or name:ga.

Find wikidata relations having identical wikidata way members

The following query find all wikidata relations in the current bounding box, and both the relation and the way member share the same wikidata id.

rel[wikidata]({{bbox}});// get all relations with wikidata tag in current bounding boxway(r)[wikidata]->.all;// get all way members with wikidata tagforeach->.rel(// process each relation one by one// find out all way members where the wikidata tag matches the relation's wikidata tagway.all(r.rel)(if:t["wikidata"]==rel.u(t["wikidata"]))->.ways;// if some way members could be found, print the current relation first...rel.rel(if:ways.count(ways)>0);outcenter;// ... followed by all ways with matching wikidata tag.waysouttags;);

Multipolygons with inappropiate member roles

The following query can be used to identify all multipolygon relations in the current bounding box, where not all of their members have an inner or outer role.

Complex Situations of Tagging and Geometry

Highway around schools with inappropriate maxspeed (since 0.7.54)

// see: http://blattspinat.com/index.php/posts/tempo-50-vor-schulen[out:json][timeout:800];// Get all schools in current bounding box(way[amenity=school]({{bbox}});node[amenity=school]({{bbox}});rel[amenity=school]({{bbox}});)->.schools;// find highway=* around schools with radius 50m, ignoring// footway and paths. In addition, highways are relevant if they // either// (1) have no maxspeed tag at all// (2) maxspeed tag indicates a value larger than 30 km/hway(around.schools:50)[highway][highway!~"^(footway|path)$"](if:(is_number(t[maxspeed])&&t[maxspeed]>30)||!is_tag(maxspeed))->.streets;// get schools in 50m distance for all identified relevant streets(node.schools(around.streets:50);way.schools(around.streets:50);rel.schools(around.streets:50);)->.matchingSchools;// return results, schools and streets(.matchingSchools;.streets;);outgeom;

Banks far away from police stations

Find banks where the closest police station is more than 3km away.

[out:json][bbox:{{bbox}}][timeout:800];// determine set of police stations(node[amenity=police];way[amenity=police];rel[amenity=police];)->.polices;// put them into the set "polices"// determine set of banks(node[amenity=bank];way[amenity=bank];rel[amenity=bank];)->.banks;// put them into the set "banks"// determine set of banks near police stations(node.banks(around.polices:3000);way.banks(around.polices:3000);rel.banks(around.polices:3000);)->.banksNearPolices;// put them into the set "banksNearPolices"// determine banks far from police stations(.banks;-.banksNearPolices;);// return node, ways, relations as determined aboveoutgeommeta;

City limit street signs

Tag:traffic_sign=city_limit recommends to put a traffic_sign=city_limit node on the highway (rather than somewhere next to it). The following query identifies those standalone nodes, excluding those nodes which are in close proximity to an already correctly mapped city_limit node.

Users and Museum Data

Find newbies mapping railway signals

Task: Find all unknown newbies in an area who have started mapping railway signals railway=signal after a point in time. If needed, help them with JOSM templates, etc.

node[railway=signal](newer:"2017-01-01T07:00:00Z")// adjust date as needed({{bbox}})->.newnodes;// List all well-known power users here, which should be excluded from the result list:(.newnodes;-node.newnodes(user:Nakaner,"Nakaner-repair",bigbug21,mapper999);)->.newnodes;// Output.newnodesoutmeta;

This query has a few shortcomings:

Only last-changed timestamp of a node is taken into account. A non-railway mapper moving a railway=signal node would trigger false positives.

The list of power users needs to be manually adjusted until the number of false positives is small enough.

OSM data at a certain date

The "date" parameter can be used to retrieve OSM objects as they were on a particular date, for example:

[date:"2014-05-06T00:00:00Z"];(node({{bbox}});<;>;);outmeta;

This somewhat famous attempt of 2.5D modeling was reverted fairly quickly.

Exporting Data

Exporting Data has its own special requirements.
As opposed to simply viewing data, it may make sense to have quite large amounts of data.
There are some special precautions you should take in that case
to be efficient with the resources of the public server.
The second subject specific to data export is formatting the output in something different than the usual OSM XML.

List of streets

The following query allows you to compile a complete list of all street names in a town. The example is made for Troisdorf:

This gives all the Ways inside this town, including ways that cross the town boundary. It cannot be avoided, but luckily it does not occur that often. The Nodes of the ways are not returned.

One only has to remove duplicates from this list, this can easily be done with

sortliste.csv|uniq

one can extract the list of street names.

In many cases, the boundary of a town has a different name than the city itself. This leads to empty results.E.g. Eckernförde requires the suffix "Landmasse" . The problem can be solved in general by using a regular expression

Adding geocoding details to POIs

Original question on help.openstreetmap.org:

I have a Overpass API query which returns lot of nodes. I would like to know whether there is a way to add reverse geocoding information to the resulting data set. Details of my case are not that important, but just for completeness:

area[name="Česko"];node[information="guidepost"](area);out;

In fact I do not need full reverse geocoding info for nodes, I only need relation of certain administrative level, so if this is possible to add into the result set, it would be great.

Solution:

area[name="Česko"];node[information="guidepost"][ele~"^2..$"](area)->.posts;// You can remove "ele".// It has been added to experiment with a fewer number of resultsforeach.posts(out;is_in;area._[admin_level~"[46]"];// The choice of "[46]" is arbitrary and could be anything else.// In this case, admin_level=4 are counties and admin_level=6 are cities,// which might be handy.outids;);// collect area details in 2nd step.postsis_in;area._[admin_level~"[46]"];out;

To avoid repeating full area details for each information=guidepost, the query uses the following alternative approach: for each guidepost, we will only print the osm id for the area, but nothing else. Only towards the end of the query, the full details for all relevant areas are returned.

Here's a brief example on how the format looks like: a POI (node 691566183) is followed by two area ids (3600435511 and 3600442466), which are followed by another POI and its respective area ids. To find out the details for area id 3600435511, simply consult the full area details towards the end of the response.

Unfortunately, any nodes which have been enhanced via convert don't include any lat/lon details at this time.

Church building ways in an area

When applying this technique to ways, one has to keep in mind that the is_in statement only works on nodes. For this reason, we first have to determine all nodes for a way.

[timeout:60];area["name"="Mayenne"]->.boundaryarea;way(area.boundaryarea)["building"="church"];foreach(node(w)->.d;// determine all nodes of a way.nis_in->.a;area.a[name][boundary=administrative][admin_level~"^[2-8]$"]->.a;outcenter;convertway::=::,::id=id(),is_in=a.set("{"+t["admin_level"]+":"+t["name"]+"}");out;);

Wiki table generator (since 0.7.54)

The following query abuses csv and make features a bit to create a wikitable syntax table, which can be copy & pasted into a wiki page (see result below). This might be useful to avoid command line post processing of Overpass results.

Quality Assurance

The general purpose of the Quality Assurance Queries is to check
whether some assumption about the data universally holds.
Thus, the themes covered here are converting assumptions into query conditions
and mastering the functionality to understand museum data.

Find all bus stops which are not included in a relation

This query returns all bus stop nodes, which are not part of a relation.

// Select city of Bonn as areaarea[name="Bonn"];// Collect all bus stops in Bonn and store the result in a variable .allnode(area)[highway=bus_stop]->.all;// Select all relations, where one of the nodes in variable .all is a memberrel(bn.all);// ...and for those relations find all related node membersnode(r);// Calculate the set difference (._ contains all nodes which are member of a relation)(.all;-._;);// return the result including meta dataoutmeta;// Variant for line 9 / 10:// Return only relations with a specific tagging:// rel[route=bus](bn.all);

(via talk-de, Thanks to Roland)

Bus relations, which are not part of a master relation

Q: I need to find out, which bus relations (route=bus) are not part of a master relation (route_master=bus) in a given area.

Counties without fire station

The following alternative gives all counties (Kreise) in Schleswig-Holstein without amenity=fire_station. The result is in CSV format and contains the OSM ID of the relation, the "amtlichen Gemeindeschlüssel" and the name of the relation.

// Output in CSV format[out:csv(::id,"de:amtlicher_gemeindeschluessel",name)];area[admin_level=4]["name"="Schleswig-Holstein"][boundary=administrative]->.boundaryarea;// Alle bounding areas with level 8 in Schleswig-Holsteinrel(area.boundaryarea)[admin_level=8];// map relations to their respective areamap_to_area->.all_level_8_areas;// Search All amenity=fire_station in Schleswig-Holstein(node(area.boundaryarea)["amenity"="fire_station"];way(area.boundaryarea)["amenity"="fire_station"];>;);// in which boundary areas with level 8 do they appear?is_in;area._[admin_level=8]->.level_8_areas_with_firestation;// All level 8 bounding areas without those // areas with fire station(.all_level_8_areas;-.level_8_areas_with_firestation;);// Calculate and output relationrel(pivot);outgeom;

Buildings crossed by roads that are not tagged as tunnel or covered

Building overlaps highway

Query for buildings crossed by roads (Ways) that do not have a tunnel or covered tag. Since query uses the "around" operator, which searches in the environment of an item, it is possible that false positives are returned, e.g. when a street (Way) is directly connected to the building

Please note that this is a very slow query, that can better be run with a specified bounding box.

Find duplicate nodes (since 0.7.54)

We iterate over all nodes in the current bounding box one by one, and find out the list of all nodes with the same lat/lon value. Assuming there's more than one node at the same lat/lon, those two nodes will have different node ids. That's also the condition we use to filter out those duplicate nodes. The output will only return the duplicate node for each location having the lowest node id.

Find useless associatedStreet-relations

JOSM-plugin "terracer" can be used to split buildings in several parts. Unfortunately, this plugin used to create an associatedStreet relation by default. Those relations are totally useless. Also, street names on the selected buildings are ignored, and only the names filled in the dialog are taken and put on the relation. Also the required "street"s for this type of relation are missing. The result is an associatedStreet-relation with a few members with the role "house".

Default settings were changed in the meantime. However, there are still many useless aS relations around.

/* Enter your city/region/etc. here */{{nominatimArea:Berlin}}(._;)->.area;/* Find all associatedStreet relations in your area */rel[type=associatedStreet][!name][!"addr:street"](area.area)->.allASRelations;/* Find associatedStreet relations with member ways having role "street" */way(r.allASRelations:"street");rel(bw:"street")[type=associatedStreet]->.relationsWithRoleStreet;/* Find all aS relations with empty role-way members */way(r.allASRelations:"");rel(bw:"")[type=associatedStreet]->.relationsWithEmptyRole;/* Find all relations with node members */node(r.allASRelations);rel(bn)[type=associatedStreet]->.relationsWithNode;/* Check if there are member ways with role 'house' not having a building tag */way(r.allASRelations:"house")[!building];rel(bn)[type=associatedStreet]->.relationsWoHouseBuilding;/* Take all aS relations and remove all relations we want to exclude */((((.allASRelations;-.relationsWithRoleStreet;);-.relationsWithEmptyRole;);-.relationsWithNode;);-.relationsWoHouseBuilding);/* add ways and nodes for output*/(._;);outmeta;

Find house numbers without street

The following Overpass API query retrieves all Nodes, Ways and Relations that have a addr:housenumber-tag and no addr:street nor addr:place tag. For this collection, we remove all Nodes/Ways/Relations that take part in an associatedStreet-Relation with a role "house".

Notes:

The query assumes that the associatedStreet-relation is conform with the wiki and that it contains at least one member with the role "street", such that the street can be deduced. This is not verified by the query!

associatedStreet-Relations without street-roles can be found with the query= "unnütze associatedStreet-Relationen ermitteln" . This problem has to be resolved first, as it would prevent the correct retrieval of house numbers.

{{nominatimArea:"Regionalverband Saarbrücken"}}(._;)->.boundaryarea;/* Shows the boundary area as extra check - one is free to activate this step *//* rel(pivot.boundaryarea);(way(r);>;);out; */rel(area.boundaryarea)[type=associatedStreet]->.associatedStreet;way(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesWay;way(r.associatedStreet:"house")->.asHouseWay;((.allHousesWay;-.asHouseWay);>;);outmeta;node(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesNode;node(r.associatedStreet:"house")->.asHouseNode;((.allHousesNode;-.asHouseNode););outmeta;rel(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesRel;rel(r.associatedStreet:"house")->.asHouseRel;((.allHousesRel;-.asHouseRel);>>;);outmeta;

The overpass turbo friendly version first determines all postal_code boundary relations in the current bounding box and checks for deviations in nodes and ways, comparing the postal_code with the addr:postcode tag.

Ways that are part of a "Bundesstraßenrelation", but do not have a ref-tag

Normally, one would expect that the properties of a relation are also applied to the member ways, so that it is not needed to set those tags explicitly on the ways. However, it turns out that the common practice is to set this ref also on each way. This query shows all ways that do not have the ref-tag.

For a selected area (in the example Saarland), the query retrieves all Ways whose ref-tag starts with a "B". From this collection, we remove all Ways that are part of a relation with type=route, route=road and that have a ref that starts with "B". The remaining federal streets, which are not part of a relation, are returned together with their nodes, in order to show them on a map.

POIs with websites but with incorrect opening hours

The following query returns institutions and shops, for which a website is tagged, but the opening hours are incorrect (i.e. the syntax is wrong). One should first try the first query, because it more likely to return results for which the opening hours can be found on the website. When the result of the first query is empty, one could try the second one.

Sum of a few defined OSM areas

This query is easily modified to get a sum of any OSM defined areas (geocodeArea) and extract any data for this sum of areas. See comments for details. The example just shows the chosen areas.

[out:json][timeout:900];// get a few areas into .myArea// you can add or remove an area by simply adding or removing// one line here. ({{geocodeArea:"Warszawa"}};{{geocodeArea:"Grodzisk Mazowiecki County"}};// "name:en" may be used as well as "name"{{geocodeArea:"powiat pruszkowski"}};{{geocodeArea:"powiat żyrardowski"}};{{geocodeArea:"powiat warszawski zachodni"}};{{geocodeArea:"powiat sochaczewski"}};{{geocodeArea:"powiat nowodworski"}};{{geocodeArea:"powiat legionowski"}};{{geocodeArea:"powiat wołomiński"}};{{geocodeArea:"powiat miński"}};{{geocodeArea:"powiat otwocki"}};{{geocodeArea:"powiat piaseczyński"}};)->.myArea;// display .myArea This can be replaced by any query// on the objects in .myArearel(pivot.myArea);// print resultsoutgeom;{{style:node{opacity:0;fill-opacity:0}}}

« n » adjacent ways

The following example illustrates how to determine five adjacent ways for OSM way 111435507. The around statement with radius 0, which is used in this query not only filters directly connected ways, but also returns intersecting ways (without a common node). Possibly those intersecting ways need to be filtered out in a post-processing step.

To limit the overall data volume only ways with a highway tag (excluding path, track, cycleway and footpath) are considered. In addition, the global search space is limited via [bbox:...] to a certain bounding box.

If ways cannot be split into two distinct groups (e.g. building ways vs. highway=tertiary ways), it is necessary to iterate over each single way and determine the intersecting nodes with all other ways in a bbox:

Examples for Styles in overpass turbo (MapCSS)

Hiking routes

The following query for Overpass Turbo shows all hiking-relations in the current bounding box (route=hiking and network=?wn), such as in the Lonvia-style.
The color for the ways is taken from the relation.