Explainer · Interoperability
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.
An agency that decides to put its bus stops, bike racks or bike share docks 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 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.

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.

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 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.

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 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.

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 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 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 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
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 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 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.
Common 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.