RU:Overpass API/Overpass QL
Servers status · Versions · Development · Technical design · Installation · XAPI compatibility layer · Public transport sketch lines · Приложения · Source code and issuesOverpass turbo · Wizard · Overpass turbo shortcuts · MapCSS stylesheets · Export to GeoJSON · больше (русский) · Development · Source code and issues · Web siteOverpass Ultra · Examples · Overpass Ultra extensions · MapLibre stylesheets · URL Params · больше (русский) · Source code and issues · Web site
Обзор
Overpass QL это второй язык запросов для Overpass API и был разработан как альтернатива Overpass XML. Он имеет синтаксис языка Си: весь исходный код запроса разбивается на операторы (statements), и каждый оператор оканчивается точкой с запятой. Также имеет императивную семантику: операторы обрабатываются один за другим и изменяют контекст исполнения (execution state) в соответствии с их семантикой.
Контекст исполнения состоит из набора по умолчанию, возможно других именованных наборов, и для блочных операторов - стек. Набор может содержать узлы (nodes), пути (ways), отношения (relations) и области, а также смешанные типы в любом количестве. Наборы создаются как результирующие наборы (result sets) от операторов и считываются вложенными операторами как входные данные. За исключением случая, когда вы определяете именованный набор как входной или результирующий, все входные данные неявно считываются, а результаты записываются из/в в переменную по умолчанию - _ (одинарное подчеркивание). Имена для наборов могут состоять из букв, цифр и подчеркивания, но не могут начинаться с цифры. Как только результирующий набор (неявно или явно) присваивается существующему набору, его предыдущее содержимое будет замещено и более доступно не будет. Наборы всегда имеют глобальную видимость.
Есть несколько различных операторов. Вам почти всегда будет нужен оператор print, который называется action, потому что действует вне контекста исполнения (вывод). Остальные операторы подразделены на следующие группы:
- Самостоятельные запросы: Это завершенные сами по себе операторы.
- Фильтры: они всегда являются частью от оператора query и содержат интересующие селекторы и фильтры.
- Блочные операторы: это групповые операторы, и они, как и циклы, допускают прерывание выполнения.
- Настройки: различные вещи на подобие формата вывода ответа и прочего, что устанавливается один раз в самом начале работы.
Наборы
Overpass QL может работать с наборами. По умолчанию, все считывается и записывается из/в набор по умолчанию "_".
Чтобы послать что либо в другой набор используйте оператор "->". Пример:
(node[name="Foo"];)->.a;
сохранит все nodes с тегом name=Foo в набор "a".
Чтобы выбрать что либо из набора добавляйте точку с именем набора - ".a".
node.a[amenity=foo];
Вернет все nodes из набора "a", которые имеют тег amenity=foo.
Блочные операторы
Объединение
union это блочный оператор, описывающийся парой круглых скобок. Внутрь union может быть помещена любая последовательность операторов, включая вложенные операторы union и foreach.
(statement_1; statement_2; …)[->.result_set];
Он не имеет входного набора. Производит результирующий набор. Этот набор является объединением результирующих наборов всех вложенных операторов, независимо от того, есть ли у вложенного оператора перенаправленный результирующий набор или нет.
Пример:
(node[name="Foo"];way[name="Foo"];);
Здесь в первом операторе собираются все узлы (nodes) с тегом "Foo", и во втором все пути (ways), так же с тегом "Foo". После выполнения оператора union, результирующим набором объединения являются результирующие наборы обоих операторов.
Результирующий набор оператора union может быть перенаправлен с помощью обычной постфиксной нотации:
Пример:
(node[name="Foo"];way[name="Foo"];)->.a;
Еще один пример наподобие предыдущего, но результат записывается в переменную a.
Ограничения
Замечание: операторы foreach и print не могут быть под-элементами оператора union.
Разность
difference - блочный оператор, описывающийся парой круглых скобок. Внутри difference должны помещаться ровно два оператора, и между ними знак минус "-".
(statement_1; - statement_2;)[->.result_set];
Он не имеет входного набора. Производит результирующий набор. Этот набор содержит все элементы, являющиеся результатом первого вложенного оператора, которые не содержатся в результате второго вложенного оператора.
Пример:
(node[name="Foo"]; - node(50.0,7.0,51.0,8.0););
Здесь отбираются все узлы (nodes) с тегом "Foo", но не находящиеся в заданной области.
Результирующий набор оператора difference может быть перенаправлен с помощью обычной постфиксной нотации:
Пример:
(node[name="Foo"]; - node(50.0,7.0,51.0,8.0);)->.a;
Еще один пример наподобие предыдущего, но результат записывается в переменную a.
Collection-controlled loops
For-each цикл (foreach)
foreach блочный оператор, описывающийся ключевым словом foreach, за которым следует пара круглых скобок. Внутри этих скобок может быть помещена любая последовательность операторов, включая вложенные операторы union и foreach.
Он обрабатывает входной набор. Не производит результирующий. Оператор foreach "пробегается" по содержимому входного набора, по каждому элементу за раз.
Пример:
way[name="Foo"];
foreach(
(
._;
>;
);
out;
);
Для каждого way, имеющего тег с ключом "name" и значением "Foo", выводятся узлы, которые относятся непосредственно к этому way и следуют за самим way. Если более подробно, результат выражения way[name="Foo"] выступает как входной набор. Затем, для каждого элемента в этом входном наборе тело цикла исполняется один раз. Внутри тела цикла происходит объединение элемента и его узлов. Затем данное объединение печатается. Заметьте, что во время исполнения, каждый выводимый набор в одной итерации не зависит от выводимых наборов в других итерациях, что, вероятно, может привести к дублированию объектов в глобальном выводе (объединение не вычисляется оператором out внутри цикла).
Входной набор для оператора foreach можно захватить из переменной с помощью обычной постфиксной нотации:
Пример:
foreach.a(...);
Данный цикл "пробегается" по содержимому набора a вместо набора по умолчанию - "_".
The name of the variable to put the loop element into can also be chosen by adding a postfix immediately before the opening parenthese.
Example:
foreach->.b(...);
В этом примере результат работы цикла помещается в переменную b. Без этого, оператор foreach не размещает элементы перебора в какой-либо набор. Пример, где изменяются как входной набор, так и набор, полученный после обработки в цикле:
foreach.a->.b(...);
Самостоятельные запросы
Item
item - самостоятельный запрос, состоящий только из an input set prefix.
It takes the input set specified by its prefix. Это особенно полезно в union statements: он воспроизводит свой входной набор как результат (или часть) от union statement.
Наиболее общий способ применения - с набором по умолчанию:
._;
В контексте union statement, следующий код вернет все items во входном наборе по умолчанию вместе с recurse down результатом.
(._; >;);
И конечно же возможны и другие наборы:
.a;
В контексте union statement:
(.a; .a >;);
Заметка: Последующие statements в 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.
Рекурсия вверх (<)
recurse up - самостоятельный запрос, записываемый в виде одиночного знака "меньше" - <.
Он захватывает входной набор. Производит результирующий. Его результат состоит из:
- всех ways, которые имеют node, появляющиеся в input наборе; плюс
- всех relations, которые имеют node или way, появляющиеся в input наборе; плюс
- всех relations, которые имеют way, появляющиеся в result наборе
Пример:
<;
Входной набор для recurse up statement может быть выбран с помощью обычной постфиксной нотацией:
.a <;
The result set of the recurse up statement can be redirected with the usual postfix notation:
< ->.b;
Of course, you can also change both:
.a < ->.b;
Recurse up relations (<<)
The recurse up relations standalone query has a similar syntax to the recurse up query and differs only in two aspects:
- It is written as a double less than.
- It also recursively returns all relations that have a member relation appearing in the input set.
In particular, you can change the input and/or result set with the same notation as for the recurse up standalone query.
Precisely, the recurse up relations standalone query returns the transitive and reflexive closure of membership backwards.
Example:
<<;
Recurse down (>)
The recurse down standalone query is written as a single greater than.
It takes an input set. It produces a result set. Its result set is composed of:
- all nodes that are part of a way which appears in the input set; plus
- all nodes and ways that are members of a relation which appears in the input set; plus
- all nodes that are part of a way which appears in the result set
In particular, you can change the input and/or result set with the same notation as for the recurse up standalone query.
Example:
>;
Recurse down relations (>>)
The recurse down relations standalone query has a similar syntax to the recurse down query and differs only in two aspects:
- It is written as a double greater than.
- It also recursively returns all relations that are members of a relation appearing in the input set.
In particular, you can change the input and/or result set with the same notation as for the recurse down standalone query.
Precisely, the recurse down relations standalone query returns the transitive and reflexive closure of membership.
Example:
>>;
Query for areas (is_in)
The standalone query is_in returns the areas that cover the given coordinates (when specified) or one or more nodes from the input set (when no coordinates are specified).
It takes either an input set or a co-ordinate. It produces a result set. The results are all areas which contain at least one of node from the input set or the specified coordinates.
[.input_set] is_in[->.result_set];
is_in(latitude,longitude)[->.result_set];
In its shortest form, it takes its input set as the coordinates to search for. Example:
is_in;
The input set can be chosen with the usual prefix notation:
.a is_in;
The result set can be redirected with the usual postfix notation:
is_in->.b;
Of course, you can also change both:
.a is_in->.b;
Instead of taking existing nodes you can also specify coordinates with two floating point numbers, divided by a comma. They are interpreted as latitude, longitude. In this case, the input set is ignored. Example:
is_in(50.7,7.2);
Also in this variant, the result set can be redirected with the usual postfix notation:
is_in(50.7,7.2)->.b;
Note: Area creation depends on some specific extraction rules, there's no area counterpart for each and every OSM way or relation! For more details see areas.osm3s and the Areas Wiki page.
Filters
The most important statement is the query statement. This is not a single statement but rather consists of one of the type specifiers node, way, relation (or shorthand rel) or area, followed by one or more filters. The result set is the set of all elements that match the conditions of all the filters.
Example:
node[name="Foo"];
way[name="Foo"];
rel[name="Foo"];
area[name="Foo"];
Here, node, way, rel and area are the type specifier, [name="Foo"] is the filter and the semicolon ends the statement.
The query statement has a result set that can be changed with the usual postfix notation.
node[name="Foo"]->.a;
The individual filters may have in addition input sets that can be changed in the individual filters. Please see for this at the respective filter.
By tag (has-kv)
The has-kv filter selects all elements that have or have not a tag with a certain value. It supports the basic OSM types node, way, and relation as well as the extended type area.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
All variants consist of an opening bracket, then a string literal in single or double quotes. Then the variants differ. All variants end with a closing bracket. If the string literal consists only of letters, the quotes can be omitted.
Equals (=, !=)
The most common variant selects all elements where the tag with the given key has a specific value. This variant contains after the key literal an equal sign and a further literal containing the value. Examples, all equivalent:
node["name"="Foo"];
node[name=Foo];
node['name'="Foo"];
node[name="Foo"];
node["name"='Foo'];
If you have a digit, whitespace or whatever in the value, you do need single or double quotes:
node["name"="Foo Street"];
node["name"='Foo Street'];
node[name="Foo Street"];
Querying for empty values is not possible using the equals value operator. This can only be achieved by using a regular expression:
node[power=""]; // not supported
node[power~"^$"]; // use regular expression instead
Likewise, querying empty key values is also not possible using this kind of key-value query and needs to be expressed via regular expressions.
node[~"^$"~"."]; // find nodes with empty key ("") and any value
NB: Overpass Turbo Wizard already has some logic in place to automatically convert ""="" accordingly.
Exists
The second variant selects all elements that have a tag with a certain key and an arbitrary value. It contains nothing between the key literal and the closing bracket:
node["name"];
node['name'];
node[name];
Value matches regular expression (~, !~)
The third variant selects all elements that have a tag with a certain key and a value that matches some regular expression. It contains after the key literal a tilde, then a second literal for the regular expression to search for:
node["name"~"^Foo$"]; /* finds exactly "Foo" */
node["name"~"^Foo"]; /* finds anything that starts with "Foo" */
node["name"~"Foo$"]; /* finds anything that ends with "Foo" */
node["name"~"Foo"]; /* finds anything that contains the substring "Foo" */
node["name"~"."]; /* finds anything, equal to the previous variant */
node["name"!~"."]; /* finds nodes without "name" tag; does not have key name */
Please note that in QL you need to escape backslashes: ["name"~"^St\."] results in the regular expression ^St. (which finds every name starting with "St"), while ["name"~"^St\\."] produces the most likely meant regular expression St\. (which finds every name starting with "St."). This is due to the C escaping rules and doesn't apply to the XML syntax.
Case insensitively
You can also search case insensitively
node["name"~"^Foo$",i]; /* finds "foo", "FOO", "fOo", "Foo" etc. */
Both the key and value variants with and without regular expressions can be negated. They then select exactly the elements which have a tag with the given key, but no matching value and the elements that don't have a tag with the given key:
node["name"!="Foo"];
node["name"!~"Foo"];
node["name"!~"Foo",i];
Key/value matches regular expression (~"key regex"~"value regex")
The forth variant selects all elements where both key and value match a regular expression. After an initial tilde (~) the regular expression for the key needs to be provided, followed by another tilde character and eventually the regular expression for the value.
node[~"^addr:.*$"~"^Foo$"]; /* finds addr:* tags with value exactly "Foo" */
node[~"^addr:.*$"~"^Foo"]; /* finds addr:* tags with value starting with "Foo" */
node[~"^addr:.*$"~"Foo$"]; /* finds addr:* tags with value ending with "Foo" */
node[~"^addr:.*$"~"Foo"]; /* finds addr:* tags with value containing the substring "Foo" */
node[~"^addr:.*$"~"."]; /* finds addr:* tags with any value */
Regular expressions for values cannot be negated in this variant |
Case insensitively
Is it possible or not?
- Not yet, there's a GitHub ticket, but the fix hasn't been merged yet. Mmd (talk) 08:41, 16 September 2015 (UTC)
Bounding box
The bbox-query filter selects all elements within a certain bounding box.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
(south,west,north,east)
It consists of an opening parenthesis. Then follow four floating point numbers, separated by commas. The filter is ends with a closing parenthesis.
The floating point numbers give the limits of the bounding box: The first is the southern limit or minimum latitude. The second is the western limit, usually the minimum longitude. The third is the northern limit or maximum latitude. The last is the eastern limit, usually the maximum longitude. If the second argument is bigger than the fourth argument, the bounding box crosses the longitude of 180 degrees.
Example:
node(50.6,7.0,50.8,7.3);
Recurse (n, w, r, bn, bw, br)
The recurse filter selects all elements that are members of an element from the input set or have an element of the input set as member, depending on the given parameter.
The input set can be changed with an adapted prefix notation. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows one of the symbols: w (forward from ways), r (forward from relations), bn (backward from nodes), bw (backward from ways), or br (backward from relations). Then follows an optional input set declaration. The filter ends with a closing parenthesis.
Examples with default input set:
node(w); // select child nodes from all ways of the input set
node(r); // select node members of relations of the input set
way(bn); // select parent ways for all nodes from the input set
way(r); // select way members of relations from the input set
rel(bn); // select relations that have node members from the input set
rel(bw); // select relations that have way members from the input set
rel(r); // select all members of type relation from all relations of the input set
rel(br); // select all parent relations of all relations from the input set
Example with modified input set:
node(w.foo);
You can also restrict the recurse to a specific role. Just add a colon and then the name of the role before the closing parenthesis.
Examples with default input set:
node(r:"role"); // select node members of relations of the input set
way(r:"role"); // select way members of relations from the input set
rel(bn:"role"); // select relations that have node members from the input set
rel(bw:"role"); // select relations that have way members from the input set
rel(r:"role"); // select all members of type relation from all relations of the input set
rel(br:"role"); // select all parent relations of all relations from the input set
Example with modified input set:
node(r.foo:"role");
And you can also search explicitly for empty roles:
node(r:"");
node(r.foo:"");
By input set (.setname)
The "item" filter selects all elements from its input set.
As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of a dot, followed by the name of the input set.
Examples: The default set
node._;
and a named set
node.a;
It is also possible to specify several input sets:
node.a.b;
This statement returns all nodes which are both in input set .a and input set .b (set intersection).
By element id
The id-query filter selects the element of given type with given id. It supports beside the OSM datatypes node, way, and relation also the type area.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows a positive integer. The filter is ends with a closing parenthesis.
Examples:
node(1);
way(1);
rel(1);
area(1);
Note that area ids need to be derived from an existing OSM way by adding 2400000000 to its OSM id or in case of a relation by adding 3600000000 respectively. Note that area creation is subject to some extraction rules, i.e. not all ways/relations have an area counterpart. See areas.osm3s for details.
Relative to other elements (around)
The around filter selects all elements within a certain radius around the elements in the input set. If you provide coordinates, then these coordinates are used instead of the input set. The input set can be changed with an adapted prefix notation. As for all filters, the result set is specified by the whole statement, not the individual filter.
A radius of 0 can be used for a way intersection test on outer/inner points.
Syntax: It consists of an opening parenthesis. Then follows the keyword around. Then follows optionally an input set declaration. Then follows a single floating point number that denotes the radius in meters. The filter either ends with a closing parenthesis or is followed by two comma separated floating point numbers indicating latitude and longitude and then finally a closing parenthesis.
(around[.input_set]:radius)
(around:radius,latitude,longitude)
Examples:
node(around:100.0);
way(around:100.0);
rel(around:100.0);
Example with modified input set:
node(around.a:100.0);
Examples with coordinates:
node(around:100.0,50.7,7.1);
way(around:100.0,50.7,7.1);
rel(around:100.0,50.7,7.1);
Example: Find all cinemas in Bonn which are at most 100m away from bus stops
area[name="Bonn"];
node(area)[highway=bus_stop];
node(around:100)[amenity=cinema];
out;
By polygon (poly)
The polygon filter selects all elements of the chosen type inside the given bounding box.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows the keyword poly. Then follows a string containing an even number of floating point numbers, divided only by whitespace. Each pair of floating point numbers represents a coordinate, in order latitude, then longitude. The filter ends with a closing parenthesis.
(poly:"latitude_1 longitude_1 latitude_2 longitude_2 latitude_3 longitude_3 …");
An example (a triangle near Bonn, Germany):
node(poly:"50.7 7.1 50.7 7.2 50.75 7.15");
way(poly:"50.7 7.1 50.7 7.2 50.75 7.15");
rel(poly:"50.7 7.1 50.7 7.2 50.75 7.15");
newer
The newer filter selects all elements that have been changed since the given date. As opposed to other filters, this filter cannot be used alone. If the underlying database instance supports attic data, then "changed" is probably a better choice than "newer".
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows a date specification. Please note that this date specification cannot be abbreviated and has to be put in single or double quotes. The filter ends with a closing parenthesis.
Example:
node._(newer:"2012-09-14T07:00:00Z");
This finds all nodes that have changed since 14 Sep 2012, 7 h UTC, in the given input set.
By date of change (changed)
The changed filter selects all elements that have been changed between the two given dates. If only one date is given, then the second is assumed to be the front date of the database. If only one date is given and it is run with the current timestamp, then it behaves exactly like "newer" with two exceptions: first, it is faster, second, it can also stand as the only filter.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows a date specification. Please note that this date specification cannot be abbreviated and has to be put in single or double quotes. Then can follow a comma and a second date specification. The filter ends with a closing parenthesis.
Example: All changes since the given date and now
node._(changed:"2012-09-14T07:00:00Z");
Example: All changes between the two given dates
node._(changed:"2012-09-14T07:00:00Z","2012-09-14T07:01:00Z");
By user (user, uid)
The user filter selects all elements that have been last touched by the specified user.
It has no input set. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows either the keyword user, a colon and a string literal denoting the user name to search for. Or the keyword uid followed by the user id of the user to search for. The filter ends with a closing parenthesis.
Example:
node(user:"Steve");
node(uid:1);
By area (area)
The area filter selects all elements of the chosen type that are inside the given area. Please note with regard to attic data that areas always represent current data.
The input set can be changed with an adapted prefix notation. As for all filters, the result set is specified by the whole statement, not the individual filter.
Syntax: It consists of an opening parenthesis. Then follows the keyword area. Then can follow a colon and a non-negative integer. The filter ends with a closing parenthesis.
Nodes are found if they are properly inside or on the border of the area. Ways are found if at least one point (also points on the segment) is properly inside the area. A way ending on the border and not otherwise crossing the area is not found. Relations are found if one of its members is properly inside the area.
If the area statement is provided without integer, the areas from the input set are used. An Example:
node(area);
way(area);
rel(area);
The example with modified input set:
node(area.a);
way(area.a);
rel(area.a);
If an integer is added, the input set is ignored and instead the area that has the given integer as id is taken.
node(area:2400000001);
way(area:2400000001);
rel(area:2400000001);
Caveat: area(area); is currently not supported. In this case, the (area) filter will be silently ignored, leading to unexpected results.
Because areas in OSM are not native elements but are only inferred from the OSM database using its closed ways or relations; this facility allows grouping their various representation in a coherent set which can store their geometry, independently of their complexity and representation in the OSM database, as if they were a single distinctive element, without using complex filtering rules in your query. However associating these objects with an OSM id attribute requires some adjustment because the same id value could be used for unrelated elements with different type (way or relation). For this reason, areas returned by the Overpass API only have a "virtual" id specific to the Overpass API, but not found directly in the OSM database.
By convention the area id can be calculated from an existing OSM way by adding 2400000000 to its OSM id, or in case of a relation by adding 3600000000 respectively. Note that area creation is subject to some extraction rules, i.e. not all ways/relations have an area counterpart (notably those that are tagged with area=no, and most multipolygons and that don't have a defined name=* will not be part of areas).
Areas are created by a regular job on the Overpass API server and usually have a lag of several hours compared to the OSM main database. The exact timestamp can be determined by checking the `timestamp_areas_base` value in the Overpass json or xml result.
If you want more immediate results (not depending on the delayed batch processing), you can also write your own filters without using this facility in your Overpass query: use standard OSM element types and ids and filter them by specific tags of your choice.
- See areas.osm3s for details of the filters (written using the XML variant of the Overpass query language) currently by Overpass used to generate the areas that can be queried with this facility. Those areas are defined using the "pivot" query feature (see below).
Area pivot (pivot)
The pivot filter selects the element of the chosen type that defines the outline of the given area.
The input set can be changed with an adapted prefix notation. As for all filters, the result set is specified by the whole statement, not the individual filter.
It consists of an opening parenthesis. Then follows the keyword pivot. The filter ends with a closing parenthesis.
The statement finds for each area in the input set the respective element that the area has been generated from. Which is either a multipolygon relation or a way.
Examples:
way(pivot);
rel(pivot);
The example with modified input set:
way(pivot.a);
rel(pivot.a);
The following example initially determines the area(s) for the county of Greater London first and stores the result in resultset .londonarea
. In the next line the areas contained in resultset .londonarea
are converted back into their corresponding OSM relations using the pivot filter. Eventually out geom;
outputs the relations (including ways and nodes).
area[name="London"][admin_level=6][boundary=administrative]->.londonarea;
rel(pivot.londonarea);
out geom;
Actions
There is currently only one action. This action prints out the content of its input set.
Print (out)
The out action can be configured with an arbitrary number of parameters that are appended, separated by whitespace, between the word out and the semicolon.
The out action takes an input set. It doesn't return a result set. The input set can be changed by prepending the variable name.
Allowed values, in any order, are:
- one of the following the degree of verbosity; default is body:
- ids: Print only the ids of the elements.
- skel: Print also the information necessary for geometry. These are also coordinates for nodes and way and relation member ids for ways and relations.
- body: Print all information necessary to use the data. These are also tags for all elements and the roles for relation members.
- tags: Print only ids and tags for each element and not coordinates or members.
- meta: Print everything known about the elements. This includes additionally to body for all elements the version, changeset id, timestamp and the user data of the user that last touched the object.
- one of the following modificators for derived information:
- bb: Adds the bounding box of each element to the element. For nodes this is equivalent to "geom". For ways it is the enclosing bounding box of all nodes. For relations it is the enclosing bounding box of all node and way members, relations as members have no effect.
- center: This adds the center of the above mentioned bounding box to ways and relations. Note: The center point is not guaranteed to lie inside the polygon (example).
- geom: Add the full geometry to each object. This adds coordinates to each node, to each node member of a way or relation, and it adds a sequence of "nd" members with coordinates to all relations.
The attribute "geom" can be followed by a bounding box in the format "(south,west,north,east)". In this case only coordinates that are inside the bounding box are produced. For way segments also the first coordinate outside the bounding box is produced to allow for properly formed segments.
- One of the following for the sort order can be added. Default is asc.
- asc: Sort by object id.
- qt: Sort by quadtile index; this is roughly geographical and significantly faster than order by ids.
- a non-negative integer for the maximum number of elements to print. Default is no limit.
Example:
out;
Print the elements without meta information.
Example:
out meta;
Print the elements with meta information.
Example:
out 99;
Print at most 99 elements.
Example:
out meta qt 1000000;
Print up to 1,000,000 elements, ordered by location, with meta data.
Example:
.a out;
Reads from variable a the data to output.
Settings
timeout
The timeout setting has one parameter, a non-negative integer. Default value is 180.
This parameter indicates the maximum allowed runtime for the query in seconds, as expected by the user. If the query runs longer than this time, the server may abort the query with a timeout. The second effect is, the higher this value, the more probably the server rejects the query before executing it.
So, if you send a really complex big query, prefix it with a higher value; e.g., "3600" for an hour. And ensure that your client is patient enough to not abort due to a timeout in itself.
Example:
[timeout:180]
Element limit (maxsize)
The maxsize setting has one parameter, a non-negative integer. Default value is 536870912 (512 MB).
This parameter indicates the maximum allowed memory for the query in bytes RAM on the server, as expected by the user. If the query needs more RAM than this value, the server may abort the query with a memory exhaustion. The second effect is, the higher this value, the more probably the server rejects the query before executing it.
So, if you send a really complex big query, prefix it with a higher value; e.g., "1073741824" for a gigabyte. The maximum value highly depends on the current server load, e.g. requests for 2GB will likely be rejected during peak hours, as they don't fit into the overall resource management. Technically speaking, maxsize is treated as a 64bit signed number.
Example:
[maxsize:1073741824]
Output Format (out)
Note that the out setting is unrelated to the out action. Syntax should not be mixed
The out setting defines the output format used to return OSM data. It can take one of the five values; default value is xml:
- xml
- json (not to be confused with geoJSON)
- csv
- custom
- popup
Example:
[out:json]
- CSV output mode
CSV output format returns OSM data as csv document, which can be directly opened in tools like LibreOffice. It requires additional configuration parameters to define a list of fields to display, as well as two optional parameters for csv headerline, as well as the separator character.
Format:
[out:csv( fieldname_1 [,fieldname_n ...] [; csv-headerline [; csv-separator-character ] ] )]
- List of field names
Besides normal OSM field names the following special fields are available:
Special fieldname | Description |
---|---|
::id | OSM Object ID |
::type | OSM Object type: node, way, relation |
::otype | OSM Object as numeric value |
::lat | Latitude (available for nodes, or in out center mode) |
::lon | Longitude (available for nodes, or in out center mode) |
The following meta information fields are only available, if out meta; is used to output OSM elements. | |
::version | OSM object's version number |
::timestamp | Last changed timestamp of an OSM object |
::changeset | Changeset in which the object was changed |
::uid | OSM User id |
::user | OSM User name |
Note that all of these special fields needs to be prefixed by two colons "::".
Example:
[out:csv(::"id", amenity, name, operator, opening_hours, "contact:website", "contact:phone", brand, dispensing, lastcheck)];
Railway stations in Bonn:
[out:csv(::id,::type,"name")];
area[name="Bonn"]->.a;
( node(area.a)[railway=station];
way(area.a)[railway=station];
rel(area.a)[railway=station]; );
out;
- Header line
Header line is the first optional parameter, which can be added right after the field list separated by semicolon. Possible values include true and false. If this parameter is not specified, a header line will be printed.
[out:csv(::"id",amenity,name,operator,opening_hours,"contact:website","contact:phone",brand,dispensing,lastcheck;false)];
- Separator character
By default all fields are separated by a tab character (\t). However, this setting can be changed via the second optional parameter. In the following example all output fields will be separated by a pipe ("|") character instead.
[out:csv(::"id",amenity,name,operator,opening_hours,"contact:website","contact:phone",brand,dispensing,lastcheck;true;"|")];
- Checking for complete data
Unlike other output modes like XML and JSON, there's currently no indication of any error message at all. An empty result (or a result with just a header line) might indicate either that nothing was found or that the query was aborted due to timeout or some other more serious error condition. One way to work around this is to introduce an additional counter, which summarizes the previous query result and is always put as the very last output statement of a query.
The following example extends the previously shown list of all railway stations in Bonn by an additional count output:
[out:csv(::type,::id,"name",::count)];
area[name="Bonn"]->.a;
( node(area.a)[railway=station];
way(area.a)[railway=station];
rel(area.a)[railway=station]; );
out;
out count;
Note that the result now includes an additional line with @type count and an indication of how many total elements are contained in the current resultset. If the final count line is missing or the total number differs, you know for sure that something went wrong and the query results are incomplete/inconsistent.
@type @id name @count node 26945519 Bonn-Oberkassel node 1271017705 Bonn-Beuel node 2428355974 Bonn-Bad Godesberg node 2713060210 Bonn Hauptbahnhof node 3400717493 Bonn-Mehlem count 5
The values custom and popup also require further configuration. Please see details in the output formats documentation.
Global bounding box (bbox)
The bbox setting can define a bounding box that is then implicitly added to all queries (unless they specify a different explicit bbox).
The bounding box is written in order southern lat, western lon, northern lat, eastern lon (which is the standard order).
[bbox:south,west,north,east]
Example:
[bbox:50.6,7.0,50.8,7.3]
Enforces a bounding box roughly around the German city Bonn, which is at 50.7 degrees latitude, 7.15 degrees longitude.
If a query is URL encoded as value of the data= parameter, the bounding box can also be appended as separate parameter. It has then order lon-lat. This is the common order for OpenLayers and other frameworks.
Complete Example:
/api/interpreter?data=[bbox];node[amenity=post_box];out;&bbox=7.0,50.6,7.3,50.8
This finds all post boxes roughly in Bonn, Germany.
Attic data ("date")
The date setting lets the database answer a query based on a database state in the past. This is useful for example to reconstruct data that has been vandalised.
It consists of the identifier "date", followed by a colon and then a date specification.
Example:
[date:"2012-09-12T06:55:00Z"]
This processes the rest of the query as if it were posed on 12th September 2012 at 06:55 UTC.
Limitation
The earliest possible date to return a result is 2012-09-12 06:55:00 UTC (1347432900 in epoch seconds).
It corresponds to the first change included in the first ODbL compliant planet file, which was created on 2012-09-14. If your query asks for an object in a state prior to what this planet file contains, Overpass API will return the version contained in the first ODbL compliant planet. (Note: there's a DB inconsistency at this time, which would return an error message instead. This is only a temporary issue and will disappear once the DB has been rebuilt).
Delta between two dates ("diff")
The diff setting lets the database determine the difference of two queries at different points in the past. This is useful for example to deltas for database extracts.
It consists of the identifier "diff", followed by a colon, then a date specification, and optionally a comma and a second date specification. If only one date specification is given, then the second is assumed to be the current state.
Example:
[diff:"2012-09-14T15:00:00Z"]
This processes the rest of the query as if it were posed on 14th September 2012 at 15:00, then processes the same query with current data and finally outputs the difference between the two results.
[diff:"2012-09-14T15:00:00Z","2012-09-21T15:00:00Z"]
Does basically the same, but compares the state of 14th September with the state of 21st September.
Augmented Delta between two dates ("adiff")
The adiff does basically the same like "diff" , but for all elements that aren't contained in the newer result, it is indicated what happened to them.
If an element has been deleted, then its last deletion date is printed and the indication "visible=false". If an element has changed such that it no longer matches the query then its last change date is printed and the indication "visible=true".
Special syntax
Comments
The query language allows comments in the same style like in C source code:
out; // A single line comment
/* Comments starting with slash asterisk must always be closed with an asterisk slash. */
/* But they can span
multiple lines. */
Escaping
The following C-style escape sequences are recognized:
- \n: escapes a carriage return
- \t: escapes a tabulator
- \", \': escaped the respective quotation mark
- \\: escapes the backslash
- \u#### (the hash characters stand for four hexadecimal digits): escapes the respective unicode UTF-16 code unit, see Unicode escape sequences.
- Note that the database encodes characters in UTF-8 on 1 byte (only characters in the 7-bit US-ASCII characters subset in the range U+0000..U+007F) or more. All characters that that are assigned a Unicode scalar value in the standard 17 planes are encoded as UTF-8.
- But this syntax only supports characters assigned in the BMP; excluding surrogates which are not Unicode characters and have no valid UTF-8 encoding; even if they has a 16-bit scalar value. Non-ASCII Characters in the BMP are encoded with UTF-8 on 2 bytes (in the range U+0080..U+07FF), or 3 bytes (in the range U+0800..U+FFFF, minus surrogates in the range U+D800..U+DFFF)
- Unicode characters outside the BMP can be represented in UTF-16 as a pair of surrogates: only valid pairs of UTF-16 surrogates (a high surrogate in U+D800..U+DBFF immediately followed by a low surrogate in U+DC00..U+DFFF) are convertible to UTF-8 and can be escaped as \uD###\uD### (the result of escaping invalid pairs of surrogates or unpaired surrogates is undefined); these valid escaped pairs of surrogates will be converted to UTF-8-encoded sequences of 4 bytes (in supplementary planes 1 to 15) or 5 bytes (in the last valid supplementary plane 16 assigned only for private use, not useful in OSM data as they are not interoperable).
- There's currently no support for the common escaping syntax \U000##### used in modern C to represent a codepoint in any one of the 17 valid Unicode planes (excluding surrogates), and not even for arbitrary 8-bit bytes with the common escaping syntax \x## (defined in C independantly of the encoding used). As much as possible escaping should be avoided if it's not needed, and valid UTF-8 used directly in requests.
Experimental features
Features described in this section were introduced in v0.7.51 but are not yet fully tested and not yet officially announced. If you encounter some bugs or issues, please raise a new Github issue.
Counting of elements
In addition the the existing output modes, out count; provides a way to return the total number of elements in a given inputset without transferring individual OSM objects. Is it supported in XML, JSON and CSV mode.
out count;
- XML output mode
<count total="923" nodes="923" ways="0" relations="0"/>
- JSON output mode
{
"count": {
"total": 923,
"nodes": 923,
"ways": 0,
"relations": 0,
"areas": 0
}
}
- CSV output mode
In addition to the previously outlined output fields for CSV output mode, counting of elements provides additional special fieldnames.
Special fieldname | Description |
---|---|
The following fields are only populated via an out count; statement | |
::count | Returns total number of objects (nodes, ways, relations and areas) in inputset |
::count:nodes | Returns number of nodes in inputset |
::count:ways | Returns number of ways in inputset |
::count:relations | Returns number of relations in inputset |
::count:areas | Returns number of areas in inputset |
Map way/relation to area (map_to_area)
Note: this statement might still change in the future
The map_to_area statement maps OSM object ids for both ways and relations to their Overpass API area id counterpart.
This is done by applying the following mapping rules inside Overpass API:
- For ways: add 2400000000 to the way's OSM id
- For relations: add 3600000000 to the relations's OSM id.
Example:
rel(62716);
out; // output relation 62716
map_to_area; // map OSM relation to Overpass API area by adding 3600000000 to its id
out; // output area 3600062716
The main use case of this statement is to search for objects inside an area, which is again inside another area ("area in area query").
Note: The Overpass API internal area creation job does not create an area for each and every way/relation in OSM. If an area does not exist for a given way/relation, map_to_area will simply skip this object without adding an area.
The following examples outline some possible use cases for this statement:
Example 1: Find all pubs in the inner city of Cologne
Querying only for an area named "Innenstadt" would return quite a number of areas, not limited to Cologne.
area[name="Köln"]->.b;
rel(area.b)[name="Innenstadt"];
map_to_area -> .a;
node(area.a)[amenity=pub];
out meta;
Example 2: Find all counties in Hessen without fire station
area[admin_level=4]["name"="Hessen"][boundary=administrative]->.boundaryarea;
( node(area.boundaryarea)["amenity"="fire_station"];
way(area.boundaryarea)["amenity"="fire_station"];>;) ->.a;
.a is_in -> .b;
area.b[admin_level=8] -> .bf;
rel(area.boundaryarea)[admin_level=8];
map_to_area -> .bllf;
(.bllf - .bf ) ;
rel(pivot); (._;>;); out;
Example 3ː Count the number of pharmacies per county
[out:csv(::"type",::"id", name, admin_level,::"count")];
area[name="Saarland"][boundary];
rel(area)[boundary][admin_level=6];
map_to_area;
foreach->.d(
(.d;);out;
(node(area.d)[amenity=pharmacy];
way(area.d)[amenity=pharmacy];
relation(area.d)[amenity=pharmacy];);
out count;
);