Find, style, count, and inspect map data.

The PBFX query language is intentionally compact. You choose feature types, add tag filters, optionally limit to the current map view or a resolved local area, then request geometry, counts, styling, labels, or simple spatial relations such as near(...).

Quick Start

Choose feature typesnodes, ways, and relations limit what can match.
Limit to a local arealimitLocal keeps matching in the current map view, limitLocal(auto) reruns when the view changes, and limitLocal(...) can resolve GPS, bbox, names, or filters.
Draw resultscoords returns geometry so the result can be rendered on the map.
Explore valuescount(key) counts distinct values instead of returning full geometry.
ways
limitLocal
coords
highway=*
limitLocal("Zoo Leipzig")
building=*
coords
Lines starting with # are comments and ignored by the parser.

Core Directives

  • nodes, ways, relations: choose feature types
  • coords: include geometry
  • limitLocal: restrict to the current map view
  • limitLocal(gps, 2km): restrict to a radius around the current GPS position
  • limitLocal(bbox, west, south, east, north): use an explicit bounding box
  • limitLocal(auto): keep using the current map view and rerun automatically after significant map moves
  • limitLocal("Zoo Leipzig"): resolve a free-text local area first, then search inside it
  • limitLocal(name="Zoo Leipzig"): resolve a structured filter first, then search inside it
  • coverage: return a raster coverage/heatmap layer instead of normal geometry results
  • coverage(log, blur=5): use logarithmic scaling and five blur passes for smoother density maps
  • results 100000: raise or lower the result cap
  • numTags 5: include more tag information in result items
  • zoom 10 16: only activate following lines in that zoom range
  • routing or routing(highway=*|route=ferry): build a route graph, optionally restricted to matching ways (intersections is still accepted as an alias)
  • routeCost(highway=primary):1.8, routeCost(highway=traffic_signals):+25m, routeCost(oneway=yes):forward, routeCost(access=private):blocked, routeCost(highway=residential):defer(10km), or routeCost(refMaxspeed):20km/h: weight, penalize, set direction, exclude routing graph segments, defer low-priority road classes far away from start and target, or set the ETA reference speed
  • debugPages and debugTagSets: print debug information to the server log
ways
coords
limitLocal
results 200000
limitLocal(gps, 2km)
amenity=pharmacy
coords

Filters

Use show(...) to choose the returned feature set. Older bare filter lines still work, but show(...) keeps result selection separate from styling.

show(highway=*|building=*|natural=water)

Filters are mostly exact. The most common forms are:

  • key=value
  • key=*
  • *=value to match a value across any key
  • key=a|b|c for several values of the same key
  • !key=value to exclude matches
  • (a=b)|(c=d) for explicit OR across different conditions
highway=primary|secondary|trunk
building=*
*=Eldenaer Straße|Hübnerstraße
!highway=street_lamp|traffic_signals|crossing
(railway=station)|(highway=bus_stop)
*=value means: match if any tag value equals that value. This is useful when the same name or identifier may appear under different keys.

Spatial Queries

near(...) adds a simple proximity condition using a radius in meters.

Near, symmetric form

Returns matches from both sides. Outer feature-type directives such as ways apply to the left side.

near(100m, amenity=pharmacy, shop=bakery)
limitLocal
Near, filtering form

Keeps the main query only if it is near the second condition.

shop=bakery
near(100m, amenity=pharmacy)
limitLocal
Inside

Checks whether the left-side feature geometry lies inside matching polygon targets.

inside(highway=path, natural=wood)
limitLocal
near(...) samples decoded line geometry for distance checks. inside(...) is a separate, more expensive polygon containment check. Both are supported as top-level query lines, not as fully nestable boolean expressions.

Count and Coverage

Use count(key) to count distinct values instead of returning full geometry.

ways
limitLocal
count(surface)

Use coverage when you want a density/coverage raster layer instead of normal geometry results.

nodes
limitLocal
coverage(log, blur=5)
amenity=pharmacy
coverage supports linear, sqrt, and log scaling. The explicit form is coverage(scale=log, blur=5, resolution=256); only resolution=256 is currently supported.

Styles and Labels

Two style forms are supported:

  • color(condition):r,g,b,a,width
  • condition->style:r,g,b,a,width
color(highway=primary):0.93,0.56,0.33,0.98,3.6
surface=cobblestone->style:0.92,0.38,0.22,0.95,4.6

Style options can limit geometry types, choose line patterns, disable picking, or add an outline/casing:

color(highway=primary):0.88,0.38,0.24,0.98,3.8; for=ways; casing=2
color(building=*):0.52,0.50,0.48,0.30,0; for=ways|relations; casing=1; hit=no
color(railway=rail):0.18,0.18,0.20,0.78,1.8; for=ways; line=dashdot

Line width and casing use pixels by default. Append m for meters or px explicitly:

color(highway=primary):0.88,0.38,0.24,0.98,6m; casing=1.5m

The map view background can be set with background:r,g,b,a, which is especially useful when the base map is hidden:

background:0.08,0.09,0.10,1

When DEM tiles are available, the background can also be drawn from elevation data. Missing tiles are requested in the background and appear after rerunning the query:

background:hillshade; opacity=0.45; azimuth=315; altitude=45; exaggeration=1.4; resolution=384; smooth=3
background:relief; opacity=0.55; exaggeration=1.2

Routing overlays can be styled client-side when routing is active:

color(route):0,0.35,1,0.9,6; line=dash
color(route:start):0,0.7,0.25,1,7
color(route:end):0.9,0.1,0.1,1,7

Routing costs are independent from visual style. Factors multiply weighted meters. A factor of 1 is neutral, lower values are preferred, higher values are avoided. Multiple matching factors multiply. Additive +Xm values add meter-equivalent penalties, blocked removes a segment or node from the route graph, and defer(Xm|Xkm) postpones matching segments while both start and target are farther away than that distance:

routeCost(highway=cycleway):0.45
routeCost(highway=secondary):1.8
routeCost(highway=traffic_signals):+25m
routeCost(barrier=bollard):+12m
routeCost(access=private):blocked
routeCost(highway=residential):defer(10km)
routeCost(refMaxspeed):20km/h
routeCost(elevationProfile):1

Spatial route costs can prefer or avoid routing ways inside matching polygon targets or near matching geometry:

$green = leisure=park|natural=wood|landuse=forest
routeCost(inside($green)):0.5
routeCost(near(20m, highway=primary|highway=secondary)):2.0
Spatial route costs currently annotate the matched route feature. Because route metadata is serialized per returned way, a long way can carry the factor beyond the exact local section that matched the spatial radius or polygon.

Routing direction is another independent routeCost dimension. Later direction rules override earlier ones, without changing the numeric cost:

routeCost(oneway=yes):forward
routeCost(oneway=-1):backward
routeCost(oneway:bicycle=no):both
routeCost(cycleway=opposite):both

When routing is active, start/end placement snaps to the nearest segment. The route overlay reports length, average route cost, type shares, and counted traffic-signal nodes. Turn restriction relations are not implemented yet.

Global output keys use ->name or ->name|ref|maxspeed.

Conditional labels use label(condition):keys with optional label options:

label(place=city):name; priority=320
label(place=town):name; priority=240
label(highway=primary|secondary):name; priority=120; size=11

Image overlays can load Commons thumbnails via Wikidata entity tags:

limitLocal
coords
tourism=museum
->name
->image(64):wikidata
->image(size):wikidata requests the wikidata output key automatically and shows up to a small number of image markers on the map when matching results contain a Wikidata Q-id with a Commons image.

Macros

Macros start with $ and are expanded before normal parsing.

$roads = highway=*
$major = highway=primary|secondary|trunk|motorway

$roads
$major->style:0.93,0.56,0.33,0.98,3.6

Function-like macros are also supported:

$road($type,$width)=highway=$type->style:0.95,0.72,0.48,0.95,$width
$road(primary,3.6)
$road(secondary,2.8)

Examples

Minimal local road map
ways
limitLocal
coords
highway=*
Resolve a local place first
limitLocal("Zoo Leipzig")
building=*
coords
Places only
nodes
limitLocal
coords

place=city|town|village
place=city|town|village->label:name
QA example
nodes
ways
limitLocal
coords

addr:housenumber=*
!addr:street=*|addr:place=*
!addr:city=*

color(*=*):1,0,0,1,0
->addr:housenumber|addr:city|addr:place|addr:street
Symmetric near
near(100m, amenity=pharmacy, shop=bakery)
color(amenity=pharmacy):1,0,0,1,3
color(shop=bakery):0,1,0,1,3
limitLocal

Not Supported Yet

  • numeric comparisons such as maxspeed >= 50
  • regex matching
  • full boolean expression precedence
  • multiple simultaneous top-level near(...) / inside(...) filters