I just published a hacky but effective tool to fix wrong tag values. This lead to some 50 edits only this morning.
More info: https://www.grulic.org.ar/~mdione/glob/posts/correcting-openstreetmap-wrong-tag-values/
I just published a hacky but effective tool to fix wrong tag values. This lead to some 50 edits only this morning.
More info: https://www.grulic.org.ar/~mdione/glob/posts/correcting-openstreetmap-wrong-tag-values/
Log in to leave a comment
Discussion
Comment from chris_debian on 5 April 2026 at 09:07
Nice script, Marcos! Would you be able to share an example of a ‘before’ and ‘after’ tag?
Thanks,
Chris
Comment from Marcos Dione on 5 April 2026 at 13:53
The edits are by hand, there is no automation there, just finding “bad” values.
Comment from chris_debian on 5 April 2026 at 14:23
Thanks for the clarification Marcos, makes sense to keep the edits manual for accuracy.
I had a go at tidying up the script a little, in case it’s useful. The main changes:
os.system()forsubprocess.run()— a bit safer and more Pythonicinput()pause between objects so they open one at a time rather than all at onceHAVING count(*) < Nfilter to focus on the long tail and skip common valid valuesKNOWN_GOODset to skip values you already know are fineRevised script below. Sorry about the formatting, the diary interprets hash/ pound as bold font, they should be comments in the script. Happy to be ignored if you prefer your original — it clearly does the job! :)
Chris
Revised script
```python #! /usr/bin/env python3 “”” fix_osm_tags.py - Find and manually correct wrong highway tag values in OSM.
Requires a local osm2pgsql rendering database (e.g. ‘europe’). Workflow: 1. Queries planet_osm_line for highway values, rarest first (long tail first). 2. For each rare value, opens the OSM editor in your browser one object at a time. 3. You review, correct or leave a note, then press Enter to continue. “””
import subprocess import sys
import psycopg2
— Configuration —
DB_NAME = “europe” BROWSER = “librewolf” BROWSER_PROFILE = “default”
Highway values that are known-good and should be skipped.
# Expand this list to avoid being prompted for valid rare values. KNOWN_GOOD = { “residential”, “track”, “path”, “footway”, “cycleway”, “service”, “unclassified”, “tertiary”, “secondary”, “primary”, “trunk”, “motorway”, “living_street”, “pedestrian”, “steps”, “motorway_link”, “trunk_link”, “primary_link”, “secondary_link”, “tertiary_link”, }
Only show groups with fewer than this many occurrences.
# Keeps the focus on the long tail of rare/likely-wrong values. MAX_COUNT = 50
def open_in_editor(osm_id: int) -> None: “"”Open the OSM web editor for a given osm2pgsql osm_id.
def main() -> None: with psycopg2.connect(dbname=DB_NAME) as db: cursor = db.cursor()
if name == “main”: sys.exit(main()) ```
Comment from Marcos Dione on 7 April 2026 at 08:28
I did more modifications on my side, I collapsed both queries into a single one, and now there’s no wait between objects :) Also, any key for any table. Will try to merge these tonight.
``` #! /usr/bin/env python3
import os import sys
import psycopg2
def main(): db = psycopg2.connect(dbname=’europe’) cursor = db.cursor()
if name == ‘main’: main() ```
Comment from chris_debian on 7 April 2026 at 16:24
Nice work.