Bus stop data quality in OpenStreetMap

April 2024 (republished in March 2026)

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This post was written in 2024 and has not been updated since (up to fixing some typos).

OpenStreetMap (OSM) is a large open database for geographic data created and maintained by volunteers, see Wikipedia on OSM for an overview and some background. OSM’s main data use is rendering an extremely detailed map of the world.

Data quality is an important issue for applications like routing of pedestrians to public transport facilities. In this report we describe different schemes for mapping bus stops in OSM and we provide statistics on usage of those schemes, the good ones and the not so good ones.

OSM bus stop basics

OSM does not have one fixed scheme for mapping bus stops. Instead, there exist several tags for describing bus stops or parts of bus stops. Tag usage changes over time. The decision for a tagging scheme usually is based on

Tagging schemes should meet all three points. The first point (other mappers) is the main concern of this report. Addressing this point requires a deep look into the OSM database. Before we come to the statistics part, we summarize what OSM wiki has about bus stops. The question which tags applications do process cannot be answered in general. In this report we focus on OSM’s standard style Carto for the Mapnik renderer.

A bus stop in the OSM database consists of one of the following collections of objects:

Next to many individual mapping schemes there exist several documented ones:

The original mapping scheme has turned out to be not expressive enough. PTv2 introduced a rather powerful (and complex!) tagging scheme. PTv3 tries to combine the power of PTv2 with the simplicity of PTv1. The Carto style mainly follows PTv1.

We briefly summarize the bus related relevant parts of PTv1, PTv2 and Carto rendering below. Since it’s not yet approved, we do not discuss PTv3 here.

PTv1

Following PTv1 bus stops are nodes on the road or beside the road with the highway=bus_stop tag. The node should be placed beside the road to indicate the passenger waiting area. For simplicity and for making OSM data more accessible to routing software some mappers place the node on the road.

There’s also a highway=platform tag to map the waiting area as a line, a rectangle or some other shape.

PTv2

In PTv2 a bus stop usually is a group of two objects: a stopping position on the road and a platform beside the road. PTv2 also knows stop areas (relations combining all objects of a stop) and routes (lists of stops for describing bus routes).

The stopping position is a node with public_transport=stop_position and bus=yes. A node on the road with highway=bus_stop is interpreted as stop position, too.

A platform is a node or a way or an area (closed way with area=yes) with public_transport=platform. Often there’s also a bus=yes to indicate the purpose of the platform, but that’s not required by PTv2. A node beside the road with highway=bus_stop is interpreted as platform, too.

Routes in PTv2 should contain both stopping positions and platforms.

Carto rendering

The standard OSM map only renders the following bus stop related objects:

Carto does not use the PTv2 tags for rendering because there are too many ambiguous tag combinations in the OSM database. It’s a long and ongoing discussion:

Mapping schemes

Based on PTv2 and Carto’s behavior we want to derive bus stop tagging schemes which on the one hand are compatible with PTv2 and on the other hand produce acceptable renderings with Carto. We distinguish between stops without platform (just a pole on the side walk, for instance) and stops with platform (waiting area is not part of a sidewalk and has been solely constructed for boarding the bus).

Each tagging scheme gets an abbreviation, which will be used in the bus stop statistics below.

Stops without platform

Stopping position only (SPN)

The simplest bus stop in OSM is

That’s the PTv1 way for tagging a bus stop (although placing the node beside the street is preferred). PTv2 interprets the node as a stopping position. Stopping positions without platform node/way/area are okay in PTv2 (mapping the platform, too, is preferred). Carto will show a bus stop sign on the road.

Platform node only (PFN)

Another simple bus stop is

That’s the preferred PTv1 way for tagging a bus stop. PTv2 interprets the node as a platform. Platforms without stopping position seem to be okay in PTv2 (mapping the stopping position, too, is preferred). Carto will show a bus stop sign beside the road.

Two nodes (PFN+SPN)

The preferred PTv2 way for tagging a bus stop without platform is

Both nodes should also have bus=yes.

Carto won’t show any of the two nodes. To get correct rendering with Carto one of the nodes should additionally have highway=bus_stop, preferrably the platform node. Then Carto shows the bus stop sign on the map.

Stops with platform

Platform and stopping position (PFW+SPN)

The PTv2 way for mapping a stop with platform is

Both objects should also have bus=yes.

None of both objects gets rendered by Carto. To get a bus stop sign on the road add highway=bus_stop to the stopping position node. To get the platform rendered add highway=platform to the platform way/area.

In case of a platform area one may make Carto render a bus stop sign at the platform by adding highway=bus_stop to the area. But then the platform itself won’t get rendered anymore.

Platform with two nodes (PFW+PFN+SPN)

To get better rendering with Carto one may use three objects for a bus stop:

All three objects should also have bus=yes.

None of the three objects gets rendered by Carto. To get a bus stop sign on the platform add highway=bus_stop to the platform node. To get the platform rendered add highway=platform to the platform way/area.

This tagging scheme might contradict the OSM rules ‘one OSM object per real object’ and ’no mapping for the renderer’. But we could argue that the platform node refers to the bus stop pole and the platform way/area to the platform.

Another issue with this tagging scheme is that PTv2 on the one hand expects that a route contains all available stop positions and platforms. On the other hand, PTv2 asserts that each stop is included in routes with two elements, the stop position and the platform. The situation that the platform is represented by two objects is not covered by PTv2 (this fact has been pointed out to the author by Toni Erdmann in a discussion in OSM community forum). If this tagging scheme is used, only one of the two platform objects should be added to routes (else, routing software might run into troubles). Additional tags like bench, bin, wheelchair aso. should then go to the platform object included into routes.

Platform with two nodes, PTv2 compatible (PFW+PFN+SPN+v2)

With a slight modification the previous tagging scheme becomes fully PTv2 compatible:

Here the platform way/area has no public_transport=* tag. Thus, there’s only one platform object (the node), which in addition gets highway=bus_stop to make Carto show the bus stop sign. The platform node represents the stop including all relevant information, whereas the platform way/node plays the role of the ground the stop rests on. This is in complete analogy to the two-nodes variant PFN+SPN for stops without platform, where the stop rests on a sidewalk and the sidewalk does not have any public transport related tags.

Scheme usage statistics

The decision for a tagging scheme to use for adding bus stops to the OSM database should also be based on what schemes other mappers have been following so far in the region of interest. Due to the multitude of possible object and tag combinations it’s hard to get an overview of scheme usage. In this section we provide and use some code to automatically identify bus stop tagging schemes for a region of interest.

Code download and usage

Here is the Python code in a Jupyter notebook:

The code is of poor quality. Don’t expect a piece of highly polished software! It’s more like a proof of concept.

Usage:

  1. Install Jupyter Lab and Python packages folium, geopy, numpy, osmium.
  2. Get OSM data of your region of interest (*.osm or *.osm.pbf format). Use JOSM or OSM’s export feature or BBBike file list or BBBike extract feature.
  3. Write your data’s file name to the first cell in the notebook.
  4. Run all cells in the notebook (may take a while).
  5. The last cell in the notebook shows the interactive map. In addition, a *.html file with the map appears in your working directory.

In the upper right corner of the map you may choose what is shown on the map. Hovering nodes you get some information about the node. Following abbreviations are used:

Results for selected regions

We use the scheme abbreviations introduced above. An s appended to a component of the abbreviation means that a bus stop sign is shown at corresponding location. Without s no bus stop sign is shown. We only consider combinations the author considers acceptable tagging practice:

scheme acceptable comment
SPN yes bus stop on road, no rendering
SPNs yes bus stop on road with rendering
PFN yes bus stop beside road, no rendering
PFNs yes bus stop beside road with rendering
PFN+SPN yes preferred PTv2 bus stop, no rendering
PFNs+SPN yes preferred PTv2 bus stop with bus stop sign at platform
PFN+SPNs no as before, but bus stop sign on road although there’s a platform
PFNs+SPNs no as before, but with two bus stop signs
PFW+SPN yes PTv2 platform way/area, platform may be rendered, but no bus stop sign
PFWs+SPN yes PTv2 platform area with bus stop sign at platform
PFW+SPNs yes PTv2 platform way/area with bus stop sign on road
PFWs+SPNs no PTv2 platform area with two bus stop signs
PFW+PFNs+SPN yes platform way/area with bus stop sign at platform
PFWs+PFNs+SPN no platform area with two bus stop signs at platform
PFW+PFNs+SPNs no platform way/area with two bus stop signs
PFWs+PFNs+SPNs no platform area with three bus stop signs
PFW*+PFN+SPN* no useless, because the platform node’s purpose is to have a bus stop sign
PFW+PFNs+SPN+v2 yes platform way/area with bus stop sign at platform
PFWs+PFNs+SPN+v2 no not possible because highway=* would have two values
PFW+PFNs+SPNs+v2 no platform way/area with two bus stop signs
PFWs+PFNs+SPNs+v2 no not possible because highway=* would have two values
PFW*+PFN+SPN*+v2 no useless, because the platform node’s purpose is to have a bus stop sign

Route membership is relevant for categorization, too. If something is wrong with route membership (only one of the two nodes in PFN+SPN belongs to a route, for instance), then the bus stop does not belong to the category.

Regions shown here have been chosen without thinking to much about it. One is the author’s home region. The others are randomly chosen cities and regions in Germany.

Stops without platform way/area:

scheme Berlin Chemnitz-Zwickau Darmstadt Munich Reutlingen
SPN 180 (61.9%) 176 (4.7%) 25 (2.0%) 33 (2.2%) 58 (3.3%)
SPNs 1 (0.3%) 595 (15.8%) 33 (2.6%) 88 (5.8%) 9 (0.5%)
PFN 0 6 (0.2%) 0 0 2 (0.1%)
PFNs 11 (3.8%) 251 (6.7%) 441 (34.4%) 117 (7.7%) 76 (4.3%)
PFN+SPN 0 14 (0.4%) 0 0 5 (0.3%)
PFNs+SPN 99 (34.0%) 2353 (62.4%) 773 (60.3%) 1128 (74.1%) 1579 (89.7%)
other 0 375 (9.9%) 9 (0.7%) 156 (10.2%) 32 (1.8%)
total 291 3770 1281 1522 1761

Stops with platform way/area:

scheme Berlin Chemnitz-Zwickau Darmstadt Munich Reutlingen
PFW+SPN 12 (0.4%) 21 (14.5%) 57 (18.1%) 62 (2.7%) 19 (11.2%)
PFWs+SPN 0 0 5 (1.6%) 361 (15.8%) 8 (4.7%)
PFW+SPNs 1 (0.0%) 50 (34.5%) 127 (40.3%) 1631 (71.3%) 4 (2.4%)
PFW+PFNs+SPN 3288 (97.6%) 28 (19.3%) 54 (17.1%) 132 (5.8%) 97 (57.4%)
PFW+PFNs+SPN+v2 0 1 (0.7%) 0 2 (0.1%) 1 (0.6%)
other 67 (2.0%) 45 (31.0%) 72 (22.9%) 100 (4.4%) 40 (23.7%)
total 3368 145 315 2288 169

Maps with categorized stops (large ones may significantly slow down your browser):

Results for the five regions are quite different. Berlin uses PFW+PFNs+SPN for almost all stops. Munich is quite uniform, too, with PFNs+SPN and PFW+SPNs for three quarters of all stops. Reutlingen’s stops without platform way/area mostly follow PFNs+SPN like in Munich. Scheme usage in Chemnitz-Zwickau region and in Darmstadt is far from being consistent. Especially, one thrid of all stops with platform way/area in those regions (and Reutlingen) do not follow one of the acceptable schemes.

From manual spot-checking one sees that a major issue with ‘other’ platform way/area stops is that only the stop position is in the routes (not allowed in PTv2). For stops without platform way/area the most common deviation from the schemes listed above are additional bus stop signs on the road although there’s a stop bus sign at the platform already.

Categorization of stops heavily relies on the automatic assignment of stop positions to platform nodes/ways/areas and of platform nodes to platform ways/area. The assignment procedure uses simple distance measuring (closest node within 30 meter radius around node or way/area). There seem to be few cases where this algorithm yields incorrect results, mostly because the stop position is too far away from the platform or the closest stop position belongs to another platform.

Another issue with the approach are bus platforms having public_transport=platform but no bus=yes. In view of PTv2 this is okay. But our code does not recognize such platforms as bus related. Consequently, there will be stop positions without platform. Not expecting bus=yes for platforms would bring many tram-only platforms into the game, again causing wrong categorization.

Starting bus stop mapping, the author came up with the idea to use PFW+PFNs+SPN+v2, which seemed to be an elegant tagging scheme meeting the requirements of PTv1, PTv2 and Carto and which by the way establishes stronger parallels between stops with and without platform ways/areas (cf. description of scheme above). Based on a discussion in OSM community forum PFW+PFNs+SPN+v2 seemed to be quite uncommon in mapping practice. That discussion has been the starting point for the bus stop statistics project. To the author’s regret, PFW+PFNs+SPN+v2 indeed is rarely used in OSM.