FR:Overpass API/Language Guide

From OpenStreetMap Wiki
Jump to navigation Jump to search
Overpass API logo.svg
edit
API Overpass · Référence du langage · Guide du langage · Termes techniques · Aires · Exemples de requêtes · Édition clairsemée · ID persistant · Questions fréquentes · plus (français) · Site web
État des serveurs · Versions · Développement · Conception technique · Installation · Surcouche de compatibilité XAPI · Diagrammes de transports publics · Applications · Code source et problèmes
Overpass turbo · Assistant · Raccourcis Overpass turbo · Feuilles de style MapCSS · Export en GeoJSON · plus (français) · Développement · Code source et problèmes · Site web
Overpass Ultra · Overpass Ultra extensions · Feuilles de style MapLibre ·plus (français) · Code source et problèmes · Site web

Ce tutoriel présente des exemples de requêtes à adresser à un serveur API Overpass. Vous êtes invités à adapter les requêtes à vos besoins spécifiques. Pour un descriptif complet de ce langage, vous pouvez également consulter Overpass QL


Contexte et concepts

L'API Overpass permet de requêter la base de données OSM selon vos propres critères de recherche. À cette fin, elle dispose de deux langages de requête spécialement conçus : l'Overpass XML et l'Overpass QL.

Dans le fonctionnement de base de l'API Overpass, les flux de données OSM (nœuds, chemins ...) sont générés et modifiés par des instructions, qui sont exécutées les unes après les autres.

Par exemple, la requête suivante génère un flux de données contenant tous les nœuds d’un cadre de sélection donné (bounding box) et l'affiche :

node(50.745,7.17,50.75,7.18);
out;

Vous pouvez ensuite filtrer davantage le flux résultant en ne recherchant que les arrêts de bus :

node(50.745,7.17,50.75,7.18)[highway=bus_stop];
out;

Vous pouvez également chercher les chemins (way) qui utilisent les nœuds sélectionnés (ceci en utilisant la clause 'bn' qui signifie "recurse back to node"). Dans ce cas, la requête permettant d'obtenir l'ensemble des nœuds (node) appartenant à ces chemins (way) s'écrit de la manière suivante :

node(50.745,7.17,50.75,7.18);way(bn);
( ._; >; );
out;

Ces instructions et leur syntaxe sont détaillées ci-dessous.

Les langages de l'API Overpass

L'API Overpass offre à présent toute sa puissance via une simple requête HTTP GET. Dans ce but, le langage de requête "Overpass QL" est introduit en parallèle du langage "Overpass XML". Vous pouvez toujours faire la conversion de l'un à l'autre en utilisant l'outil http://overpass-api.de/convert_form.html. Cela permet faire la conversion en :

  • XML développé : il correspond au formulaire XML dans tous les exemples ci-dessous.
  • Overpass QL développé : il correspond au formulaire Overpass QL ci-dessous.
  • Overpass QL concis : cela génère une requête HTTP GET d'une ligne pour la même expression.

Pour exécuter la requête, utilisez plutôt http://overpass-api.de/query_form.html.

Overpass QL Basics

Des exemples de syntaxe QL sont fournis ci-dessous. La syntaxe QL est plus concise que celle de l'Overpass XML et, dans une certaine mesure, similaire aux langages de programmation de type C. Une déclaration se termine toujours par un point-virgule ";". En outre, une déclaration est soit :

  • une instruction de requête commençant par "node", "way", "relation", "rel" (abréviation de "relation") ou dans l'une des instructions de requête récursive ">", ">>", "<", ou "<<",
  • une instruction de sortie commençant par "out".

Les instructions de requête contiennent le type d'objet à récupérer :

 node
 way
 rel

et au moins une instruction décrivant l'objet à récupérer, comme :

 ["name"="Berlin"]

Les deux assemblés donnent cette requête :

 node["name"="Berlin"];

qui récupère tous les nœuds nommés Berlin.

Instructions Overpass QL

Il existe différents types d'instructions que vous pouvez utiliser :

  • pour filtrer des objets (nodes, ways, relations ou areas Overpass) qui sont présents dans le jeu d'entrée, résultut de l'étape précédente,
  • pour effectuer des requêtes autonomes sur ces objets afin de les remplacer par l'union de tous leurs objets liés selon la requête.

Les filtres Overpass QL (ou les requêtes autonomes) ne peuvent être utilisés qu'après avoir spécifié un type de requête principal (ou Resultset ), ce ne sont pas des requêtes par elles-mêmes.

Filtres sur les attributs

Voici des exemples de filtres sur les attributs :

  ["key"]            /* filtre les objets étiquetés avec cette clé (key) et n'importe quelle valeur */
  [!"key"]           /* filtre les objets non étiquetés avec cette clé  */
  ["key"="value"]    /* filtre les objets étiquetés avec cette clé (key) et cette valeur  */
  ["key"!="value"]   /* filtre les objets étiquetés avec cette clé (key) mais pas cette valeur */
  ["key"~"value"]    /* filtre les objets étiquetés avec cette clé et une valeur correspondant à une expression régulière */
  ["key"!~"value"]   /* filtre les objets étiquetés avec cette clé et une valeur ne correspondant pas à une expression régulière */
  [~"key"~"value"]   /* filtre les objets étiquetés avec une clé et une valeur correspondant à des expressions régulières */
  [~"key"~"value",i] /* filtre les objets étiquetés avec une clé et une valeur correspondant à des expressions régulières tout en étant insensible à la casse */

Bounding box clauses ("bbox query", "bounding box filter")

Bounding box clauses (like all other clauses for filters or recursion queries) can only be used as filters after specifying a main query type (or .resultset), they are not queries by themselves. In the Overpass QL syntax, they have a form like in this example:

  /*your query here*/(51.0, 7.0, 52.0, 8.0)

Bounding box clauses always start with the lowest latitude (southernmost) followed by lowest longitude (westernmost), then highest latitude (northernmost) then highest longitude (easternmost). Note that this is different from the ordering in the XAPI syntax.

The Overpass XML syntax is safeguarded by using (more explicit) named parameters (but note that their name may still be misleading, as they still take negative values for all absolute coordinates in the southern or western hemispheres, and positive values for all absolute coordinates in the northern or eastern hemispheres):

  <query><!-- replace by an effective query type; if this element is missing, a default <query type="node"> is assumed -->
    <bbox-query s="51.0" w="7.0" n="52.0" e="8.0"/>
  </query><!-- replace by an effective query type -->

A bounding box spanning through the antimeridian (which would otherwise swap the two longitudes) is equivalent to an union of two subqueries for each side of the antimeridian. For example the long band which complements the previous bounding box over the same span of latitudes is equivalent to this union of queries on two bounding boxes (as this is a very large area covering too much data, this query will probably fail, unless the main queries include more selective filters such as tag filters):

  (
    /*your query here*/(51.0,  7.0, 52.0, 180); /* West side of the antimeridian (up to the positive longitude 180°E) */
    /*your query here*/(51.0, -180, 52.0, 8.0); /* East side of the antimeridian (from  the negative longitude 180°W) */
  );

Note that you must specify same the main query here (at least "node", "way", "rel", "area" or a ".namedresultset", optionally followed by other filters or recursions) in each subquery. Currently, the Overpass API offers no facility to make this transform automatically if you swap the longitudes; instead Overpass API returns an error if the first specified longitude is greater than the second longitude.

And it is still not possible to create a single compound filter containing an union of bounding boxes (or other polygonal shapes based on an ordered list of coordinates pair, or other disc shapes based on a the cordinates of a central node and a maximum radius, or exclusions based on a substraction of two simple or compound shapes). As well, Overass API offers no way to geometrically transform such simple or compound shapes using positive or negative buffers, in order to use more complex bounding filters: queries have to be repeated using different pretransformed simple shapes. For more details, see the sections below related to the supported unions of queries, and to (around: ...) or (poly: "...") special filters for other kinds of simple bounding shapes.

Clause "area" (ou filtre "area")

Les objets "area" ("zone" en français) ne sont pas directement des objets de la base de données OSM, au contraire ce sont des objets générés en plus (sur une base régulière par une tâche d'arrière-plan, pour prendre en compte les changements et les nouveautés dans la base de données OSM), pour ce concerne les objets qui ne dénotent pas des nœuds, mais qui décrivent des surfaces : des chemins fermés, des relations ("boundary" et "multipolygon" ) dont les membres contiennent des chemins fermés qui joints ensemble (avec la notion d'anneau intérieur et d'anneau extérieur) peuvent délimiter des surfaces. Une fois générés, ces "aeras" sont conservées dans un cache. La couche Overpass est capable de traiter ces objets pour en extraire leur géométrie (les connecte ensemble et les ordonne de façon correcte en cas de relations) et les constituer comme un ensemble de frontières polygonales. La couche Overpass conserve leur géométrie et les associe à des identifiants OSM. Le langage de requète Overpass 'Overpass QL' est capable de leur associer des noms pour pouvoir, dans la suite du script 'Overpass QL', les identifier plus facilement.

Les "zones" Overpass sont utiles car elles évitent de faire des requètes avec des récursions explicites, et également comme des filtres précalculés qui ne retourneront ni chemins ni relations (qui dans les faits ne délimitent pas des surfaces). Mais comme ces "zones" sont générées de façon périodique, elles peuvent ne pas reflèter le tout-dernier état de la base de données OSM (ni même le tout-dernier différentiel de la base de données OSM reçu par le serveur Overpass). Malgré tout, cette notion de zone peut grandement simplifier et accélerer les requêtes, notamment pour les grandes surfaces ou celles avec une géométrie complexe : celles qui utilisent des relations de type "boundary" ou "multipolygon", comme les frontières de pays (ou leur sous-divisions administratives), ou les frontières complexes de grandes aires de type "landuse" ou "natural".

Ces "zone" peuvent être utilisées comme des filtres de périmètres (plutôt que d'utiliser de simples boîtes de sélection carrées "bounding boxes"), ou peuvent être utilisées directement comme des requêtes et dans ce cas ces requêtes retournent tous les nœuds contenus dans la géométrie délimitée.

If areas are referenced by their internal id in Overpass (and that area has been included), any areas present in input set is ignored and only OSM objects in the input set that are intersecting with that specified area will be kept as is:

  (area:2400000001) /* filter objects in area whose surface is delimited by the way with id=1 in OSM */
  (area:3600000001) /* filter objects in area whose surface is delimited by ways members of the relation with id=1 in OSM */

The ids for precomputed Overpass areas are currently assigned by adding simply large static constants to the OSM id (provided that the associated OSM objects effectively enclose a surface).

Sélectionner des zones (des "areas") par leur nom

However areas are usually selected by running a separate special query (supported by the Overpass Turbo client) on their known naming tags for the OSM object they represent (Nominatim is used to process, recognize and index several naming tags, including tags for translated names) and storing the found areas into a named result set: any matching area with relevant tags will be stored in that named result set:

  {{geocodeArea:"United Kingdom"}}->.a; /* finds an area tagged with "name"="United Kingdom" */
  {{geocodeArea:"GB"}}->.a;             /* finds an area tagged with "ISO3166-1"="GB" */

Note that the "geocodeArea" queries above will only return (into the result set "a") only Overpass areas matching the indicated name, but no OSM objects (nodes, ways or relations). Not all possible areas are returned by such queries, only the first matching one is returned: this is using an Overpass Turbo syntax extension, which allows performing a search by name (using Nominatim) and then convert the returned object into a suitable Overpass area id. These queries will not work directly on basic Overpass API servers, and you'll need to specify the constant area id yourself.

Without using the Overpass Turbo extension (which is more limited and may not return the area you expect), you can still use the Overpass API construct to get the same thing (but without being limited to only one area in the result set, and with more possibilities to filter the selectedunion

area by explicit tags):

  ( area[name="United Kingdom"]; )->.a;  /* or more selectively: */
  ( area["ISO3166-1"="GB"][admin_level=2]; )->.a;

Then this named result set can be used to filter objects by intersection with this area. The following filter clause will keep only objects from the current result set that are insersecting with any area present in the named result set "a":

  /*your query here*/(area.a)

Note that this filter will keep any object (nodes, ways, relations, or areas) in the main query that are fully contained in any area in "a", or partially covered by any one of them, or any object in the query whose surface completely encloses any area in "a". For example, if the selected area is the area of a city, the filter will return all local subdivisions (districts, quarters) in that city, all natural features (such as lakes) in that city, and all subdivisions that are including that city (nodes, ways, relations and areas in the input set), unless you use additional tag filters in the main query to be more selective (such as ["admin_level"="8"] for just selecting OSM objects representing that city; the closed objects for the surrounding cities that also tagged with ["admin_level"="8"], and that are sharing only a common border with the selected city will normally not be returned because the surface of their mutual intersection should be empty and limited to these common borders; however any nodes and ways that are in the input set, and that are also falling exactly on the border of the selected area will be returned, independantly of other relations or closed ways in which they could be members).

Recursion clauses ("recursion filters")

Or recursion forward or backward about membership links

  (r)
  (w)
  (n)
  (br)
  (bw)
  (bn)
  (>)
  (>>)
  (<)
  (<<)

Special clauses ("special filters")

Or special clauses of the form "(type:value)", e.g. the "(around:value)" clause.

More details are provided in the respective parts of the Usage Examples.

About the links

Most examples are illustrated with showing links to a map. This is still a very experimental solution. The bounding box is fixed to show always the German town Bonn. And some queries take quite a lot of time, maybe over a minute if none of the needed data is in the cache on the server. The symbols are ugly, but this could also be changed for a mashup layer aiming at end users. They should be primarily easy to find.

Usage examples: All data in a bounding box

Let's start looking at some examples for queries by looking at querying by bounding box.

The bounding box

The bbox-query lets you download all nodes, ways or relations from the given bounding box. Specify with:

  • s the southern limit in decimal degrees (lowest latitude, measured along a meridian from the nearest point on the Equator, negative in the Southern Hemisphere)
  • w the western limit in decimal degrees (lowest longitude, measured along a parallel from the nearest point on the Greenwich meridian, negative in the Western Hemisphere)
  • n the northern limit in decimal degrees (highest latitude, measured along a meridian from the nearest point on the Equator, positive in the Northern Hemisphere)
  • e the eastern limit in decimal degrees (highest longitude, measured along a parallel from the nearest point on the Greenwich meridian, positive in the Eastern Hemisphere))

These coordinates are specified in the OSM database and in the OverPass API by vertically projecting the real points to nodes on the WGS84 ellipsoid.

Please note also that the Overpass QL form has the implicit order (s, w, n, e). This is more concise than the explicit XML syntax, but of course requires some care to get the order right. The western limit is higher than the eastern limit if and only if your query surpasses the longitude ±180.0 degrees with a bounding box passing through the Antimeridian (in that case the query is equivalent to the union of two bounding boxes on each side the Antemeridian.

For areas that aren't boxes, see the Poly command.

Retrieving all nodes within a bounding box

All nodes in a small sample bounding box:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <bbox-query e="7.157" n="50.748" s="50.746" w="7.154"/>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node(50.746,7.154,50.748,7.157);
out body;

Display result: OpenLayers map, JSON, XML.

Ways

In a similar fashion, you can get all ways of the bounding box. A way is found not only if it has a node inside the bounding box but also if it just crosses somewhere the bounding box.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="way">
    <bbox-query e="7.157" n="50.748" s="50.746" w="7.154"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
way(50.746,7.154,50.748,7.157);
out body;

Display result: OpenLayers map, JSON, XML.

Relations

A relation is found in a bounding box if it has a member of type node or way within the bounding box.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="relation">
    <bbox-query e="7.157" n="50.748" s="50.746" w="7.154"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
relation(50.746,7.154,50.748,7.157);
out body;

Display result: OpenLayers map, JSON, XML.

Usage examples: Simple queries for tags and bounding boxes

Wherever you see the this symbol: overpass turbo icon, you can click it to use overpass turbo for inspecting the query and its results.

Finding something in the OpenStreetMap data always means to search for a location or for the values of certain tags. You can choose any key for the tag in the following examples. In a first step, we find objects by their names, thus we search for certain values of the key "name".

By exact name

In our first example, we search for a node by the value of its name tag:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node["name"="Gielgen"];
out body;

Display result: OpenLayers map, JSON, XML.

By exact name and rough location

If this isn't exact enough, you could also specify a bounding box to get results from only within a certain bounding box. The coordinate order is (lower lat., lower lon., upper lat., upper lon.). If you don't have a bounding box, the following example may fit better to you:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  (50.7,7.1,50.8,7.2);
out body;

Display result: OpenLayers map, JSON, XML.


Non-exact names

But even when you don't know the exact name, you can find the object. For that purpose, Overpass API supports (POSIX extended) regular expressions. We give a couple of examples for useful regular expressions.

The first example searches for any node that contains the substring "holtorf" in its name:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="holtorf"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"holtorf"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

The second example searches for any node that has the substring "Holtorf" as the beginning of the name:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="^Holtorf"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"^Holtorf"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

The third example searches for any node that has the substring "holtorf" as the end of the name:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="Holtorf$"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"holtorf$"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

Of course you could also search for "^Holtorf$", but this is the same as a simple search for equal value.

And you can search case insensitive with regular expressions by enclosing both variants in brackets:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="[hH]oltorf"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"[hH]oltorf"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

Accents and decorated characters

A lot of European languages have modified variants of the well known Latin characters, not only "e" but also "é" or "ê". You can obtain them with a regular expression:

By list listing candidates:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="H[oôóòö]ltorf" />
    <bbox-query s="50.7" w="7.1" n="50.8" e="7.25" />
  </query>
  <print />
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"H[oôóòö]ltorf"]
  (50.7,7.1,50.8,7.25);

out body;

Or by leaving a dot wildcard:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="H.ltorf" />
    <bbox-query s="50.7" w="7.1" n="50.8" e="7.25" />
  </query>
  <print />
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"H.ltorf"]
  (50.7,7.1,50.8,7.25);

out body;

Please note:

  • A single wildcard dot replaces a single UTF-8 encoded code point, not necessarily only a single byte in that encoding (only the characters in the 7-bit US-ASCII subset are encoded in UTF-8 on one byte). So a single dot matches "e" as well as "é" or "ê" (but also any other letter, including non-Latin; "-" or a space), but not "ø̄" which is not encodable as a single codepoint, but as the precombined letter barred o followed by the combining macron, or as the precombined letter o with macron followed by the combiningbar overlay, or as the base letter o followed in any order by the combining macron and the combining bar overlay).
  • Letters with combining diacritics should be stored in the database in Unicode “Normalized Form Composed”, or NFC. Most letters with diacritics used in modern European languages are composable in NFC, but not every pair consisting in a base letter with by a single combining diacritic are composable into a single code point, and some letters with two combining diacritics are still encodable in NFC with a single codepoint, such as "ế" used in Vietnam and will be matched by a single wildcard dot), instead of the canonically equivalent encoding as the base letter "e" followed by the two distinct combining diacritics in either order (one of this order is the “Normalized Form Decomposed” (NFD) used by some OSes like MacOS (which prefers storing filenames encoded as NFD in its filesystem), or by some keyboard drivers or text editors.
  • For this reason it is not easy to match all possible encoding forms of the same base letter e (including lettercase variants) with or without one or more combining diacritics: the Overpass API still does not support matching regular expressions based on collation (whose rules depend on the language and script used, and on the collator used for that language and script, and on the collation strength parameters (such as letter case sensitivity). Instead you can enumerate expected the letter variants in [square] brackets, or use unions of queries for each orthography or encoding of the letter you're looking for.

One or another name

If you want to allow two alternative values, you can use a pipe for that.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" regv="holtorf|Gielgen"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"~"holtorf|Gielgen"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

More information about (POSIX extended) regular expressions can be found on the console or by your favourite search engine with "man 7 regex".

Negation

Regular expressions don't allow negation on their own. For that reason, there is an explicit negation operator in Overpass QL.

For example, the following query yields all ways that do not have a highway key value:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="way">
    <has-kv k="highway" modv="not" regv="."/>
    <bbox-query e="7.18" n="50.75" s="50.74" w="7.17"/>
  </query>
  <print limit="" mode="body" order="id"/>
</osm-script>
try it yourself in overpass-turbo
way
  ["highway"!~"."]
  (50.74,7.17,50.75,7.18);
out body;

Display result: OpenLayers map, JSON, XML.

As a second example, you can restrict a query for bus stops to those that have a shelter. Technically, we search for nodes with "highway"="bus_stop" and tag "shelter" present, but not set to "no".

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="highway" v="bus_stop"/>
    <has-kv k="shelter"/>
    <has-kv k="shelter" modv="not" v="no"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["highway"="bus_stop"]
  ["shelter"]
  ["shelter"!="no"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

The same thing with regular expressions:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="highway" v="bus_stop"/>
    <has-kv k="shelter"/>
    <has-kv k="shelter" modv="not" regv="no"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["highway"="bus_stop"]
  ["shelter"]
  ["shelter"!~"no"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

Multiple tags

Of course you can search also for nodes that have a tag "highway" to value "bus_stop" and a tag "shelter" to value "yes":

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="highway" v="bus_stop"/>
    <has-kv k="shelter" v="yes"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["highway"="bus_stop"]
  ["shelter"="yes"]
  (50.7,7.1,50.8,7.25);
out body;

Display result: OpenLayers map, JSON, XML.

Streets and other ways

Every of the above queries also works for ways or relations. We search for the street "Gielgenstraße" within the now well-known bounding box:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="way">
    <has-kv k="name" v="Gielgenstraße"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
way
  ["name"="Gielgenstraße"]
  (50.7,7.1,50.8,7.25);
out;

Display result: OpenLayers map, JSON, XML.

Please note that you need to also request the nodes of the way if you want to display the way in map (or need the coordinates for another reason. This is done with an extra-recurse down statement. To get also the way, we put both in an union statement. All these statements are explained further down.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="way">
    <has-kv k="name" v="Gielgenstraße"/>
    <bbox-query e="7.25" n="50.8" s="50.7" w="7.1"/>
  </query>
  <union>
    <item />
    <recurse type="way-node"/>
  </union>
  <print/>
</osm-script>
try it yourself in overpass-turbo
(
  way
    ["name"="Gielgenstraße"]
    (50.7,7.1,50.8,7.25);
  >;
);
out;

Relations

And now we search for the relation of "network"="VRS" and "ref"="636". This is a local bus service. As the network shortcut is unique, we don't need a bounding box or any other similar aid.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="relation">
    <has-kv k="network" v="VRS"/>
    <has-kv k="ref" v="636"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
relation
  ["network"="VRS"]
  ["ref"="636"];
out body;

Display result: OpenLayers map, JSON, XML.

Query by element id

If you want a specific id from the database, you can query for it. We give

  • an example for a node:
Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <id-query ref="507464799" type="node"/>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node(507464799);
out;

Display result: OpenLayers map, JSON, XML.

  • an example for a way:
Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <id-query ref="24777894" type="way"/>
  <print/>
</osm-script>
try it yourself in overpass-turbo
way(24777894);
out;

Display result: OpenLayers map, JSON, XML.

  • an example for a relation:
Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <id-query ref="1745069" type="relation"/>
  <print/>
</osm-script>
try it yourself in overpass-turbo
relation(1745069);
out;

Display result: OpenLayers map, JSON, XML.

The union operator: combining results and forming sets

Combining results with the union operator

The "union" statement means the set of brackets "(...);" in QL. The output of that union is placed in "_".

And, finally, we search for all kind of objects with a certain tag within a bounding box. You need to repeat the tag for every type and to use the union operator. To allow us displaying everything on a map, we also ask for the nodes and ways that are referred by the relations and ways in the result:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <union>
    <query type="node">
      <has-kv k="amenity" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="way">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="relation">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
  </union>
  <union>
    <item/>
    <recurse type="down"/>
  </union>
  <print/>
</osm-script>
try it yourself in overpass-turbo
(
  node
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
  way
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
  rel
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
);
(._;>;);
out;

Display result: OpenLayers map JSON, XML.

The default set "_" and recalling the default set "._"

Similar to a default variable in the programming language PERL, Overpass QL has a default set, called "_". Let's look at the last query again:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <union>
    <query type="node">
      <has-kv k="amenity" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="way">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
    <query type="relation">
      <has-kv k="amenity" modv="" v="fire_station"/>
      <bbox-query e="7.3" n="50.8" s="50.6" w="7.0"/>
    </query>
  </union>
  <union>
    <item/>
    <recurse type="down"/>
  </union>
  <print/>
</osm-script>
try it yourself in overpass-turbo
(
  node
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
  way
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
  rel
    ["amenity"="fire_station"]
    (50.6,7.0,50.8,7.3);
);
(
    ._;
    >;
);
out;

Display result: OpenLayers map JSON, XML.

The query consists of

  • A first union (nodes, ways, relations), indicated by the "union" statement or first set of brackets "(...);" in QL. The output of that union is placed in "_".
  • A second union "(._;>;);" in QL, consisting of
    • recalling the default set ("item" or "._;" in QL)
    • recurse down, (">;" in QL)

The output of that second union is again placed in "_", which is then printed.

The print command prints the content of the container "_" at execution time. This comes very close to "the last set defined".

Other named sets

The item standalone query consists only of an input set prefix. It takes the input set specified by its prefix. This is in particular useful for union statements: it reproduces its input set as (part of the) result of the union statement. The most common usage is the usage with the default input set:

  ._;

In the context of a union statement, the following will return all items in the default input set along with the recurse down result.

  (._; >;);

But of course other sets are possible too:

  .a;

In the context of a union statement:

  (.a; .a >;);

Note: Subsequent statements in a union statement are not impacted by the item statement. In particular `.a;` does not add the contents of the input set to the default item set "_".

The item statement can also be used as filter.

Union and assigning sets: .->a

Overpass has an imperative execution model. In particular, the statements are executed one after another, and each statement is terminated by a semicolon. Each statement puts its results into a container in its memory named by default "_". If a statement needs input, it reads its input from "_". For example, the print statement reads from "_". Sometimes it is useful to use more than one container during a more complex query. In this case, the output can be redirected to another container, e.g. with name "x". This is what the above syntax controls.

The union block statement is written as a pair of parentheses. Inside the union, any sequence of statements can be placed, including nested union and foreach statements.

  (statement_1; statement_2; )[->.result_set];

It takes no input set. It produces a result set. Its result set is the union of the result sets of all sub-statements, regardless of whether a sub-statement has a redirected result set or not.

Example:

  (node[name="Foo"];way[name="Foo"];);

This collects in the first statement all nodes that have a name tag "Foo" and in the second statement all ways that have a name tag "Foo". After the union statement, the result set is the union of the result sets of both statements.

The result set of the union statement can be redirected with the usual postfix notation.

Example:

  (node[name="Foo"];way[name="Foo"];)->.a;

Same as the preceding example, but the result is written into the variable a.

Limitation : Note foreach and print statements cannot be sub-element of element union.

Recursion: ">", "<", etc

Recursion clauses

We already met the recursion clauses:

  (r)
  (w)
  (n)
  (br)
  (bw)
  (bn)
  (>)
  (>>)
  (<)
  (<<)

We'll now have a look at some of these.

Why we need recursion

In general, you will be interested in complete data, rather than just elements of a single type. First, there are several valid definitions of what "complete map data" means. The first unclear topic is what to do with nodes outside the bounding box which are members of ways that lie partly inside the bounding box.

The same question repeats for relations. If you wait for a turn restriction, you may prefer to get all elements of the relation included. If, for example, your bounding box hits the border of Russia, you likely don't want to download ten thousand kilometers of boundaries around half the world.

A second question for relations is whether relations on relations should be included.

For that reason, we subsequently give examples for several variants of map calls. It is a discipline where the query paradigm shows its strength: you can construct a query of any flavor you want. Just choose from the examples below or modify them to your needs.

The particular statements of the calls are explained in the more advanced sections further below.

Récursion en aval: ">" and ">>"

Recursing up: "<" and "<<"

This call includes all nodes in the bounding box, all ways that have such a node as member, and all relations that have such a node or such a way as members. Please observe that not all returned ways or relations are displayed in OpenLayers because Open Layers requires all nodes of a way or members of a relation to be present.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <union into="_">
    <bbox-query e="7.157" n="50.748" s="50.746" w="7.154"/>
    <recurse type="up"/>
  </union>
  <print mode="meta"/>
</osm-script>
try it yourself in overpass-turbo
(
  node(50.746,7.154,50.748,7.157);
  <;
);
out meta;

More about this query below.

Recursing up and down: Completed ways and relations

This call includes all nodes in the bounding box, all ways referring to any of these nodes, all member nodes of these ways whether these are inside the bounding box or not, all relations that have such a node or such a way as a member, and their node and way member, and even the nodes of these ways. Note that due to the involved relations, objects from quite far outside the bounding box are included.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <union into="_">
    <bbox-query e="7.157" n="50.748" s="50.746" w="7.154"/>
    <recurse type="up"/>
    <recurse type="down"/>
  </union>
  <print limit="" mode="meta" order="id"/>
</osm-script>
try it yourself in overpass-turbo
(
  node(50.746,7.154,50.748,7.157);
  <;
  >;
);
out meta;

More about this query below.

More complex recursion

See Overpass API/Overpass_API_by_Example#More_complex_recursion.

Special clauses: around and poly

"around" - finding something near something else

A less technical way to get one of multiple results can be to find something by providing a nearby location. For example, you can search for a location called "Gielgen" in a 1000 meter radius of a location called "Bonn".

(Be aware that the computations are made with a non-spheroid formula (see more here), that may cause some approximations)

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Bonn"/>
  </query>
  <query type="node">
    <around radius="1000"/>
    <has-kv k="name" v="Gielgen"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node["name"="Bonn"];
node
  (around:1000)
  ["name"="Gielgen"];
out body;

Display result: OpenLayers map, JSON, XML.

Note: When you want to query for or node or way with the same property, you can group them with brackets, i.e. (node["amenity"="fuel"]; way["amenity"="fuel"];) but this does not work for the around part.

Not clear what you mean by this. By using a named inputset you can of course also use multiple statements with around filter. Please revise your edit accordingly Mmd (talk) 17:49, 2 June 2018 (UTC)

Select region by polygon

In addition to bounding boxes, now also polygons can be used to cut out a region for download. A simple example is a part of my home town in Germany:

try it yourself in overpass-turbo
(
  node(poly:"50.7 7.1 50.7 7.12 50.71 7.11");
  <;
);
out meta;

Display result: XML, JSON

More general, the examples from above can be adapted to the polygon variant: Just replace the bbox condition by the polygon condition. The only restriction is that polygons can only be used as borders for nodes. Please use one of the various recurse statements to get ways and relations from it.

If you want to use a polygon like the output of rel2poly.pl as a boundary, you can convert it with the following bash script poly2request.sh:

#!/usr/bin/env bash

echo -n '(node(poly:"'
awk '{ if ($1 != "1" && $1 != "polygon" && $1 != "END") printf $2" "$1" "; }'
echo '");<;);out;'

Now you can get your download with e.g.

./poly2request.sh <polygon.txt >request.txt
wget --post-file=request.txt http://overpass-api.de/api/interpreter

Control output format (print, out)

Print does what its name lets you expect: it prints the contents queried so far as returned data. Thus, almost every query ends with a print statement. For the sake of brevity, print has been renamed to out; in Overpass QL.

Degree of verbosity

Print exists in four different degrees of verbosity, which are specified by the mode attribute: body (default), skeleton, ids_only, and meta. Those are explained by the following examples, giving the relevant parts of the query and the result. The more concise the output is, the faster the query runs. For that reason, skeleton is used in this guide for the OpenLayers layers. meta is likely to be the best choice if you want to edit the data. If you are unsure what you need, try body first.

XML QL Description
<print/> out;
or
out body;
The normal print mode.
<print mode="skeleton"> out skel; The skeleton print mode is somewhat shorter than the usual print mode: No tags are printed in this mode, only ids, child elements, and coordinates of nodes.
<print mode="ids_only"> out ids; ids_only is the shortest print mode; only ids are printed. ids_only is shortened to ids in Overpass QL. Note that this doesn't work with OpenLayers because no coordinates are returned.
<print mode="meta"> out meta; meta is the most complete mode. Beside child elements and tags, also the meta data (timestamp, version, changeset, user name and id) is printed.

Normal (body) =

body is the default mode: ids, child elements, and tags are printed. If you want the mode body, you can omit the mode attribute.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <has-kv k="place" v="suburb"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  ["place"="suburb"];
out;

Display result: OpenLayers map, JSON, XML.

Concise (skeleton, skel)

The skeleton print mode is somewhat shorter: No tags are printed in this mode, only ids, child elements, and coordinates of nodes:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <has-kv k="place" v="suburb"/>
  </query>
  <print mode="skeleton"/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  ["place"="suburb"];
out skel;

Display result: OpenLayers map, JSON, XML.

Brief (ids_only, ids)

ids_only is the shortest print mode; only ids are printed. ids_only is shortened to ids in Overpass QL. Note that this doesn't work with OpenLayers because no coordinates are returned.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <has-kv k="place" v="suburb"/>
  </query>
  <print mode="ids_only"/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  ["place"="suburb"];
out ids;

Display result: OpenLayers map, JSON, XML.

Verbose (meta, meta)

meta is the most complete mode. Beside child elements and tags, also the meta data (timestamp, version, changeset, user name and id) is printed:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <has-kv k="place" v="suburb"/>
  </query>
  <print mode="meta"/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  ["place"="suburb"];
out meta;

Display result: OpenLayers map, JSON, XML.

This meta data is, in particular, necessary in order to handle the result in JOSM.

Order attribute for faster results (quadtile, qt)

You can also change the order of the elements. By default, elements are ordered by their id (i.e., order="id"). You get faster results if you allow elements to be ordered by their location (i.e., order="quadtile", or qt in Overpass QL).

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
    <has-kv k="place" v="suburb"/>
  </query>
  <print order="quadtile"/>
</osm-script>
try it yourself in overpass-turbo
node
  ["name"="Gielgen"]
  ["place"="suburb"];
out qt;

Display result: OpenLayers map, JSON, XML.

Limit attribute to limit elements (limit, n)

It is also possible to limit the number of printed elements:

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
  </query>
  <print limit="2"/>
</osm-script>
try it yourself in overpass-turbo
node["name"="Gielgen"];
out 2;

Display result: OpenLayers map, JSON, XML.

This limits the output to at most two nodes.

Geometry attributes

XML QL Description
<print mode="geom"> out geom; geom please refer to the Overpass QL wiki page.
<print mode="center"> out center; center adds the center of the object's boundingbox to the output, not guaranteed to be on the object's area.
<print mode="bb"> out bb; bb: please refer to the Overpass QL wiki page.

Also see Overpass API/Overpass API by Example.


Geometry attribute (center, center)

Add the center of the object's boundingbox to the output, not guaranteed to be on the object's area.

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script>
  <query type="relation">
    <has-kv k="boundary" v="postal_code"/>
    <has-kv k="postal_code" v="65343"/>
  </query>
  <print geometry="center"/>
</osm-script>
try it yourself in overpass-turbo
rel["boundary"="postal_code"][postal_code=65343];
out center;

OSM Script options

Choose file format (output="json", [out:json])

You can get the result as JSON or as XML. By default, you get the data as XML. To get the result as JSON, just add a JSON request to the query header (before the first statement):

Overpass XML Overpass QL
link=http://overpass-turbo.eu/?Q=%3Cosm-script%20output%3D%22json%22%3E%0A%20%20%3Cquery%20type%3D%22node%22%3E%0A%20%20%20%20%3Chas-kv%20k%3D%22name%22%20v%3D%22Gielgen%22%2F%3E%0A%20%20%3C%has-kv k="name" v="Gielgen"/> 2Fquery%3E%0A%20%20%3Cprint%2F%3E%0A%3C%2Fosm-script%3E&C=50.73515;7.20519;14&R
<osm-script output="json">
  <query type="node">
    <has-kv k="name" v="Gielgen"/>
  </query>
  <print/>
</osm-script>
try it yourself in overpass-turbo
[out:json];
node["name"="Gielgen"];
out body;

CSV (Comma Separated Values) format: see Overpass QL wiki page.

Display result: OpenLayers map, JSON, XML.

Resource management options (osm-script)

The osm-script is silently added if you don't specify it explicitly when using the XML syntax. The reason to specify one explicitly is to tweak the resource management options by setting optional XML attributes (equivalent bracketted options may also be specified in an empty statement at start of your query when using the QL syntax).

Overpass XML Overpass QL
try it yourself in overpass-turbo
<osm-script timeout="900" element-limit="1073741824">
  <bbox-query s="51.15" w="7.0" n="51.35" e="7.3"/>
  <print/>
</osm-script>
try it yourself in overpass-turbo
[timeout:900][maxsize:1073741824];
node(51.15,7.0,51.35,7.3);
out;

This query extends the timeout from 3 minutes to 15 minutes (written as 900 seconds). Additionally, the soft quota for memory usage is set to 1 GiB (equals 1073741824 byte).

Warning: when running this example, more than 100 MiB of data will be retrieved (even if it does not recurse up to give all details like in the first example, here it will only retrieve a flat list of nodes with their tags). Overpass will alert you if you run it directly in your browser to render the data on the map, the browser tab may crash if you continue loading it. The results of such large requests should be downloaded for processing by other tools.

These resource limits cannot be set to arbitrary high values: each Overpass API instance may refuse to extend them above some threshold (depending on server capabilities or current server load), or the query may just fail with an error message (and non-OK HTTP server error status).

See Also