Mapping pedestrian and bicycle crossings as nodes
Posted by Peter Elderson on 3 March 2025 in English. Last updated on 5 March 2025.Introduction
This diary entry describes my current view on how best to map and tag pedestrian and bicycle crossings. Best, considering detail, correctness, time consumption, clarity and usability. The many words in this diary may make it seem complicated, but the actual tagging is designed for easy and direct node tagging of what you see on the road, with as little redundancy and required expertise as possible. As follows:
A simple unmarked, uncontrolled crossing is just an intersection node without any tags.
A simple zebra can be tagged with highway=crossing + crossing=zebra (or equivalent ansd just as easy: highway=crossing + crossing:markings=zebra)
A simple crossing with other markings can be tagged with highway=crossing + crossing:markings=dots/dashes/lines/surface
If traffic lights control the crossing, add crossing:signals=yes
If there are special kerbs, add kerb=lowered/flush/…
If there is tactile paving, add tactile_paving=yes
If there is a crossing island within the crossing, add crossing:island=yes
If the crossing path goes uninterrupted over the road it crosses, so that the road is interrupted rather than the crossing path, ad crossing:continous=yes
Scope:
- Footway crossing any higher order way, including cycleway and busway, excluding rail.
- Cycleway crossing any higher order way, including busway, excluding rail.
- Mentioned, but not detailed: paths, including combined footway/cycleway paths as mapped regulary in Germany.
- Mentioned, but excluded: designated horse crossings.
- Mentioned, but excluded for now: how to map a crossing as a way.
- Mentioned, but excluded for now: detailed mapping of the operation of traffic signals.
- Mentioned: level crossing over tram railways
Basic principles:
- Consider only nodes where a footway, path or cycleway intersects a higher order way, or would intersect if it is actually drawn as a way of its own.
- The intersection of two ways is already a crossing node, even without any tags. It gives the location and the fact that the ways cross, and type and access/designation tags from the crossing way apply to the crossing node.
- only add the highway=crossing tag and additional tags if there are actually attributes to tag, which do not follow (inherit) from the crossing way itself.
- Only tag positive attributes, not missing attributes, unless: a. the applicable default values in your country differ from world-wide defaults; b. the no indicates something generally unexpected, such as crossing=no on a location that cannot be crossed.
- All existing crossing=* schemas are flawed and form a chaotic mix, leaving data users and other mappers to guess what was meant. I use only the additional tags to describe each additional attribute. A crossing= value may still be computed from the separately tagged attributes, for any of the previously used mixed schemes.
- For incremental mapping (start simple and add details later) crossing=zebra is acceptable as a stub for a zebra crossing. All the other crossing types have unclear meanings, because of historical differences in tagging schemes. Note that in some countries even crossing=zebra has been used systematically for non-zebra crossings!
Explanations of the basic principles
Ad 1. If a path, footway or cycleway is not actually drawn in OSM, you can still put a node on the way representing the place where the actual crossing is. In this case, it’s required to tag it highway=crossing, and preferably a tag to indicate how people can see that it’s a crossing (crossing:markings=zebra/dots/dashes/lines/surface and/or crossing:signals=yes)
Ad 2. The intersection node of a footway with a higher order way is a pedestrian crossing with access foot=designated. If the footway is tagged with bicycle=yes and/or horse=no, the crossing is also foot=designated + bicycle=yes and/or horse=no. Explicit tagging of the node with the same information is redundant, unnecessary, because the information is already there.
Ad 3. Information which warrants explicit tagging of the crossing node is: markings, signal control, tactile_paving, special kerbs, presence of a (safe) crossing island, access or designation not present on the crossing way (or in absence of the crossing way).
Ad 4. Many crossings are tagged as e.g. highway=crossing + crossing=unmarked/uncontrolled + crossing:markings=no + crossing:signals=no + crossing:island=no + tactile_paving=no. The only information there (apart from being an intersection) is that someone sometime did not see those attributes. While that is useful workflow information for a mapathon, OSM generally stores what you can see, not what you can not see, and it’s up to data users to determine what to do if they want information which is not there. We should be clear in what we tag and how, so data users can apply logical defaults. Only if e.g. a national default is clearly different from the OSM-wide default, it is sometimes wise to tag no. Tagging crossing=no (without highway=crossing) on a location where seemingly a crossing is possible: an example is a point where separately mapped cycleways are linked from both sides to the centre line representing the road. This would suggest a crossing, but that is an artefact of using short linking sections to make routing possible.
Ad 5. These special tags I often use:
- crossing:markings=zebra/dots/dashes/lines/surface /* road markings showing where to cross
- crossing:signals=yes /* the traffic over the crossing node is normally controlled by traffic lights
- crossing:island=yes /* the crossing has a traffic island, but the road has not been split around it.
- kerb=yes/lowered/flush/… /* The kerb type, important for the impaired pedestrian
- tactile_paving=yes /* presence of tactile paving to guide the visually impaired pedestrian over the crossing.
- crossing:continous=yes /* The crossing path goes uninterrupted over the crossed way; the crossed way is visually interrupted rather than the crossing path.
Tag what’s there, not what you would expect
Only tag positive values, where the expected default is no. However, for footways a kerb is to be expected, so kerb=yes on a foot crossing is redundant and kerb=no is special, to be tagged if it is seen.
bicycle=yes/designated?
In Nederland, bicycle=yes and bicycle=designated have been used a lot. I regard this as unnecessary for a bicycle crossing, because the crossing cycleway already contains that information. Only if a bicycle crossing has been mapped without a crossing way, an explicit bicycle=designated would be warranted. In Nederland, crossings without a crossing way in OSM are always pedestrian crossings. I don’t know if this default holds up world-wide, though.
highway=path
Paths crossing a higher order road can be handled according to the same basic principles. Since the access/designation of a crossing is taken from the crossing way, it only requires extra tagging if there is an exception. E.g. the path is by default allowed for pedestrians, bicycles and horses, but horses are not allowed to cross, then add horse=no to the crossing (section of the) way. If the path is for bicycles and pedestrians without segregation, but the crossing has separate lanes for pedestrians and cyclists, add segregated=yes to the crossing way, or use separate ways on the crossing. Likewise, if the path is segregated but the crossing is not, split off the crossing section and tag segregated=no on the crossing section.
Crossing node or crossing way?
I think it is acceptable to map both the node(s) as highway=crossing and the way as a *way=crossing, but tag the details on either the node OR the way, not on both at the same crossing. The exact geometry of a crossing can be mapped using the crossing way, adding way type and access as needed, possiby split into sections such as cycleway=crossing, footway=traffic_island and kerb nodes at the exact spots. My preference is to tag markings, traffic signal control, tactile paving and kerbs on crossing nodes, and to add a crossing node on every intersection node on the crossing.
Example. Suppose we have a footway crossing a secondary road that has two separate ways for the directions, a traffic island in between, and separately mapped cycleways on both sides; and zebra markings from side to side; and traffic lights for pedestrians to cross the main road, but not the cycleways. There is tactile paving all along, and kerbs are lowered.
I would draw a highway=footway from side to side, crossing a cycleway, two halves of the secondary road, and again a cycleway. I would 1. tag the footway as highway=footway + footway=crossing. 2. tag the four intersection nodes as highway=crossing with crossing:markings=zebra + tactile paving=yes + kerb=lowered. 3. additionally tag the two footway/tertiary intersection nodes with crossing:signals=yes
Now this is intermediate level of detail mapping. Other mappers might just put crossing=zebra on the intersection nodes: low level of detail (entry level duck tagging). High level of detail would be to add nodes for the exact postion of traffic lights and kerbs, splitting the footway into sections for approach, crossing and traffic_island, and e.g. tagging request buttons, sounds and vibrations.
Horse crossings
I don’t know any designated horse crossings in Nederland, although I am sure there are some. Since it would be a bridleway crossing a higher order road, I think the basics are the same as for cycleways and footways. There might be special markings, then we could simply add a value for crossing:markings. Where horses are allowed on footways, paths and cycleways, not even horse-yes would be needed. If they are -by exception- not allowed, add horse=no to the crossing footway/cycleway/path. I know that in several places high placed request buttons are present for horse riders. This is probably best tagged as a detail on the crossing nodes or on the highway=traffic_signals nodes. I don’t know an existing or proposed tag for this.
Tram level crossings for pedestrians and cyclists
In Dutch cities, many pedestrian and bicycle crossings also cross tramways. The mapping of the intersection nodes is inconsistent, to put it mildly. Let’s say that the nodes are tagged railway=crossing. Where the crossing path has markings, I simply add crossing:markings= to the intersection node. Where the tram crossing is controlled by lights regulating the flow of pedestrians/bicycles, add crossing:signals=yes. Where the tramway crossing and the main road crossing coincide, which is a common occurrence, the intersection node simply gets both the highway=crossing and the railway=*crossing tags, and the additional detail tags.
What about crossing_ref?
Nederland does not have a reference list of crossing types. The only crossing type with a nickname is the zebra crossing. Some mappers use crossing_ref to mean that it’s an official pedestrian crossing with zebra markings and either the official NL:L2 traffic sign or traffic signals controlling the two traffic streams. However, many more mappers have used it as an easy way to indicate what’s known colloquially as “a zebra” (or “zebrapad”), which does not require signs or signals, just zebra markings. In addition, no efforts are made or planned to correct the faulty usage. And we have the approved and unambiguous tag control:markings=zebra to capture the markings. All in all, the crossing_ref key is currently useless in Nederland.
Finally: Why this blog?
I have seen the ugly results of persistent competing mapping and tagging schemes for crossings, defining crossings on the basis of two independent attributes which may or may not be present, or known. Now, in Nederland, different crossings may have equal tagging, and equal crossings may have different tagging. The different mapping and tagging schemes all live on, also because different tools use the same tags to mean different things. As a result, data users cannot know what information the mapper (or their tools) had in mind and what the actual situation on the road is. Wild/ I mean educated guessing is an option, but I think most data users will just ignore the unclear features, and at most put an icon for a highway=crossing, no details. The way I map’m, there is no ambiguity in the crossing=* tag, because it is not necessary at all. Instead of guessing the attributes from the crossing= value, you could deduct the crossing= value from the mapped attributes using the scheme you like most. If you can’t assign a crossing type because you don’t know the right value(s) for markings and control, then don’t. Just tag what you now. Only one exception: highway=crossing + crossing=zebra remains as an entry level duck tag for zebra crossings. I consider it a kind of fixme note.
Discussion
Comment from SiennaShade on 4 March 2025 at 22:38
Some thoughts on this:
crossing=zebra — I wouldn’t use this tag at all. If you don’t know if there are traffic signals or not, crossing=marked + crossing:markings=zebra can be used instead. crossing=marked has about 2 442 000 uses worldwide on taginfo, and crossing=zebra has about 464 000 uses. Also I believe crossing=zebra is deprecated, and as you said its meaning is confusing and it has been widely misused.
highway=crossing + kerb tag — if the kerbs are not micro-mapped with barrier=kerb nodes this is okay, but if they are mapped separately, according to the OSM wiki the kerb tag should only be on the barrier=kerb nodes.
“… but preferably tag the details on either the node OR the way, not on both at the same crossing” — I’d add tags like crossing, crossing:markings, crossing:signals to the crossing node, because this is an older and better supported tagging scheme. Tagging only the way with crossing tags is not well supported now. Though tags like bicycle=designated, segregated should go on the way, like you said.
Comment from Peter Elderson on 5 March 2025 at 07:13
Thanks @SiennaShade for your thoughts. You may have noticed I don’t use the crossing key at all for crossings; only crossing=no for non-crossings. I did notice that other mappers tend to get very touchy about crossing=*, so in my efforts to improve the mapping and tagging of crossings, I left the crossing key alone, mostly, unless it was clearly wrong. My preferential mapping does not require a crossing tag.
Mappers in Nederland definitely did not deprecate crossing=zebra. I think they have a point when they say that zebra is the only value of crossing that describes a generally known type of crossing, so that’s what they use for starters, and the rest is up to mappers who want to add more detail. As far as I am concerned, that’s fine because I don’t rely on the crossing tag at all. I think the international overall picture is just as mixed and chaotic as the Dutch situation.
I don’t agree with your assessment that crossing=zebra is confusing, though. I think it is the one value that is not confusing at all! It says exactly the same as crossing:markings=zebra. In a few countries crossing=zebra has been used for crosswalks of any kind; I think that is wrong, and probably confuses mappers in those countries, but that is not due to the value but to the wrong usage in those countries.
In Nederland, I have reviewed nearly all the zebra crossings, and added crossing:markings=zebra to all crossing=zebra nodes and ways and crossing_ref=zebra nodes and ways. As far as I am concerned, crossing=zebra and crossing_ref=zebra could be (and should be) safey removed without losing any information, but many mappers are very attached to their historic styles of crossing mapping (and the different presets of various tools), so I am not touching that wasps nest!
I did do a cleanup of crossing=informal (1 remaining in Nederland!) and crossing=no. Many of those were mistagged because of unclear wordings in the options of a StreetComplete question (now improved . The mappers did not even know what they had mapped.
Comment from JPinAR on 5 March 2025 at 20:07
I want to first recognize that I’m presently working on a similar line of thought at you with the Draft-US-Cycling Wiki page. This is becoming the culmination of multiple 7 years of mapping Bike-Ped in the fastest growing Cycling regions in the US possibly the world which spans multiple cycling types. I’m learning a lot as well from the Pedestrian working group of OSM US as well. Please feel free to review what I have linked above and provide feedback. I’d really love review even if this is a developing draft.
“A simple unmarked, uncontrolled crossing is just an intersection node without any tags.” - I would always mark a crossing as marked or unmarked as a minimum but I typically draw the line on node vs. way marking as nodes are curb cuts for business and I’ll to the way for intersections if time is a factor.
I’ll echo what Sienna stated though although iD editor cause ‘crossing=zebra’ to shot up in prevalence there has since been discussion of separating if there is marking from the type of marking thus crossing=* + crossing:markings=zebra is now preferable even if crossing=zebra by prevalence with likely remain acceptable for a good time still.
Also realize that if a crossing has a ‘crossing=traffic_signals’ then without a distinct ‘crossing:markings=’ it’s all but impossible to mark the signals and the marking as distinct items of the same way. At least without going super duper deep on mapping each and every pedestrian light as a node with directionality. I’d much rather have marked and crossing:markings as distinct because from a stress evaluations stand point how a crossing is marked is far less relevant than how it is marked.
Traffic Island is one item I have stronger opinions on as I really, really dislike the use of crossing:island=yes and believe traffic island need to always where possible be marked as either footway=traffic_island or cycleway=traffic_island. (I typically switch to cycleway for paths wider than 3m as these are wide enough for bikes to pass comfortably.)
Why the insistence on ways? I like to view bike-ped in a lens of stress and ways are far better at measuring this by looking at way lengths. For instance a crossing of a 6+ lane road with a traffic island in between is still crossing 3+ lane roads twice. The inverse is also true if a traffic island is below a certain length it can be very high stress if you only have a meter or less between two high speed roads crossing:island=yes can very deceptively make a path look low stress when it is in reality very, very high stress. So mapping these as ways when possible give so much deeper detail on good vs. bad routes and for those from the US this is much bigger factor.
I’ll also bring back up the bicycle=yes/designated question because while I understand the difference between countries in ‘expectation’ cycling apps that are global rarely have the appreciation for country by country nuance as I’d still say that consistency on bicycle=yes/designated is important. Which bicycle=designated indicated infrastructure designed with cycling in mind vs. bicycle=yes which is were cycling wasn’t designed but is permitted. Think ‘bike lane’ or ‘multi-use path’ = designated and ‘road lane’ or wider than usual sidewalk with no businesses = yes. I get in your context this nuance isn’t as significant a distinction but routers like Komoot, Strava, Mapy.cz, and other do treat these very differently so consistency is still helpful.
Comment from Peter Elderson on 5 March 2025 at 23:26
Thanks @JPinAR for your views and comments! My focus currently is to clean up the mess that persisting historic mapping and tagging schemes and tools have left us with. E.g. many mappers still think that zebra crossings are to be tagged with crossing=marked + crossing:markings=yes, expecting others to interpret this tag combination as a zebra. So we (the Dutch) are nowhere near agreement on the optimal way to tag crossings. Maybe in the future all will agree that ways are the way to go, but currently mapping crossings as nodes is overwhelmingly more popular, and way-fans are simply outnumbered. The best I can try to achieve now is consistency within an acceptable bandwidth, so that a later move to mapping crossings as ways would be easier to accomplish (read: automated or semi-automated).
That’s one of the reasons I like the concept of mapping both the crossing way and the crossing node, tagging details either on the way or on the node, but not both. This way mappers can use their personal preferences, without creating another mess. In the end, to switch to tagging crossings as ways, you’ll just combine the tags on the preferred object, whatever that is.
About directionality: a crossing in OSM is seen as a path, footway or cycleway crossing over a higher order way. So details on the crossing node such as crossing markings, signal control, tactile paving, designation/access, kerbs, and for cycleway crossings, oneway, always apply to the crossing way (lower order), not to the crossed way (higher order). The cyclist has to ride the crossing way (as allowed) and pass the node that’s part of it, so I think all the information is there. The exact geometric position of kerbs, islands, etc is not available, and if an application needs that, it has a big problem… solvable, of course, theoretically, but that requires a lot of change management. Which I don’t see happening in Nederland for the next few wee/^H^H^Hyears.
About bicycle=yes and bicycle=designated. My preference, in this stage, is to simply go with the access and designation of the crossing way, and add only the rare exceptions on the crossing node. If bicycles are not the intended crossers but allowed e.g. on the pedestrian crossing, then the crossing footway is tagged bicycle=yes. The access/designation of the crossing is to be taken (by data users) from, or defaults to, the crossing way. (I know there are edge cases where it is not so simple, but solutions can be found, I am sure).
I will read the draft cycling page tomorrow, thanx for the link. I think I need a clear head for that!
Comment from JPinAR on 7 March 2025 at 05:09
I was working through my Draft for US cycling and I will not a possible source for something that I think we do align on.
https://wiki.openstreetmap.org/wiki/Crossings
This has multiple instances of ‘crossing:markings=yes’ listed multiple times and I think I’m in alignment that if people are going to bother marking that an intersection has markings that ‘crossing:markings’ should be used to specify the type of marking and yes should rarely be used. (Like some odd undocumented or unrecognized marking.)