Overpass API/Overpass API by Example

From OpenStreetMap Wiki
Jump to: navigation, search
Available languages — Overpass API/Overpass API by Example
· Afrikaans · Alemannisch · aragonés · asturianu · azərbaycanca · Bahasa Indonesia · Bahasa Melayu · Bân-lâm-gú · Basa Jawa · Basa Sunda · Baso Minangkabau · bosanski · brezhoneg · català · čeština · corsu · dansk · Deutsch · eesti · English · español · Esperanto · estremeñu · euskara · français · Frysk · Gaeilge · Gàidhlig · galego · Hausa · hrvatski · Igbo · interlingua · Interlingue · isiXhosa · isiZulu · íslenska · italiano · Kiswahili · Kreyòl ayisyen · kréyòl gwadloupéyen · Kurdî · latviešu · Lëtzebuergesch · lietuvių · magyar · Malagasy · Malti · Nederlands · Nedersaksies · norsk bokmål · norsk nynorsk · occitan · Oromoo · oʻzbekcha/ўзбекча · Plattdüütsch · polski · português · română · shqip · slovenčina · slovenščina · Soomaaliga · suomi · svenska · Tiếng Việt · Türkçe · Vahcuengh · vèneto · Wolof · Yorùbá · Zazaki · српски / srpski · беларуская · български · қазақша · македонски · монгол · русский · тоҷикӣ · українська · Ελληνικά · Հայերեն · ქართული · नेपाली · मराठी · हिन्दी · भोजपुरी · অসমীয়া · বাংলা · ਪੰਜਾਬੀ · ગુજરાતી · ଓଡ଼ିଆ · தமிழ் · తెలుగు · ಕನ್ನಡ · മലയാളം · සිංහල · བོད་ཡིག · ไทย · မြန်မာဘာသာ · ລາວ · ភាសាខ្មែរ · ⵜⴰⵎⴰⵣⵉⵖⵜ ⵜⴰⵏⴰⵡⴰⵢⵜ‎ · አማርኛ · 한국어 · 日本語 · 中文(简体)‎ · 中文(繁體)‎ · 吴语 · 粵語 · ייִדיש · עברית · اردو · العربية · پښتو · سنڌي · فارسی · ދިވެހިބަސް
Overpass turbo · Wizard · Overpass turbo shortcuts · MapCSS Overpass API · Language reference · Language guide · Query examples · Advanced examples · Sparse Editing · FAQ more: Overpass turbo · Overpass API

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 overpass turbo Icon next to each query to try it in overpass turbo!


Contents

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

try it yourself in overpass-turbo
/*
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 results
out body;
>;
out skel qt;

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

try it yourself in overpass-turbo
[out:json][timeout:25];
(
  node["amenity"="post_box"]({{bbox}});
  way["amenity"="post_box"]({{bbox}});
  relation["amenity"="post_box"]({{bbox}});
);
out body;
>;
out skel qt;

As we are about a simple example here, we reduce the query further in two steps to get it really simple.

We know for post boxes by common knowledge that they are always nodes:

try it yourself in overpass-turbo
[out:json][timeout:25];
(
  node["amenity"="post_box"]({{bbox}});
);
out body;
>;
out skel qt;

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.

try it yourself in overpass-turbo
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.

try it yourself in overpass-turbo
node["amenity"="restaurant"]({{bbox}});
out;

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

try it yourself in overpass-turbo
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:

try it yourself in overpass-turbo
way["amenity"="restaurant"]({{bbox}});
out center;

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.

try it yourself in overpass-turbo
node["amenity"="restaurant"]({{bbox}});
out;
way["amenity"="restaurant"]({{bbox}});
out center;
relation["amenity"="restaurant"]({{bbox}});
out center;

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.

As a last step, we make the query more concise:

try it yourself in overpass-turbo
[bbox:{{bbox}}];
( node["amenity"="restaurant"];
  way["amenity"="restaurant"];
  relation["amenity"="restaurant"]; );
out center;

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.

We also have grouped the query statements by an union statement - these are the parentheses. This allows to have only a single output statement.

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.

In total, we arrive at the following request:

try it yourself in overpass-turbo
[timeout:25][bbox:{{bbox}}];
( node["amenity"="restaurant"];
  way["amenity"="restaurant"];
  relation["amenity"="restaurant"]; );
out center;

Rare Tags

If do not know beforehand where you would expect a tag but if you are pretty sure that there are not much more than some hundred elements then you can drop the bounding box.

try it yourself in overpass-turbo
[timeout:25];
( node[name="Belsenplatz"];
  way[name="Belsenplatz"];
  rel[name="Belsenplatz"]; );
out center;

If you also leave the timeout setting then the server sets a default of 180 seconds:

try it yourself in overpass-turbo
( node[name="Belsenplatz"];
  way[name="Belsenplatz"];
  rel[name="Belsenplatz"]; );
out center;

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:

try it yourself in overpass-turbo
node({{bbox}})(if:count_tags() > 0);
out geom;

The question was posed here.

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:

try it yourself in overpass-turbo
node({{bbox}})[name](if:count_tags() == 1);
out geom;

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.

The original question comes from this source.

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.

try it yourself in overpass-turbo
/*
   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 057
area["de:regionalschluessel"~"^057"];

// Count the pharmacies in each area
foreach->.regio(
  // display details for the current area
  .regio out;

  // 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  
  out count; 
);

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

try it yourself in overpass-turbo
[out:csv( "de:regionalschluessel", name, total, nodes, ways, relations )];

//All areas with regional key (German: "Regionalschlüssel") starting with 057
area["de:regionalschluessel"~"^057.*"];

// Count the pharmacies in each area
foreach->.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]);
  
  make count "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.

try it yourself in overpass-turbo
[out:csv(::count, ::"count:nodes", ::"count:ways", ::"count:relations")][timeout:25];
{{geocodeArea:Chemnitz}}->.searchArea;
(
  node["addr:housenumber"](area.searchArea);
  way["addr:housenumber"](area.searchArea);
  relation["addr:housenumber"](area.searchArea);
);
out count;

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.

try it yourself in overpass-turbo
[timeout:600];
rel[admin_level=2][wikidata]->.a;
foreach .a -> .b (
  rel.a(if:t[wikidata] == b.u(t[wikidata]))->.d;
  rel.d(if: id() == d.min(id()) && d.count(relations) > 1 );
  convert rel ::id = _.u(id()),
             wikidata = _.u(t[wikidata]),
             all_relation_ids = d.set( id() );
  (._ ; .result; ) -> .result;
);

.result out;

Result:

<?xml version="1.0" encoding="UTF-8"?>
<osm version="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>
<meta osm_base="2017-03-29T19:04:03Z"/>

  <rel id="11980">
    <tag k="wikidata" v="Q142"/>
    <tag k="all_relation_ids" v="11980;2202162"/>
  </rel>
  <rel id="36990">
    <tag k="wikidata" v="Q235"/>
    <tag k="all_relation_ids" v="1124039;36990"/>
  </rel>
  <rel id="51477">
    <tag k="wikidata" v="Q183"/>
    <tag k="all_relation_ids" v="1111111;51477;62781"/>
  </rel>
  <rel id="87565">
    <tag k="wikidata" v="Q258"/>
    <tag k="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:

try it yourself in overpass-turbo
[out:csv(wikidata, ::id;false;";")];
rel[admin_level][wikidata];
out;

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.

try it yourself in overpass-turbo
rel[wikidata]({{bbox}});     // get all relations with wikidata tag in current bounding box
way(r)[wikidata]->.all;      // get all way members with wikidata tag

foreach -> .rel(             // process each relation one by one
    
  // find out all way members where the wikidata tag matches the relation's wikidata tag
  way.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);
  out center;
  
  // ... followed by all ways with matching wikidata tag
  .ways out tags;
);

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.

try it yourself in overpass-turbo
rel({{bbox}})[type=multipolygon]->.relations;

foreach .relations -> .relation (

  (
    node(r.relation);
    way(r.relation);
    rel(r.relation);
  )->.elem_all;

  (
    node(r.relation:"inner");
    way(r.relation:"inner");
    rel(r.relation:"inner");
  )->.elem_inner;
  
  (
    node(r.relation:"outer");
    way(r.relation:"outer");
    rel(r.relation:"outer");
  )->.elem_outer;
  
  
  rel.relation( if:elem_all.count(nodes)     > elem_inner.count(nodes) + 
                                               elem_outer.count(nodes) ||
                   elem_all.count(ways)      > elem_inner.count(ways)  +
                                               elem_outer.count(ways)  ||
                   elem_all.count(relations) > elem_inner.count(relations) +
                                               elem_outer.count(relations));

  out center;
);

Geometry and Topology

Find multipolygons with more than one outer way member (since 0.7.54)

Please note that relations with more than one outer member are valid.

try it yourself in overpass-turbo
rel[type=multipolygon]({{bbox}});
foreach -> .a (
  way(r.a:outer);
  ( rel.a(if:count(ways) > 1);
    .result; )->.result;
);
.result out center;

Search for street intersections

The following query returns the street intersection of 6th Avenue and West 23rd Street (e.g. in New York):

try it yourself in overpass-turbo
[bbox:{{bbox}}];
way[highway][name="6th Avenue"]->.w1;
way[highway][name="West 23rd Street"]->.w2;
node(w.w1)(w.w2);
out;

Assumption: both streets need to be connected via a common node.

Source

Find intersections of major and minor roads:

try it yourself in overpass-turbo
[bbox:{{bbox}}];
way[highway~"^(motorway|trunk|primary|secondary|tertiary|(motorway|trunk|primary|secondary)_link)$"]->.major;
way[highway~"^(unclassified|residential|living_street|service)$"]->.minor;
node(w.major)(w.minor);
out;

Complex Situations of Tagging and Geometry

Highway around schools with inappropriate maxspeed (since 0.7.54)

try it yourself in overpass-turbo
// 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/h

way(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;);
out geom;

Isolated Buildings

Find buildings where the closest building is more than 1km away.

try it yourself in overpass-turbo
way[building]({{bbox}})->.a;
foreach .a (
  way.a(around:1000);
  way._(if:count(ways) == 1);
  out center;
);

NB: Query is very slow, needs the following fix

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.

try it yourself in overpass-turbo
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
.newnodes out meta;

This query has a few shortcomings:

  1. Only last-changed timestamp of a node is taken into account. A non-railway mapper moving a railway=signal node would trigger false positives.
  2. 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 following query retrieves a object of virtu in the data. It was visible on May 6, 2014 at 00:00.

try it yourself in overpass-turbo
[date:"2014-05-06T00:00:00Z"];
( node({{bbox}}); <; >; );
out meta;

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:

try it yourself in overpass-turbo
[out:csv("name";false)];
area[name="Troisdorf"];
way(area)[highway][name];
out;

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

sort liste.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

try it yourself in overpass-turbo
[out:csv("name";false)];
area[name~"Eckernförde"];
way(area)[highway][name];
out;

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:

try it yourself in overpass-turbo
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:

try it yourself in overpass-turbo
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 results
foreach.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.
  out ids;
);

// collect area details in 2nd step
.posts is_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.

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API">
  <node id="691566183" lat="49.7982193" lon="13.4686623">
    <tag k="ele" v="295"/>
    <tag k="information" v="guidepost"/>
    <tag k="name" v="Dolanský most (pravý břeh)"/>
    <tag k="tourism" v="information"/>
  </node>
  <area id="3600435511"/>
  <area id="3600442466"/>
  <node id="691566191" lat="49.8003120" lon="13.4679726">
    <tag k="ele" v="295"/>
    <tag k="information" v="guidepost"/>
    <tag k="name" v="Dolanský most (levý břeh)"/>
    <tag k="tourism" v="information"/>
  </node>
  <area id="3600435511"/>
  <area id="3600442466"/>
[...]
  <area id="3600435511">
    <tag k="admin_level" v="4"/>
    <tag k="boundary" v="administrative"/>
    <tag k="name" v="Jihozápad"/>
    <tag k="name:cs" v="Jihozápad"/>
    <tag k="name:de" v="Südwesten"/>
    <tag k="population" v="1209298"/>
    <tag k="ref" v="CZ03"/>
    <tag k="ref:NUTS" v="CZ03"/>
    <tag k="source" v="cuzk:ruian"/>
    <tag k="source:population" v="csu:uir-zsj"/>
    <tag k="type" v="boundary"/>
    <tag k="wikipedia" v="cs:NUTS Jihozápad"/>
  </area>
  <area id="3600442466">
    <tag k="ISO3166-2" v="CZ-PL"/>
    <tag k="admin_level" v="6"/>
    <tag k="boundary" v="administrative"/>
    <tag k="name" v="Plzeňský kraj"/>
    <tag k="name:cs" v="Plzeňský kraj"/>
    <tag k="name:de" v="Region Pilsen"/>
    <tag k="name:ru" v="Пльзенский край"/>
    <tag k="population" v="572687"/>
    <tag k="ref" v="PL"/>
    <tag k="ref:NUTS" v="CZ032"/>
    <tag k="source" v="cuzk:ruian"/>
    <tag k="source:population" v="csu:uir-zsj"/>
    <tag k="type" v="boundary"/>
    <tag k="wikipedia" v="cs:Plzeňský kraj"/>
  </area>

Source, Thanks to Roland

Adding Georeference details to village nodes (since 0.7.54)

Since 0.7.54, it is also possible to generate is_in details for place=village nodes in the current bbox on-the-fly:

try it yourself in overpass-turbo
node({{bbox}})[place=village];
  foreach(
    is_in->.a;
    area.a[name][boundary=administrative][admin_level~"^[2-8]$"] -> .a;
    convert node ::=::,
              ::id = id(),
              is_in=a.set("{" + t[admin_level] + ":" + t[name] + "}");
   
    out;
  );

The resulting XML includes a new is_in tag, which lists all boundary=administrative with admin_level from 2..8 and a name, sorted by increasing admin_level:

  <node id="1724711941">
    <tag k="name" v="Steinklingen"/>
    <tag k="place" v="village"/>
    <tag k="is_in" v="{2:Deutschland};{4:Baden-Württemberg};{5:Regierungsbezirk Karlsruhe};{6:Rhein-Neckar-Kreis};{8:Weinheim}"/>
  </node>

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.

try it yourself in overpass-turbo
[timeout:60];
area["name"="Mayenne"]->.boundaryarea;
way(area.boundaryarea)["building"="church"];
  foreach(
    node(w)->.d;                                     // determine all nodes of a way
    .n is_in->.a;
    area.a[name][boundary=administrative][admin_level~"^[2-8]$"] -> .a;
    out center;
    convert way ::=::,
              ::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.

try it yourself in overpass-turbo
// Poor man's wikitable generator

[out:csv(_row;false)];

make out _row = "{|class=wikitable    "; out;
make out _row = "! Regional Key       "; out;
make out _row = "! Name               "; out;
make out _row = "! Total              "; out;
make out _row = "! Nodes              "; out;
make out _row = "! Ways               "; out;
make out _row = "! Relations          "; out;
make out _row = "|-                   "; out;


//All areas with regional key (German: "Regionalschlüssel") starting with 057
area["de:regionalschluessel"~"^05774"];

// Count the pharmacies in each area
foreach->.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]) -> .r;
  
  make out _row = "| " + regio.set(t[ "de:regionalschluessel"]) + 
                  " || " + regio.set(t["name"]) + 
                  " || " + (r.count(nodes) + r.count(ways) + r.count(relations)) + 
                  " || " + r.count(nodes) + 
                  " || " + r.count(ways) +
                  " || " + r.count(relations); 
  out;
  make out _row = "|-"; out;

);
make out _row = "|}"; out;

Query result (pasted into a wiki page):

Raw data Rendered as wiki page
{|class=wikitable    
! Regional Key       
! Name               
! Total              
! Nodes              
! Ways               
! Relations          
|-                   
| 05774 || Kreis Paderborn || 68 || 61 || 7 || 0
|-
| 057740016016 || Büren || 3 || 3 || 0 || 0
|-
| 057740036036 || Salzkotten || 5 || 5 || 0 || 0
|-
| 057740040040 || Bad Wünnenberg || 3 || 2 || 1 || 0
|-
| 057740028028 || Lichtenau || 2 || 2 || 0 || 0
|-
| 057740024024 || Hövelhof || 3 || 2 || 1 || 0
|-
| 057740020020 || Delbrück || 6 || 6 || 0 || 0
|-
| 057740008008 || Bad Lippspringe || 4 || 4 || 0 || 0
|-
| 057740032032 || Paderborn || 39 || 35 || 4 || 0
|-
| 057740012012 || Borchen || 1 || 1 || 0 || 0
|-
| 057740004004 || Altenbeken || 2 || 1 || 1 || 0
|-
|}
Regional Key Name Total Nodes Ways Relations
05774 Kreis Paderborn 68 61 7 0
057740016016 Büren 3 3 0 0
057740036036 Salzkotten 5 5 0 0
057740040040 Bad Wünnenberg 3 2 1 0
057740028028 Lichtenau 2 2 0 0
057740024024 Hövelhof 3 2 1 0
057740020020 Delbrück 6 6 0 0
057740008008 Bad Lippspringe 4 4 0 0
057740032032 Paderborn 39 35 4 0
057740012012 Borchen 1 1 0 0
057740004004 Altenbeken 2 1 1 0

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.

Checking boundary relations for correct tagging

Looking for a boundary relation with boundary=administrative and admin_level=9 and de:amtlicher_gemeindeschluessel=XXXXXXXX, because this combination is invalid. Boundary relation for villages with their own "Gemeindeschlüssel" should have at least admin_level=8 or higher.

The first query also leaves out "boundary=administrative", because it is equally possible that one has set the wrong level or did not mention the level at all

try it yourself in overpass-turbo
rel[admin_level=9]["de:amtlicher_gemeindeschluessel"];
out;

or

try it yourself in overpass-turbo
rel[boundary=administrative][admin_level=9]["de:amtlicher_gemeindeschluessel"];
out;

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.

try it yourself in overpass-turbo
// Select city of Bonn as area
area[name="Bonn"];

// Collect all bus stops in Bonn and store the result in a variable .all
node(area)[highway=bus_stop]->.all;

// Select all relations, where one of the nodes in variable .all is a member
rel(bn.all);
// ...and for those relations find all related node members
node(r);

// Calculate the set difference (._ contains all nodes which are member of a relation)
( .all; - ._; );

// return the result including meta data
out meta;

// 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.

try it yourself in overpass-turbo
rel({{bbox}})[route=bus]->.all;
rel[route_master=bus](br.all);
rel[route=bus](r);
( .all; - ._; );
out;

Step-by-step explanation:

  1. Determine all relations in the current bbox with type route=bus. Save the result in variable .all
  2. Determine all parent relations of our relations in .all. Those relations need to be of type route_master=bus.
  3. Based on the list of route_master relations, we determine all child relations of type route=bus. Those relations are all part of a master relation.
  4. Create the set difference of the relations in variable .all and the result from the previous step 3. This way, all relations, which are not part of a master relation, are returned.

Source

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.

try it yourself in overpass-turbo
// 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-Holstein
rel(area.boundaryarea)[admin_level=8];
// map relations to their respective area
map_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 relation
rel(pivot);
out geom;

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.

try it yourself in overpass-turbo
way[!covered][!tunnel]
   ["highway"~"primary|secondary|tertiary|trunk|service|residential|primary_link|secondary_link|tertiary_link|unclassified"]["access"!~"no|private"][!area]
   ({{bbox}});
   (way(around:0)["building"~"."];
    node(w););
out meta;

Find duplicate nodes (since 0.7.54)

See https://help.openstreetmap.org/questions/39745/show-duplicated-nodes-via-overpass


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.

try it yourself in overpass-turbo
[bbox:{{bbox}}];
node;
foreach->.a(
    node(around.a:0)->.b;
    node.b(if:id() == b.min(id()) && b.min(id()) != b.max(id()));
    out ;
);

Unfortunately, this is very slow.

Search for untagged ways

try it yourself in overpass-turbo
way({{bbox}})(if:count_tags() == 0);
out geom;

Before version 0.7.54 the following query can be run in overpass turbo and results exported to JOSM for further processing.

try it yourself in overpass-turbo
(way({{bbox}}); - way({{bbox}})[~"."~"."];)->.w1;
rel(bw.w1);way(r)->.w2;
(.w1; - .w2;);
(._; >;);
out meta;

Source

Alternative: OSM Inspector has a Tagging layer highlighting ways without tags.

Orphaned nodes (nodes without tags, not part of any way or relation)

The following query checks for nodes in the current bounding box without any tags, that are not part of any way or relation.

try it yourself in overpass-turbo
[bbox:{{bbox}}];
rel; > -> .r;
way; > -> .w;
(( node(if:count_tags()==0); - node.r; );  - node.w; );
out meta;

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".

It would be good to identify those relations and delete them:
— brogo, im dt. OSM Forum

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

try it yourself in overpass-turbo
/* 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*/
(._;  );
out meta;

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.
  • The name-tag on the relation is ignored. Warning: in the solution of User:Gehrke for #osmwa3334 requires a name tag on the associatedStreet-Relation, but ignores the members with the role "street"

The search area can be adapted in the first line, more details in Forum Thread.

try it yourself in overpass-turbo
area[type=boundary]["de:amtlicher_gemeindeschluessel"="08115003"]->.boundaryarea;
rel(area.boundaryarea)[type=associatedStreet]->.associatedStreet;

way(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesWay;
way(r.associatedStreet:"house")->.asHouseWay;
((.allHousesWay; - .asHouseWay); >; );out meta;

node(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesNode;
node(r.associatedStreet:"house")->.asHouseNode;
((.allHousesNode; - .asHouseNode););out meta;

rel(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesRel;
rel(r.associatedStreet:"house")->.asHouseRel;
((.allHousesRel; - .asHouseRel); >>; );out meta;


Alternatively, one could do a search via Nominatim:

try it yourself in overpass-turbo
{{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); >; );out meta;

node(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesNode;
node(r.associatedStreet:"house")->.asHouseNode;
((.allHousesNode; - .asHouseNode););out meta;

rel(area.boundaryarea)["addr:housenumber"][!"addr:street"][!"addr:place"]->.allHousesRel;
rel(r.associatedStreet:"house")->.asHouseRel;
((.allHousesRel; - .asHouseRel); >>; );out meta;

Nehme entweder "addr:street", "addr:place" oder "name" von associatedStreet. Trifft nichts zu, ist die Straße "null". Ich zähle nun alle Fälle (nur nodes und ways), wo es zwar eine Hausnummer gibt, aber die Straße "null"

Non-matching addr:postcode=XXXXX tags inside a boundary relation with postal code ≠ XXXXX

... what is the query for all Nodes and Ways with a different addr:postcode than the surrounding boundary relation?

Query for a specific postal code, e.g. "42103":
try it yourself in overpass-turbo
area[postal_code="42103"]->.a;
(node(area.a)["addr:postcode"]["addr:postcode"!="42103"];
 way(area.a)["addr:postcode"]["addr:postcode"!="42103"];);
out;

Non-matching addr:postcode=XXXXX tags inside multiple boundary relation with postal code ≠ XXXXX (since 0.7.54)

Since release 0.7.54, it's also possible to check several postal codes in one query:

try it yourself in overpass-turbo
area[postal_code](if:number(t[postal_code])>="42103" &&
                     number(t[postal_code])<="42119")->.pc;

foreach.pc -> .a(
  .a out;
  (
    node(area.a)["addr:postcode"]["addr:postcode"](if: t["addr:postcode"] != a.u(t["postal_code"]));
    way(area.a) ["addr:postcode"]["addr:postcode"](if: t["addr:postcode"] != a.u(t["postal_code"]));
  );
  out geom;
);

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.

try it yourself in overpass-turbo
[bbox:{{bbox}}];
rel[boundary=postal_code][postal_code];
map_to_area;
foreach -> .a(
  (
  node(area.a)["addr:postcode"](if:t["addr:postcode"] != a.u(t[postal_code]));
  way (area.a)["addr:postcode"](if:t["addr:postcode"] != a.u(t[postal_code]));
//  rel(area.a)["addr:postcode"](if:t["addr:postcode"] != a.u(t[postal_code]));
  );
  out geom;
);


Previously, this required a bash-script for postal codes 42103 - 42119

i=42103; 
while [[ $i -le 42119 ]];
do { 
   wget -O false_$i.osm "http://overpass-api.de/api/interpreter?data=area[postal_code=\"$i\"]->.a;(node(area.a)[\"addr:postcode\"][\"addr:postcode\"!=\"$i\"];way(area.a)[\"addr:postcode\"][\"addr:postcode\"!=\"$i\"];>;);out;";
   i=$(($i + 1));
};
done

When one replaces "out;" with "out meta;", than it becomes possible to read the data in the file "false_XXXXX.osm" into JOSM for editing.

The query becomes noticeable faster faster with a proper Bounding Box:

i=42103;
while [[ $i -le 42119 ]];
do {
   wget -O false_$i.osm "http://overpass-api.de/api/interpreter?data=area[postal_code=\"$i\"]->.a;(node(51,7,51.5,7.5)(area.a)[\"addr:postcode\"][\"addr:postcode\"!=\"$i\"];way(51,7,51.5,7.5)(area.a)[\"addr:postcode\"][\"addr:postcode\"!=\"$i\"];>;);out meta;";
   i=$(($i + 1));
};
done

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.

try it yourself in overpass-turbo
rel({{bbox}})[type=route][route=road][ref~"^B."];
way(r)[!ref];
(._;>;);
out meta;

It is also possible to have a ref tag, but that the way does not belong to a relation.

try it yourself in overpass-turbo
area[name="Saarland"][type=boundary]->.a;
( 
  way(area.a)[highway][ref~"^B.*"]; - 
 (rel(area.a)[ref~"^B.*"][route=road][type=route];>;);
);
(._;>;);out;

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.

First Query, Second Query

Building Blocks

These are examples that are not directly related to applications but rather support the language specification with examples.

Search objects with a certain tag A but without a tag B

Example: find all Nodes, Ways and Areas which are tagged with addr:city, but do not have addr:postcode. This makes use of the exists filter and not exists filter.

try it yourself in overpass-turbo
[out:json][timeout:25];
(
  node["addr:street"][!"addr:postcode"]({{bbox}});
  way["addr:street"][!"addr:postcode"]({{bbox}});
);
out skel;

Find nodes/ways with a given role in a relation

Find all nodes with role "label" or "admin_centre" in current bounding box:

try it yourself in overpass-turbo
rel({{bbox}})->.relations;

(  node(r.relations:"label");
   node(r.relations:"admin_centre")
);
out;


Find all "inner" ways, e.g. relation member ways with role 'inner':

try it yourself in overpass-turbo
rel({{bbox}});(way(r:"inner");>;);out;


Find all nodes and ways with role "via":

try it yourself in overpass-turbo
rel({{bbox}})->.relations;

( 
  node(r.relations:"via");
  way(r.relations:"via");>;
);out;

Source

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.

try it yourself in overpass-turbo
[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 .myArea

rel(pivot.myArea);

// print results
out geom;

{{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. try it yourself in overpass-turbo

[bbox:{{bbox}}];
way(111435507);
(way(around:0)[highway~"."][highway!~"path|track|cycleway|footway"];(._;>;))->.a;
(way(around:0)[highway~"."][highway!~"path|track|cycleway|footway"];(._;>;))->.b;
(way(around:0)[highway~"."][highway!~"path|track|cycleway|footway"];(._;>;))->.c;
(way(around:0)[highway~"."][highway!~"path|track|cycleway|footway"];(._;>;))->.d;
(way(around:0)[highway~"."][highway!~"path|track|cycleway|footway"];(._;>;))->.e;
(.a;.b;.c;.d;.e;);out;

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.


Source

Search for nodes which belong to two different ways

How to find nodes, which belong to two different ways with certain tags?

Examples:

Returns nodes which are part of a building:

try it yourself in overpass-turbo
way["building"="yes"]({{bbox}});
node(w);

Returns nodes of tertiary highways:

try it yourself in overpass-turbo
way["highway"="tertiary"]({{bbox}});
node(w);

How can I combine those two queries so that both conditions are met?

try it yourself in overpass-turbo
way["building"="yes"]({{bbox}});
node(w)->.b;
way["highway"="tertiary"]({{bbox}});
node(w)->.t;
node.b.t;            // calculates set intersection of both variables .b and .t
out;

Source

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:

try it yourself in overpass-turbo
way({{bbox}})->.allways;
foreach .allways -> .currentway(
  (.allways - .currentway)->.allotherways;
  node(w.currentway)->.e;
  node(w.allotherways)->.f;
  node.e.f;
  (._ ; .result;) -> .result;
);
.result out meta;

Search for nodes which belong to an exact number of ways (since 0.7.54)

To find out all nodes, which belong to an exact number of ways (rather than just more than one way as in the previous example), the following approach can be used:

Find out all nodes, which belong to exactly 3 distinct ways:

try it yourself in overpass-turbo
way({{bbox}})->.a;
foreach .a -> .b(
  (.a - .b)->.c;
  node(w.c)->.e;
  node(w.b)->.f;
  node.e.f->.f1;
  foreach .f1 -> .g(
    way(bn.g);
    way._(if:count(ways) == 3);
    node.g(w);
    (._ ; .result;) -> .result;
  );
);
.result out meta;

Caveat: Unfortunately, this query is extremely slow.

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.

try it yourself in overpass-turbo
[bbox:{{bbox}}];
(
  relation[route=hiking][network~"^.wn$"];
  way(r);
  >;
);
out;

{{style:
way
{ color:green; fill-color:green; }

relation[network=lwn] way
{ color:blue; fill-color:cyan; }

relation[network=iwn] way
{ color:red; fill-color:red; }

relation[network=nwn] way
{ color:green; fill-color:green; }

relation[network=rwn] way
{ color:yellow; fill-color:yellow; }

}}

It is possible that this is not 100% correct, please test and adapt when needed. (received via osm-dev, MapCSS was corrected, Query simplified)

Textboxes with eval

The following MapCSS style displays all villages in the current bounding box with a combined German / Lower Sorbian textbox.

try it yourself in overpass-turbo
[bbox:{{bbox}}];
node[place=village];
out;

{{style:
node{
  text: eval('tag("name:de") . " - " . tag("name:dsb")');
}
}}

Mailboxes

This thema can be analysed with the queries below

Mailboxes, coloured depending on availability of the collection time tag

try it yourself in overpass-turbo
node[amenity=post_box]
    //[!"collection_times"]
  ({{bbox}});
out;

{{style:
node
{ color:red; fill-color: red;}

node[collection_times]
{ color:green; fill-color:green; }
}}


Alternative that also checks the syntax of the collection time

Overpass Turbo Link - valid for 2017

try it yourself in overpass-turbo
node[amenity=post_box] ({{bbox}});
out;

{{style:
  node{
    color: #ffffff;
    fill-color: #ff0000;
    fill-opacity: 0.8;
  }
  node[operator]{
    color: #0000ff;
    fill-color: #ff0000;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck], 
  node[last_check], 
  node[check_date], 
  node[last_checked], 
  node[lastcheck]{
    color: #ffff00;
    fill-color: #ffff00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck][operator],
  node[check_date][operator],
  node[last_check][operator],
  node[last_checked][operator],
  node[lastcheck][operator] {
    color: #0000ff;
    fill-color: #ffff00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2017-*./], 
  node[check_date=~/2017-*./], 
  node[last_check=~/2017-*./], 
  node[last_checked=~/2017-*./], 
  node[lastcheck=~/2017-*./]{
    color: #ffff00;
    fill-color: #00ff00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2017-*./][operator],
  node[check_date=~/2017-*./][operator],
  node[last_check=~/2017-*./][operator],
  node[last_checked=~/2017-*./][operator],
  node[lastcheck=~/2017-*./][operator]{
    color: #0000ff;
    fill-color: #00ff00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2016-*./],
  node[check_date=~/2016-*./],
  node[last_check=~/2016-*./],
  node[last_checked=~/2016-*./],
  node[lastcheck=~/2016-*./]{
    color: #ffff00;
    fill-color: #55aa00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2016-*.  /][operator],
  node[check_date=~/2016-*./][operator],
  node[last_check=~/2016-*./][operator],
  node[last_checked=~/2016-*./][operator],
  node[lastcheck=~/2016-*./][operator]{
    color: #0000ff;
    fill-color: #55aa00;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2015-*./],
  node[check_date=~/2015-*./],
  node[last_check=~/2015-*./],
  node[last_checked=~/2015-*./],
  node[lastcheck=~/2015-*./]{
    color: #ffff00;
    fill-color: #aa5500;
    fill-opacity: 0.8;
  }
  node[collection_times:lastcheck=~/2015-*./][operator],
  node[check_date=~/2015-*./][operator],
  node[last_check=~/2015-*./][operator],
  node[last_checked=~/2015-*./][operator],
  node[lastcheck=~/2015-*./][operator]{
    color: #0000ff;
    fill-color: #aa5500;
    fill-opacity: 0.8;
  }
}}