Is there a simple way to get all-time top mappers by country?

Hello

As I’ve said in the title, i wonder if there’s a simple way to find the mappers that contributed the most changes/changesets ever on a per-country basis (that means the data should be restricted to the country’s bbox or something even more precise)

The options I’ve tried are:

  • The country pages in OSMstats (this gives the right information I need but it’s limited to the last 2 months; brute-forcing the HDYC pages of the users would get me part of the way there but unfortunately some mappers would be missed and that’s a bit of a time-consuming/complex process)
  • Manually querying the changeset dump to get that data (unfortunately the dump is a bit slow to download and even slower to process, and I’ve even ran into an XML parsing error so I don’t think I’ll try to do that again)

Thanks

$ osmium cat monaco-internal.osh.pbf -f opl | cut -d' ' -f7 | sort |  uniq -ci | sort -rn | head -20
  21172 urene78
   6345 uRatZillaS
   5772 uVlad
   5260 uika-chan!
   4272 uMarcussacapuces91
   3888 uVerdy_p
   3654 usergio7826
   3647 uLuc%20%Monaco
   2884 uYod4z
   2792 ubuchanan
   2695 uVMukhtarov
   2535 uefes
   2387 uMathbau
   2224 uScrup
   2005 urusefkuma
   1978 ugilbert%20%Aeschelmann
   1927 ucmi3j89d9o
   1852 ummahmud
   1811 uLyon-St-Clair
   1782 uPatchi

Quick and dirty

This example extracts the top contributors from an OpenStreetMap history file, ranked by total number of object versions (n/w/r) they created or modified. ( not changeset based )

You can download the history file from the Geofabrik internal server with your osm id.

Monaco example:

Step Command Description
1 osmium cat ... -f opl Converts the OSM history file to OPL (text) format
2 cut -d' ' -f7 Extracts the 7th field (user field) from each line
3 sort Sorts lines alphabetically (required for uniq)
4 uniq -ci Counts occurrences, case-insensitive
5 sort -rn Sorts by count, highest first
6 head -20 Shows top 20 results

Output Format

  21172 urene78
   6345 uRatZillaS
   5772 uVlad
  • The number represents total object versions (nodes, ways, relations) attributed to that user.
  • The u prefix is part of the OPL format, indicating the user field.
  • URL-encoded characters may appear (e.g. %20 for space).

Important Notes

  • The .osh.pbf extension indicates a history file containing all versions of each object.
  • The count includes every version, not unique objects. If a user edited the same road 50 times, it counts as 50.

PS: Some users may change their username over time, which can split their contributions across multiple names in the output. For more accurate results, consider aggregating by the User ID field (field “i” in OPL format) instead of the username.

this is the user id version ( -f6 )

$ osmium cat monaco-internal.osh.pbf -f opl | cut -d’ ’ -f6 | sort | uniq -ci | sort -rn | head -5
21172 i257555
6345 i24207
5772 i24247
5260 i4763179
4272 i37548

7 Likes

This works well enough that I could query HDYC for other data (like more precise changes count or changeset count) so I’m currently marking this as a solution (until a solution for changesets or lower RAM usage gets posted)

1 Like

Other OPL examples:

Top 3 Users by Distinct Changeset Count

# ------------------------------------------------------------
# Top 3 Users by Distinct Changeset Count
# ------------------------------------------------------------
# This shows users ranked by the number of separate editing sessions, not total object edits.
# Explanation:
# - cut -d’ ’ -f4,7 - extracts changeset ID and username
# - sort -u - keeps only unique changeset-user pairs
# - cut -d’ ’ -f2 - keeps only username
# - The rest counts and ranks

osmium cat monaco-internal.osh.pbf -f opl | cut -d’ ’ -f4,7 | sort -u | cut -d’ ’ -f2 | sort | uniq -c | sort -rn | head -3

Output

$ osmium cat monaco-internal.osh.pbf -f opl | cut -d' ' -f4,7 | sort -u | cut -d' ' -f2 | sort | uniq -c | sort -rn | head -3
    541 uOleg%20%Kholin
    529 urene78
    410 uPa413

Top 3 Most Active Years in the Region

# ------------------------------------------------------------
# Top 3 Most Active Years in the Region
# ------------------------------------------------------------
# Shows which years had the most editing activity.
# Explanation:
# - cut -d' ' -f5 - extracts timestamp field
# - cut -c2-5 - extracts year (characters 2-5, skipping the "t" prefix)
# - Useful to identify peak mapping periods
osmium cat monaco-internal.osh.pbf -f opl | cut -d' ' -f5 | cut -c2-5 | sort | uniq -c | sort -rn | head -3

Output

$ osmium cat monaco-internal.osh.pbf -f opl | cut -d' ' -f5 | cut -c2-5 | sort | uniq -c | sort -rn | head -3
  13620 2011
  12934 2023
  12745 2012

DuckDB ( SQL ) + .csv.gz version

# ============================================================
# Convert OSM OPL to gzipped CSV, then query with DuckDB
# ============================================================
#
# Performance note:
# The "osmium cat" command is the memory-intensive part of this pipeline.
# Processing large .osh.pbf files (e.g. country or planet-level history)
# may require significant RAM on the server.
#
# Recommended workflow for large files:
# 1. Generate the .csv.gz file once on a server with sufficient memory
# 2. Download the compressed CSV to your local machine
# 3. Run DuckDB queries locally (DuckDB handles gzipped CSV efficiently)
#
# This approach separates the heavy lifting (osmium) from the analysis (DuckDB).
# ============================================================

# Single pipeline: OSM -> OPL -> CSV -> gzip (run on server)
(echo "obj_type,obj_id,version,deleted,changeset,timestamp,user_id,username"; \
 osmium cat monaco-internal.osh.pbf -f opl | awk '{
    print substr($1,1,1) "," substr($1,2) "," substr($2,2) "," substr($3,2) "," substr($4,2) "," substr($5,2) "," substr($6,2) "," substr($7,2)
}') | gzip > monaco.csv.gz

# DuckDB reads gzipped CSV directly (run on client)
duckdb <<'SQL'
  -- Top 3 Users by Distinct Changeset Count
  SELECT
      username,
      COUNT(DISTINCT changeset) AS changeset_count
  FROM read_csv_auto('monaco.csv.gz')
  GROUP BY username
  ORDER BY changeset_count DESC
  LIMIT 3;
SQL

Log

$ duckdb <<'SQL'
>   -- Top 3 Users by Distinct Changeset Count
>   SELECT
>       username,
>       COUNT(DISTINCT changeset) AS changeset_count
>   FROM read_csv_auto('monaco.csv.gz')
>   GROUP BY username
>   ORDER BY changeset_count DESC
>   LIMIT 3;
> SQL
┌────────────────┬─────────────────┐
│    username    │ changeset_count │
│    varchar     │      int64      │
├────────────────┼─────────────────┤
│ Oleg%20%Kholin │             541 │
│ rene78         │             529 │
│ Pa413          │             410 │
└────────────────┴─────────────────┘

Top 100 Germany:

9199866 uGeofreund1
8584229 uM_Kucha
8464321 uTeddy73
8351771 uq_un_go
6857151 uuser_212553
5937800 uRopino
5652142 uParadine
5598065 uatpl_pilot
5288504 ucatweazle67
4670781 uBeKri
4605795 uwaldhans
4600022 uWoGraSo
4062480 uda-sch
4056882 uflohoff
4036164 uopendcc
4016782 ujoe2812
3872730 uSafetyIng
3709212 uvichada
3658989 uMichaOSM
3655001 ugepeix
3595088 uOF-1
3148726 ugeodreieck4711
3110130 uhca
3045079 uuser_593899
2956050 udidimosi
2953425 udx125
2902388 utheophrastos
2791060 uuser_70413
2763701 ujacobbraeutigam
2751080 uwermak
2697234 ugsperb
2689225 ujengelh
2681904 uKartoGrapHiti
2675885 uroschitom
2643710 uPT-53
2489214 uwies1
2447378 uchris66
2388532 uShape_Import_Viersen
2388172 uWayneSchlegel
2247613 uHeideammer
2241183 uParamida
2195789 uma-rt-in
2136616 uchangchun_1
2130762 ukjon
2129782 uuser_12500175
2099935 uBurnyB
2098313 umatchman
2096992 uDer%20%Troisdorfer
2032527 uPaulchen%20%Panther
2014152 uwegavision
1984042 uokilimu
1983656 uZartbitter
1955019 uGalbinus
1946382 useichter
1936617 uHCX%20%Biker
1902646 uRatz41
1896218 ube-ju
1895821 uFahRadler
1893016 ugooglenaut
1879800 ushogun
1816651 ubiketeur
1807407 uMichaH
1804757 uherisusa
1778668 ukartler175
1741060 upyram
1736533 uFischkopp0815
1699467 uToniE
1676925 umapper999
1661040 uhotelsierra
1649442 uAntikalk
1617263 uMarkus%20%Olderdissen
1611748 uhessenland
1606853 uLübeck
1597288 uLodda
1586412 uGerit%20%Wagner
1584617 u715371
1580063 uWegefanHB
1575825 uHPHenschel
1565175 uChenshi
1557506 uelle67
1556026 ugeozeisig
1552811 uTorkel
1537758 uMap-Peter
1536114 u!i!
1533774 uSuricata
1526809 uScout%20%Jens
1504536 uArnaldur
1503176 ujabali
1454998 uvogelfreier
1441329 uGino-52
1394923 ustreckenkundler
1394528 uOMME-OSM
1388746 uletihu
1387075 uBasstoelpel
1374321 uWiebkeCHH
1363982 uStefanHRT
1325626 ualan1209
1322231 ublack_bike
1294498 ubastibay
1292073 uklausis