Overpass API
The OSM3 project has a new name! Along with its very own domain: http://www.overpass-api.de/:
(Know formerly as OSM3S, "OSM Server Side Script" or simply by the IP address 78.46.81.38.)
The public servers overpass-api.de and overpass.rambler.ru are up and running. See OSM3S/status for details.
Contents |
Introduction
The Overpass API (or OSM3S) is a read-only API that serves up raw XML encoded OSM map data. Overpass API includes functionality similar to that of XAPI.
Currently public available servers are
- http://overpass.osm.rambler.ru/ with query base address http://overpass.osm.rambler.ru/cgi/ (8 cores, 64 GB RAM).
- http://www.overpass-api.de/ with query base address http://www.overpass-api.de/api/ (4 cores, 4 GB RAM).
The rambler is intended for production use while overpass-api.de is dedicated to always the latest version of Overpass API.
Overpass API can be configured to operate as both a web-based API and a command-line program that pulls from a local store of OSM data.
- See OSM3S/install for details of how to install OSM3S on your system.
- See OSM3S/versions for an overview of the existing versions and changelog.
Queries to the Overpass API are in XML form. See the semantics explained below.
Public Transport Example
An interesting example of how the OSM3S API can be integrated into an application - a service to generate line diagrams for public transport.
- Example one here
- Example two here
(Please be patient - each request can take up to 10 seconds to generate, depending on server load.)
The map query
Before we get to a detailed syntax explanation, we present the probably most common use case, the map query, to collect all data from a given bounding box:
<union> <bbox-query s="51.249" n="51.251" w="7.148" e="7.152"/> <recurse type="node-relation" into="rels"/> <recurse type="node-way"/> <recurse type="way-relation"/> </union> <print/>
The attributes n and s are used for the latitudes of the bounding box, w and e for the longitudes. See more details about bbox below.
Simple Usage examples
The following examples all use only two statements. This is, a statement collecting data followed by the print statement to show the data. A full reference of the command is available at http://www.overpass-api.de/
All of the following examples can be tested by copying the snippets to http://www.overpass-api.de/query_form.html.
Id-Query
With id-query, you can retrieve a single element by id. This query is available for nodes, ways or relations. You select among the type of element by the type attribute.
Example: Get node #42000000.
<id-query type="node" ref="42000000"/> <print/>
Example: Get way #42000000.
<id-query type="way" ref="42000000"/> <print/>
Example: Get relation #100000.
<id-query type="relation" ref="100000"/> <print/>
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. Print exist in three different degrees of verbosity (the query statement will be explained afterwards):
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print mode="body"/>
This is the usual mode: ids, child elements, and tags are printed. You can also omit mode="body"; it is the default value.
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print/>
This mode is slightly shorter: No tags are printed in this mode, only ids, child elements, and coordinates of nodes.
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print mode="ids_only"/>
This mode is the shortest print mode: Only ids are printed.
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print mode="meta"/>
This is the most complete mode: beside child elements and tags, also the meta data (timestamp, version, changeset, user name and id) is printed.
You can also change the order of the elements. By default, elements are ordered by their id (i.e. order="by_id"). You get faster results if you allow elements to be ordered by their location (i.e. order="quadtile").
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print order="quadtile"/>
It is also possible to limit the number of printed elements:
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print limit="2"/>
This limits the output to at most two ways.
Bbox-Query
The bbox-query lets you download all nodes from the given bounding box. Specify with
- s the southern limit (bottom lat)
- n the northern limit (top lat)
- w the western limit (usually lower lon)
- e the eastern limit (usually higher lon)
Note that the western limit is higher than the eastern limit if and only if you query surpasses the longitude +/-180.0.
<bbox-query s="51.2" n="51.3" w="7.1" e="7.2"/> <print/>
Query
The query statement collects all elements which have a tag with a certain key-value pair, a certain key, or a combination of certain keys and/or key-value-pairs.
Get all nodes that have the key name with value Am Hofe.
<query type="node"> <has-kv k="name" v="Am Hofe"/> </query> <print/>
Get all ways that have the key name with value Am Hofe.
<query type="way"> <has-kv k="name" v="Am Hofe"/> </query> <print/>
Get all relations that have the key ref with value CE 61.
<query type="relation"> <has-kv k="ref" v="CE 61"/> </query> <print/>
You can combine several has-kv statements. You then get all elements that have all the corresponding tags.
<query type="relation"> <has-kv k="network" v="VRR"/> <has-kv k="ref" v="604"/> </query> <print/>
Or you can combine a bbox-query with one or more has-kv statements. This is possible only for nodes.
<query type="node"> <bbox-query s="51.2" n="51.3" w="7.1" e="7.2"/> <has-kv k="highway" v="bus_stop"/> </query> <print/>
You can omit in has-kv the attribute v to get all elements with a certain value. To keep the resonse small, we still have a bbox-query in this sample query.
<query type="node"> <bbox-query s="51.2" n="51.3" w="7.1" e="7.2"/> <has-kv k="railway"/> </query> <print/>
Advanced Usage examples
The following examples introduce the remaining commands recurse and around. They only make sense in combination with other commands.
Again, all of the following examples can be tested by copying the snippets to http://www.overpass-api.de/query_form.html.
Recurse
With recurse, you query for membership relations. It is available for ways to get all referred nodes, for relations to get all member nodes or member ways. Or the other way round, to get for a node, way or relation the ways or relations the element is member of. You select among the type of element by the type attribute.
Example: Get the nodes of all relations that have the key ref with value CE 61. In fact, get all bus stops served by CE 61.
<query type="relation"> <has-kv k="ref" v="CE 61"/> </query> <recurse type="relation-node"/> <print/>
Get the ways of all relations that have the key ref with value CE 61. In fact, that is the itinerary served by CE 61.
<query type="relation"> <has-kv k="ref" v="CE 61"/> </query> <recurse type="relation-way"/> <print/>
Get the nodes of the above mentioned ways. You don't get the bus stops, but that is intentionally - see below at the union examples.
<query type="relation"> <has-kv k="ref" v="CE 61"/> </query> <recurse type="relation-way"/> <recurse type="way-node"/> <print/>
Get all relations that have the nodes named Lichtscheid as members. These are the bus lines stopping there.
<query type="node"> <has-kv k="name" v="Lichtscheid"/> </query> <recurse type="node-relation"/> <print/>
Get all the ways that have a node member within the given bounding box.
<bbox-query s="51.249" n="51.251" w="7.149" e="7.151"/> <recurse type="node-way"/> <print/>
And we can also get relation members of relations:
<query type="relation"> <has-kv k="name" v="VRR Buslinien"/> </query> <recurse type="relation-relation"/> <print/>
Or the same thing backwards:
<query type="relation"> <has-kv k="ref" v="CE 65"/> </query> <recurse type="relation-backwards"/> <print/>
Around
Around allows you to get all nodes in the closer environment of one or more given nodes. For example, get all nodes that are at most 100 meters around the nodes called Lichtscheid:
<query type="node"> <has-kv k="name" v="Lichtscheid"/> </query> <around radius="100"/> <print/>
You can also combine this with query to get only nodes that have a certain tag:
<query type="node"> <has-kv k="highway" v="bus_stop"/> <has-kv k="name" v="Lichtscheid"/> </query> <query type="node"> <around radius="1000"/> <has-kv k="highway" v="bus_stop"/> </query> <print/>
This gives you all bus stops near the bus stop(s) called Lichtscheid.
Building blocks
We still have some helper statements to explain, in particular union, item, the variable mechanism, osm-script, and foreach.
Again, all of the following examples can be tested by copying the snippets to http://www.overpass-api.de/query_form.html.
Union
Union allows you to group the results of several queries. For example, you can get all nodes that have name Lichtscheid or Müngstener Straße.
<union> <query type="node"> <has-kv k="name" v="Lichtscheid"/> </query> <query type="node"> <has-kv k="name" v="Müngstener Straße"/> </query> </union> <print/>
Another usage would be to get a relation with all of its members, including the nodes of member ways.
<union> <query type="relation"> <has-kv k="ref" v="CE 61"/> </query> <recurse type="relation-node" into="nodes"/> <recurse type="relation-way"/> <recurse type="way-node"/> </union> <print/>
This needs some explanation:
- query collects the relations with ref CE 61. It writes the result to the default variable _. And the embracing union collects the data.
- recurse relation-node collects the nodes that are members of the above found relations. The result is placed in the variable nodes (we don't need it there anymore, just to keep relations in the default variable). And it is collected by the embracing union.
- recurse relation-way sees again the relations from the default variable and returns the ways that are members of the default variable's relations. Again, the embracing union collects the results.
- recurse way-node finally returns the nodes that are members of the ways just collected. This is the last piece of data that goes into the union's result.
If you think this is complicated, you are right. I'm open to suggestions how to improve the statement semantics, but I haven't found anything systematic yet.
Now we are ready to assemble the map call, by combining a bbox-query with several recurse statements and embracing the whole thing with an union.
Item
Part of the idea behind item and variables have you already seen in the preceeding example: every statement fetches its input from a variable and puts its output into a variable. If you omit the variable name, it defaults to _. This makes in possible to remove almost all explicit specifications of variables. The input is always fetched from the variable named by the attribute from, the output is always put into the variable specified with into.
<query type="way" into="foo"> <has-kv k="name" v="Am Hofe"/> </query> <print from="foo"/>
E.g. this does the same as the respective example at print, but it uses the explicitly stated variable foo.
To make this concept fully versatile, item allows you to specify a set as input in union and query:
<query type="relation"> <has-kv k="network" v="VRR"/> <has-kv k="ref" v="645"/> </query> <recurse type="relation-node" into="stops"/> <query type="node"> <around from="stops" radius="100"/> <has-kv k="highway" v="bus_stop"/> </query> <union> <item/> <recurse type="node-relation"/> <query type="node"> <around from="stops" radius="100"/> <has-kv k="park_ride"/> </query> </union> <print/>
Here, in the middle, the item ensures that the beforehand collected data for bus_stop is included in the results of union. This also shows how the variable stops is necessary to make the query possible.
<bbox-query s="51.15" n="51.35" w="7.0" e="7.3"/> <recurse type="node-way"/> <query type="way"> <item/> <has-kv k="highway" v="motorway"/> </query> <print/>
The item in query restricts the possibly found items to those already found in the step before, with recurse. Thus, we have a complete query to find ways with arbitrary tags within a bbox.
Osm-Script
The osm-script is silently added if you don't specify it explicitly. The reason to specify one explicitly is to tweak the resource management:
<osm-script timeout="900" element-limit="1073741824"> <bbox-query s="51.15" n="51.35" w="7.0" e="7.3"/> <print/> </osm-script>
This 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).
Foreach
<query type="relation"> <has-kv k="type" v="multipolygon"/> <has-kv k="name"/> </query> <foreach into="pivot"> <union> <recurse type="relation-way" from="pivot"/> <recurse type="way-node"/> </union> <make-area pivot="pivot"/> </foreach>
This is the essential part of the rule that creates the areas. We do not explain the make-area here. The first part with query collects all relations with certain properties. In the second part, we want to do something with each element in the result of query. This does foreach. The body of the loop is executed once for every element in the input set, containing exactly this single element in the output set, here named as pivot.
Meta data
Beside the special mode of print, there are two statements dedicated to query for specific meta data, user and newer.
User
You can select all data that has been touched the last time by a particular user. Choose the user name (for example, mine):
<user name="Roland Olbricht"/> <print mode="meta"/>
Or choose a user id:
<user uid="65282"/> <print mode="meta"/>
This statement can also be used within a query statement. It then restricts the result to data that has been last touched by the provided user:
<query type="node"> <user name="Roland Olbricht"/> <has-kv k="highway" v="bus_stop"/> <bbox-query s="51.2" n="51.35" w="7.05" e="7.3"/> </query> <print mode="meta"/>
Newer
Newer can be used within query statement (and not as a standalone statement). It restricts the output to elements that are newer than the given date. The date must be in the format YYYY-MM-DDTHH:MM:SSZ. It refers, as the results, always to the timezone UTC.
<query type="node"> <newer than="2011-08-01T00:00:00Z"/> <has-kv k="highway" v="bus_stop"/> <bbox-query s="51.2" n="51.35" w="7.05" e="7.3"/> </query> <print mode="meta"/>
If you want to get all nodes newer than a certain date from a bbox, you can use query with an item substatement.
<bbox-query s="51.2" n="51.35" w="7.05" e="7.3"/> <query type="node"> <item/> <newer than="2011-08-01T00:00:00Z"/> </query> <print mode="meta"/>
XAPI Compability Layer
As requested on SOTM-EU 2011, Overpass API has got a compability layer for the most common XAPI queries. The base URLs are
http://overpass.osm.rambler.ru/cgi/xapi?
or
http://www.overpass-api.de/api/xapi?
The only substatial differences are that Overpass API does not (at least at the moment) deliver changeset, user, version and timestamp data (unless you want to re-add the data again to the main server, this data is anyway not necessary) and does not return relations that contain downloaded elements.
When you want to re-add elements in JOSM simply redownload the elements with 'File|Update selection' before you change them. Otherwise you get errors on 'File|Upload data' or showing the history.
Map call
Both versions of the map call are supported, where the variant with map has slight performance advantages:
http://www.overpass-api.de/api/xapi?map?bbox=7.1,51.2,7.2,51.3 http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3]
The order of the four numbers is left,bottom,right,top.
Tags and Bounding Boxes
For node, way, and relation it is possible to either combine arbitrarly many tag search criteria with exactly one or no value:
http://www.overpass-api.de/api/xapi?node[name=Wuppertal-Barmen] http://www.overpass-api.de/api/xapi?node[name=Wuppertal-Barmen][railway=halt] http://www.overpass-api.de/api/xapi?node[name=Wuppertal-Barmen][railway=*]
Or you can take at most one search criteria connecting by or: The following finds any node that has name Wuppertal-Barmen or Wuppertal-Oberbarmen.
http://www.overpass-api.de/api/xapi?node[name=Wuppertal-Barmen|Wuppertal-Oberbarmen]
In the same way, you can combine any of the above possibilities with at most one bounding box:
http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3] http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][highway=bus_stop] http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][name=Wuppertal-Barmen][railway=halt] http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][highway=bus_stop|traffic_signals] http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][highway=*]
Ways and relation behave similar: A way or relation belongs to a bounding box, if it has as member a node within the bounding box. Or for relations, if a member way has in turn a node in the bounding box as member.
http://www.overpass-api.de/api/xapi?way[name=Fischertal] http://www.overpass-api.de/api/xapi?way[name=Südstraße|Fischertal] http://www.overpass-api.de/api/xapi?way[name=Fischertal][bridge=yes] http://www.overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.2,51.3] http://www.overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.2,51.3][name=Südstraße] http://www.overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.2,51.3][name=Südstraße][bridge=yes] http://www.overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.2,51.3][name=Südstraße|Weststraße] http://www.overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.2,51.3][maxspeed=*]
Same story for relations:
http://www.overpass-api.de/api/xapi?relation[ref=603] http://www.overpass-api.de/api/xapi?relation[ref=603|613] http://www.overpass-api.de/api/xapi?relation[network=VRR][ref=603] http://www.overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.2,51.3] http://www.overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.2,51.3][ref=603] http://www.overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.2,51.3][network=VRR][ref=603] http://www.overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.2,51.3][ref=603|613] http://www.overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.2,51.3][ref=*]
Or also any kind of element:
http://www.overpass-api.de/api/xapi?*[ref=603] http://www.overpass-api.de/api/xapi?*[ref=603|613] http://www.overpass-api.de/api/xapi?*[network=VRR][ref=603] http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3] http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3][name=Weststraße] http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3][network=VRR][ref=603] http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3][ref=603|613] http://www.overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.2,51.3][ref=*]
Meta Data
You can add the directive [@meta] to any query to obtain also meta data in the results. This takes longer, but will allow you to open the results in JOSM.
http://overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?node[highway=bus_stop][bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?way[highway=motorway][bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?relation[route=bus][bbox=7.1,51.2,7.25,51.3][@meta] http://overpass-api.de/api/xapi?*[highway=*][bbox=7.1,51.2,7.25,51.3][@meta]
You can use [@newer=2011-07-01T00:00:00Z] to restrict the results to elements newer than the given date.
http://overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?way[bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?relation[bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?node[highway=bus_stop][bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?way[highway=motorway][bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?relation[route=bus][bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z] http://overpass-api.de/api/xapi?*[highway=*][bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z]
And you can of course also combine both.
http://overpass-api.de/api/xapi?*[highway=*][bbox=7.1,51.2,7.25,51.3][@newer=2011-07-01T00:00:00Z][@meta]
You can restrict the result to elements touched last by a specific user. In the example, it me Roland Olbricht.
http://overpass-api.de/api/xapi?*[highway=bus_stop][bbox=7.1,51.2,7.25,51.3][@user=Roland Olbricht][@meta] http://overpass-api.de/api/xapi?*[name=Karlsplatz][highway=bus_stop][@user=Roland Olbricht][@meta] http://overpass-api.de/api/xapi?*[highway=bus_stop][bbox=7.1,51.2,7.25,51.3][@user=Roland Olbricht][@meta]
Or use instead of the user name the user id. It is my user id in the example, 65282.
http://overpass-api.de/api/xapi?*[highway=bus_stop][bbox=7.1,51.2,7.25,51.3][@uid=65282][@meta] http://overpass-api.de/api/xapi?*[name=Karlsplatz][highway=bus_stop][@uid=65282][@meta] http://overpass-api.de/api/xapi?*[bbox=7.1,51.2,7.25,51.3][highway=bus_stop][@uid=65282][@meta]