# Agency data in OpenStreetMap: the map has your stops, not your identifiers

> OpenStreetMap mappers have already placed most of the objects an agency wants to contribute, and placed them well. What the map lacks is the agency's own IDs, which is the one thing only the agency can supply.

Published 2026-08-27, updated 2026-08-28 by Nick Sawinyh.
Explainer in Interoperability.
Canonical: https://its-feed.com/articles/transit-data-in-openstreetmap/
Keywords: openstreetmap transit data, gtfs openstreetmap, gbfs openstreetmap, osm bus stop tagging, openstreetmap import, gtfs stop_id osm, transit agency open data

---

An agency that decides to put its bus stops, bike racks or [bike share
docks](https://its-feed.com/articles/shared-mobility-data-stack/) into OpenStreetMap almost always
starts by preparing geometry. The stop inventory gets exported, the coordinates
get cleaned up, somebody asks how to upload it. That is the wrong end of the
problem, and the map can prove it.

In August 2026 we took every US bike share system in the [MobilityData GBFS
catalog](https://github.com/MobilityData/gbfs) that serves an open
`station_information.json`, which is 64 systems and 9,998 docked stations, and
matched each station against every `amenity=bicycle_rental` object in the
United States. Of the 9,998 stations, 6,222 already existed in OpenStreetMap
within 80 feet. The median distance between the agency's own published
coordinate and the one a mapper had put there was 9.4 feet.

![Horizontal bar chart of three nested counts of US bike share docking stations: 9,998 docked stations in US GBFS feeds, 6,222 already in OpenStreetMap within 80 feet, and 3,047 whose OpenStreetMap object carries an identifier that resolves. An annotation notes that 2,332 of the 3,047 are one system, Citi Bike in New York.](https://its-feed.com/charts/transit-data-in-openstreetmap-identifier-gap.png)

*The geometry is largely done. The link back to the operator's data is not. Source: ITS Feed measurement, 2026-08-27. Station coordinates from every US system in the MobilityData GBFS catalog serving an unauthenticated station_information.json, matched by nearest neighbour against 11,497 OSM amenity=bicycle_rental objects from the Overpass API. Method in research/data/osm_gbfs_match.py.*

The third bar is where it comes apart. Of the 6,222 objects the map already
had, 3,138 carried any kind of reference tag, and 3,047 carried one that
actually resolves to a station in the operator's live feed. Citi Bike accounts
for 2,332 of those. Take New York out and the picture is 3,886 matched objects,
802 with a reference of any kind, 715 that resolve. The map has at least one
dock from 46 of the 64 systems, and for 34 of those 46 it carries no identifier
on any of them.

Volunteers have already done the surveying here, and they did it well. What
they cannot do, because it is not visible from the sidewalk, is write down the
ID the agency uses internally for that object.

## The coordinate is not the contribution

The instinct to lead with geometry comes from a reasonable assumption: the
agency owns these assets, so the agency must have the better position for them.
Across 6,222 matched pairs that assumption does not hold up.

![Bar chart of the distance between each GBFS station coordinate and the nearest OpenStreetMap bicycle rental object, in 8-foot bins from 0 to 80 feet: 2,854 within 8 feet, 1,144 from 8 to 16, 707 from 16 to 24, 478 from 24 to 32, 323 from 32 to 40, 239 from 40 to 48, 186 from 48 to 56, 120 from 56 to 64, 89 from 64 to 72, and 82 from 72 to 80.](https://its-feed.com/charts/transit-data-in-openstreetmap-offset-distribution.png)

*Two thirds of the matched docks sit within 16 feet of the coordinate the operator publishes. Neither dataset is systematically the worse one. Source: ITS Feed measurement, 2026-08-27. The 6,222 matched pairs from the same run. Method in research/data/osm_gbfs_match.py.*

A median disagreement of 9.4 feet is what two independent surveys of the same
object look like, and nothing in the distribution says either side is
systematically drifting. We did not classify the tail of that chart case by
case, so we cannot say what the objects out at 70 feet have in common.

So an import that pushes agency coordinates over the top of existing
OpenStreetMap nodes buys very little, and it costs the map the survey history
attached to the objects it overwrites. The [import
guidelines](https://wiki.openstreetmap.org/wiki/Import/Guidelines) are direct
about the risk: poor imports have significant impacts on both existing data and
local mapping communities, and the Data Working Group exists in part to stop
them.

## The identifier is the contribution

The tag an agency can supply and nobody else can is the primary key. Once
`gtfs:stop_id:US-WA-KCM=5980` sits on the stop node at Phinney Avenue North and
North 46th Street in Seattle, as it does today, anyone can join OpenStreetMap
geometry to that agency's schedule, its real-time feed, its ridership table and
its asset register without doing a spatial match first. Spatial matching is
exactly the step this article had to perform to produce the numbers above, and
it is lossy in ways that matter. Even at 80 feet, 48 of the OpenStreetMap
objects we matched came out as the nearest neighbour for more than one station,
pulling 102 stations into a collision that a stored identifier would have
resolved instantly.

Almost nobody has done it. Worldwide, taginfo counts 4,161,791 objects tagged
`highway=bus_stop`, and 129,769 of them carry the unsuffixed `gtfs:stop_id`
key. That is 3.1 percent. The 108 feed-suffixed variants sit on 111,699 objects
in total, but taginfo does not break that figure down by object type and some
of it lands on rail and ferry stops, so the share of the world's bus stops
carrying any GTFS identifier at all is somewhere under 6 percent.

![Horizontal bar chart of OpenStreetMap objects carrying a feed-suffixed gtfs:stop_id key, grouped by the country prefix of the feed code: France 41,992, Israel 30,952, Hungary 16,421, United States 14,152, Belgium 931, Sweden 707, Spain 585, Austria 464, Canada 308.](https://its-feed.com/charts/transit-data-in-openstreetmap-by-country.png)

*France, Israel and Hungary hold four fifths of every feed-linked stop in the map. The United States, which publishes more GTFS feeds than any of them, is fourth. Source: taginfo.openstreetmap.org API v4, keys/all query for gtfs, data_until 2026-08-27T00:59Z. Grouped by the ISO 3166-2 country prefix of each feed code. Method in research/data/osm_identifier_census.py.*

The US share is 14,152 objects across 13 feed codes. King County Metro accounts
for 4,645 of them, Milwaukee County Transit for 3,846 and Capital Metro in
Austin for 2,327. Those three agencies are more than three quarters of the
American total, and the remaining ten feeds share 3,334 objects between them.

## What the agency gets back

Everything above is an argument about what the map is missing, which is not by
itself a reason for anyone to spend a budget cycle on it. There is a return,
and it arrives in two forms.

The first is that the dependency may already exist. OpenTripPlanner [builds its
representation of the transportation
network](https://docs.opentripplanner.org/en/latest/) from open data in open
standard file formats, primarily GTFS and OpenStreetMap. GTFS supplies the
service. OpenStreetMap supplies the sidewalks, crossings, curb ramps and paths
a rider walks to reach it. Any agency or state DOT running a trip planner on
OTP is therefore publishing walking directions computed on the map, whether or
not it has ever contributed a node to it.

The second is the survey work volunteers have already done on the stops
themselves, which is a good deal more than most agencies would guess.

![Horizontal bar chart of the share of the world's 4,161,791 OpenStreetMap bus stops carrying each tag: shelter 44.0 percent, bench 34.2 percent, waste bin 22.5 percent, tactile paving 17.7 percent, lit 15.3 percent, departures board 8.5 percent, wheelchair access 7.6 percent, and GTFS stop_id 3.1 percent.](https://its-feed.com/charts/transit-data-in-openstreetmap-what-osm-knows.png)

*Shelter is recorded on fourteen times as many bus stops as the identifier that would let an agency read it. Source: taginfo.openstreetmap.org API v4, tag combinations for highway=bus_stop, data_until 2026-08-28T00:59Z.*

Shelter is on 44 percent of the world's bus stops, bench on 34 percent, tactile
paving on 18 percent, lighting on 15 percent, and a wheelchair access
assessment on 7.6 percent. Every one of those fields costs a field visit to
collect, which is why stop inventories tend to be thin on them, and every one
has already been filled in by somebody who walks past the stop anyway.

None of it is reachable without the identifier. A tag on an OpenStreetMap node
is worth nothing to an agency database until something says which row of
`stops.txt` that node is. The ID is what turns a public map into a source the
agency can query on a schedule.

The United Kingdom has been running this arrangement for years. The Department
for Transport released the [NaPTAN stop
database](https://wiki.openstreetmap.org/wiki/NaPTAN) under the Open Government
Licence, which the OpenStreetMap community treats as ODbL-compatible, and it
was imported region by region. Today 275,614 bus stops in the map carry a
`naptan:AtcoCode`, more than twice the 129,769 that carry the GTFS stop key
worldwide. British operators can join a national volunteer survey to their own
asset register on a primary key. American ones mostly cannot, and the obstacle
is the paperwork in front of the mapping rather than the mapping itself.

## Why France is at the top of that chart

What separates them is whether the licence question already has an answer by
the time a mapper goes looking for it.

Step 2 of OpenStreetMap's import process is licence approval, and the wording
leaves no room: the data must be compatible with the ODbL, and where the
licence is unclear, restrictive, or simply absent, the importer has to go and
ask the owner. The step cannot be deferred to the end, because everything after
it depends on the answer.

For a US agency, that question usually has no answer on file. Of the 914
non-deprecated US GTFS feeds in the Mobility Database catalog, read on
2026-08-27, only 138 carry a licence URL. That is 15 percent, and it is the
lowest rate of any country publishing more than twenty feeds.

| Country | Non-deprecated GTFS feeds | Feeds declaring a licence |
| --- | --- | --- |
| United States | 914 | 138 (15%) |
| Spain | 149 | 128 (86%) |
| Canada | 110 | 82 (75%) |
| France | 90 | 76 (84%) |
| Sweden | 59 | 59 (100%) |
| Germany | 50 | 29 (58%) |

Sweden declares a licence on every feed and still has only 707 tagged stops, so
a clear licence is necessary rather than sufficient. What it does is remove the
step that otherwise stops the work before it starts. A volunteer who wants to
link a French feed can read the terms in a minute. For five American feeds in
six there is nothing to read, and the correct response to that is to leave the
data alone.

Fixing this is a form letter, not a negotiation. OpenStreetMap publishes
template wording drawn from requests that have already worked, and the sentence
it asks the owner to sign is a single line: the organisation "has no objections
to geodata derived in part from #DATASET# being incorporated into the
OpenStreetMap project geodata database and released under a free and open
license". Signing it once, for the whole feed, answers the question for every
contribution that follows.

The requirement bites even where the licence is already open. The [Docomo Bike
Share
import](https://wiki.openstreetmap.org/wiki/Import/Catalogue/GBFS_Docomo_Bike_Share_Import)
in Japan, the worked GBFS example in OpenStreetMap's own import catalogue, took
its data from a source published under CC BY 4.0. The importer still obtained
separate written permission from the data owner, dated 2023-11-20, before
adding any of the 3,035 cycle ports.

## Three routes, and they do not cost the same

The full import is the heavyweight option and the one most agencies imagine
when they think about this. It runs to six mandatory steps, in order.

| Step | What it requires |
| --- | --- |
| 1. Prerequisites | Learn the editor, read what has gone wrong with past imports, and sound out the local community before committing to anything |
| 2. Licence approval | The data must be compatible with the ODbL. Where the licence is unclear, restrictive or missing, ask the owner and get the answer in writing |
| 3. Documentation | A plan on the OpenStreetMap wiki covering the conversion to OSM XML, conflation, the mapping from GIS attributes to tags, how the work is divided, changeset size, quality assurance and how to revert |
| 4. Community buy-in | Discussion with the local mapping community, in the guidelines' own words: you must not import the data without local buy-in |
| 5. Import review | A post to the Community Forum tagged `import`, which sits for 14 days while concerns are answered. Only then may the import begin |
| 6. Uploading | An import-only account named `<username>_Import`, following the published plan and reporting progress as it goes |

Conflation sits underneath all of it rather than at one step, because
OpenStreetMap has no concept of layers and nothing stops an import from laying
a second copy of every stop on top of the first. The Docomo project ran this
route with JOSM, using the OpenData plugin to read the converted CSV and the
Conflation plugin to merge it, and committed to re-checking the GBFS feed at
least twice a year afterwards. Their conflation rule is a good one to copy: if
an OpenStreetMap node already exists, keep whichever coordinate looks more
accurate; if the existing feature is a way or a relation, keep the way or the
relation; add a node only where nothing exists.

The cooperative MapRoulette challenge is the middle option. The agency
generates the edits it would like to see and publishes them as tasks, and a
human mapper approves, rejects or modifies each one inside MapRoulette, which
submits the accepted result to OpenStreetMap. No import account, no bulk
upload, a person on every object.
[mr-cli](https://github.com/maproulette/mr-cli) turns a `.osm` or osmChange
file into the challenge JSON. Note that tag-fix tasks are one edit per task and
any grouping in the source file is ignored, so the task count is the number of
tags, not the number of stops.

Identifier-only linking is the light option and the one the numbers argue for.
Touch no geometry, add no objects, just attach `gtfs:stop_id:<feed>` to stops
the map already has. It is not an import in the contentious sense, because
nothing is being added to the database that was not already surveyed. It is
also the only one of the three that is proportionate to what is actually
missing.

That does not make it unregulated. A scripted tag addition is an automated
edit, and the [Automated Edits code of
conduct](https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct)
applies in full: document and discuss the plan beforehand, name who is making
the change with contact details, describe what the script does, publish a way
to opt out and honour it when someone asks, test on a small area first, keep
changesets regional and sensibly sized, and tag them `mechanical=yes` or
`bot=yes` with a link back to the documentation. Public transport has its own
mailing list, talk-transit, and the code of conduct says to use it. Edits that
skip this get reverted and accounts get blocked, which is a slower path to
nowhere than doing it properly.

## What the tags actually are

The [GTFS tagging convention](https://wiki.openstreetmap.org/wiki/GTFS) is
settled enough to follow without a proposal. Feed codes should start with the
ISO 3166-2 region code for the area the service runs in and must not contain a
colon, since the colon is what separates the key from its suffix. The suffix is
the point of the scheme: it lets one stop carry references to several feeds at
once, which is what a station near an operating boundary needs.

| Object | Core tags | The link back to the agency |
| --- | --- | --- |
| Bus stop | `highway=bus_stop`, `public_transport=platform`, `name`, `operator`, `network` | `gtfs:stop_id:<feed>`, `gtfs:stop_code:<feed>` |
| Bike share dock | `amenity=bicycle_rental`, `bicycle_rental=docking_station`, `capacity`, `brand`, `network` | `gbfs:system_id`, `gbfs:station_id` |
| Bike rack | `amenity=bicycle_parking`, `bicycle_parking=<type>`, `capacity`, `covered`, `access`, `fee`, `operator` | none |

The last row is the one that catches people out. A bike rack appears in no
feed, so it has no identifier to carry, and the useful contribution there is
capacity and whether the thing is covered. Agencies routinely bundle racks and
docks into the same "bike infrastructure" layer; OpenStreetMap keeps them
apart, because a rack you lock your own bike to and a dock that rents you one
are different objects to anyone routing a trip. Worldwide there are 930,308
`amenity=bicycle_parking` objects and 94,151 `amenity=bicycle_rental` ones, so
the racks are not a rounding error in the map even though they are absent from
the data layer entirely.

Older forms of these keys are still common and should not be copied. The
underscore namespace, `gtfs_stop_id` and friends, is discouraged, and the bare
`gtfs:feed` key that declares which feed an object belongs to is deprecated in
favour of the suffix, though 59,140 objects still carry it and a consumer
should read it as if its value had been appended to every unsuffixed GTFS key
on the object.

## Pick the column that will still be there next year

The tagging convention's first instruction is to look through historic versions
of the feed and work out which columns hold a stable value, because different
versions can use different IDs for the same object. That is not a hypothetical.

Of the 9,998 US docked stations we pulled, 4,401 have a UUID for a
`station_id`, 3,626 have a long numeric ID, and 1,961 have an ID prefixed with
the system name. The five largest systems in the sample all carry both a UUID
and a numeric form inside the same `station_id` field, which is what a
migration looks like when it is half done. Whichever ID an agency hands to a
mapper, some of those values will be replaced without warning and the tag on
the map will quietly stop resolving.

There are two defences and an agency should offer both. Publish a second
identifier alongside the volatile one, which in GBFS is what `short_name` is
for and in GTFS is `stop_code`, and say plainly which of the two will not move.
Neither specification guarantees stability on the agency's behalf, so the
statement has to come from the agency. Then commit to a re-check cadence in
writing, the way the Docomo project committed to twice a year. A link that
nobody revalidates decays into something that still looks authoritative while
pointing at nothing, which is worse for the map than no link at all.

Tooling for the mechanical part already exists and it is worth using before
writing anything new. [GTFS Janitor](https://github.com/tjhorner/gtfs-janitor)
takes a GTFS zip and an import profile, conflates it against OpenStreetMap,
walks a person through the ambiguous matches and emits an osmChange file, all
in the browser with no server involved. Its README suggests King County Metro's
feed as the quick demo, and King County Metro is the American agency at the top
of the tagged-stop table. We have not established that the one caused the
other.

## What this looks like as a work item

An agency with a stop inventory, a GTFS feed and no OpenStreetMap presence has
a short list. Put a licence on the feed, in the feed, so that the question has
an answer without an email. Decide which identifier column is the stable one
and say so. Then either link the identifiers directly under the automated-edits
rules, or hand the proposed links to the local mapping community as a
MapRoulette challenge and let them apply the ones that are right.

None of that involves uploading a single coordinate, which is the part that
would have taken the longest and, on the evidence above, improved the map the
least.

It buys about the cheapest data collection a transit agency will be offered: a
survey that is already finished, that refreshes without anyone being dispatched
to a corner with a clipboard, and that costs a licence statement and a column
of IDs.

## Frequently asked questions

### How does a transit agency add its bus stops to OpenStreetMap?

Usually it should not add them, because they are already there. The productive contribution is to attach the agency's own identifiers to the objects OpenStreetMap already has, using the feed-suffixed keys from the GTFS tagging convention, such as gtfs:stop_id:US-WA-KCM. Adding new geometry is a formal import, which triggers OpenStreetMap's six-step import process including licence approval, a written plan, local community buy-in, and a proposal that sits for 14 days before any edit is made.

### What tags does a bus stop need in OpenStreetMap?

A roadside stop is highway=bus_stop plus public_transport=platform, with name, operator and network. The link back to the agency's data is gtfs:stop_id:<feedcode> and, where it is stable, gtfs:stop_code:<feedcode>. The feed code should start with the ISO 3166-2 region code for the area the service runs in and must not contain a colon, because the colon separates the key from the suffix.

### Do I need permission to put agency data into OpenStreetMap?

For an import, yes. OpenStreetMap's import guidelines require the data to be compatible with the ODbL, and where the licence is unclear or restrictive the importer must contact the data owner and get that in writing. An open licence on its own is not always enough: the Docomo Bike Share import in Japan was already published under CC BY 4.0 and still obtained separate written permission, dated 2023-11-20, before any of its 3,035 cycle ports were added.

### Is adding tags with a script an import?

No, but it is an automated edit, and the Automated Edits code of conduct applies. That means documenting and discussing the plan before running it, saying who is making the change and how to reach them, publishing a way to opt out, tagging the changesets mechanical=yes or bot=yes, and linking each changeset back to the documentation. Public transport edits should also be raised on the talk-transit list.

### How many transit stops in OpenStreetMap carry a GTFS ID?

Very few. Of 4,161,791 objects tagged highway=bus_stop worldwide, 162,873 carry an unsuffixed gtfs:stop_id key and 111,699 carry one of the 108 feed-suffixed variants, as of the taginfo snapshot for 2026-08-27. Counting only objects that are both a bus stop and carry the unsuffixed key gives 129,769, or 3.1 percent. Just 14,152 of the feed-suffixed objects belong to US feed codes, spread across 13 feeds.

### Why would a transit agency want its IDs in OpenStreetMap?

Because the traffic runs both ways. OpenTripPlanner builds its network from GTFS and OpenStreetMap, so an agency running an OTP trip planner already computes its walking directions on the map. And volunteers have recorded attributes that agency stop inventories are usually thinnest on: shelter on 44 percent of the world's bus stops, bench on 34 percent, tactile paving on 18 percent, lighting on 15 percent and a wheelchair assessment on 7.6 percent. None of that can be read back into an agency database until an identifier says which OpenStreetMap node is which row of stops.txt.

### What about bike racks?

Bike racks are amenity=bicycle_parking, and they carry no GTFS or GBFS identifier at all, because they appear in no feed. The useful tags there are bicycle_parking for the rack type, capacity, covered, access, fee and operator. Agencies routinely conflate racks with bike share docks; the map does not, and neither should the contribution.

---

Source: ITS Feed, https://its-feed.com/articles/transit-data-in-openstreetmap/
ITS Feed is an independent editorial site on the data and technology layer of transportation, published by the team at Veodyn. Figures trace to the sources linked inline.
Site index for agents: https://its-feed.com/llms.txt
