Built for addresses as people actually type them.
Typos, shortened street types, missing commas, the town written first: on input like this GridPin finds the right house more often than Nominatim and Photon.
Download free Run your first query How we measure
Fits: local, privacy-sensitive or high-volume address workloads in France, Germany (15 of 16 Länder; Bavaria not covered), Italy, the Netherlands, Serbia, Spain and Brazil — forward, reverse and batch, address-first. Does not fit today: worldwide coverage, a hosted endpoint, or POI-first search outside France.
Found within 150 m of the true address
Share of all rows where the first answer lands within 150 m of an independent reference coordinate. Empty answers count as misses. Same queries, same truth, one run per engine.
| Query set | Rows | GridPin | Photon | Nominatim |
|---|---|---|---|---|
| Germany · distorted addresses | 2,000 | 82.1% | 46.9% | 15.8% |
| Germany · clean addresses | 2,000 | 82.8% | 83.2% | 81.2% |
| Spain · distorted addresses | 1,590 | 33.8% | 29.6% | 20.8% |
| Brazil · distorted addresses | 2,376 | 20.7% | 19.8% | 9.6% |
| Brazil · health-facility register (as typed) | 1,000 | 36.2% | 28.2% | 20.7% |
Distorted means each real address was changed by one fixed mechanical rule — a typo, a shortened street type, commas removed, the town moved to the front — with the reference coordinate kept byte for byte. On German and Spanish distorted addresses GridPin leads both services; on Brazilian distorted addresses GridPin and Photon are level and both are well ahead of Nominatim; on clean German addresses GridPin and Photon are level. We show the sets where GridPin leads or is level. On the other Spanish sets Photon leads, on clean Brazilian addresses Photon leads too (25.5% vs 23.2%). Full counts for every country, including sets where we trail, are below; this page makes no claim beyond the sets listed.
Coverage today includes France, Germany (15 of 16 Länder), Italy, the Netherlands, Serbia, Spain and Brazil — not worldwide.
Details by country
For each country: what was measured, full counts per engine, significance and identity.
Germany · 2026-09-10 · 2 sets
What we tested. We took 2,000 real German addresses with known coordinates from two official registers — 1,000 public libraries and 1,000 electric-car charging stations — in 15 of 16 states (Bavaria is not covered). The rows were frozen before the run and never used while tuning the engine. Each address was tested twice: as written (clean) and with one mechanical distortion (dirty).
What it shows. Clean addresses: GridPin and Photon are level — the gap is within chance; GridPin is slightly ahead of Nominatim. Distorted addresses: GridPin finds 82% within 150 m, Photon 47%, Nominatim 16% — far beyond chance.
| Track | Engine | N | Found | Empty | ≤50 m | ≤150 m | ≤1,000 m | ≤5,000 m |
|---|---|---|---|---|---|---|---|---|
| clean | gridpin | 2000 | 1958 | 42 | 1280 | 1656 | 1851 | 1891 |
| clean | nominatim | 2000 | 1913 | 87 | 1241 | 1623 | 1853 | 1904 |
| clean | photon | 2000 | 1975 | 25 | 1250 | 1663 | 1907 | 1965 |
| dirty | gridpin | 2000 | 1953 | 47 | 1267 | 1642 | 1836 | 1876 |
| dirty | nominatim | 2000 | 376 | 1624 | 256 | 317 | 366 | 374 |
| dirty | photon | 2000 | 1266 | 734 | 710 | 937 | 1074 | 1105 |
Technical detail for reproducing: significance test, data fingerprints
Germany, 2026-09-10 — 1,000 ISIL libraries and 1,000 BNetzA charging stations, 15 of 16 Länder (Bavaria not covered); rows sealed on 2026-09-09, outside the development regression set; source-family independence is not claimed.
Exact paired two-sided McNemar, ≤150 m (GridPin-only / comparator-only rows): clean vs Photon
p=0.6691367 (95 / 102) — not proof of parity; clean vs Nominatim p=0.0266263 (121 / 88);
dirty vs Photon p=1.65976e-155 (767 / 62), vs Nominatim p=7.50908e-366 (1,346 / 21).
Clean corpus SHA-256 9dd8e146b1c2fb90b028b0632b8a02d76c9273d821763ca01fff822fbc9a4f4b;
dirty 0b1719b75f59553dbb8ff897e784fe93d0fdb8b172bc5c0dd4576781f22c0674.
Spain · 2026-09-21 · 1 set
What we tested. 1,590 Spanish places from Wikidata with known coordinates; every address was changed by one mechanical distortion. One row lying outside Spain was dropped for all three engines.
What it shows. GridPin finds 33.8% within 150 m, Photon 29.6%, Nominatim 20.8%. GridPin’s lead over both is beyond chance, though smaller than in Germany. On Spain’s other test sets Photon leads.
| Set | Engine | N | Found | Empty | ≤50 m | ≤150 m | ≤1,000 m | ≤5,000 m |
|---|---|---|---|---|---|---|---|---|
| distorted | gridpin | 1590 | 1056 | 534 | 385 | 538 | 733 | 953 |
| distorted | nominatim | 1590 | 511 | 1079 | 226 | 331 | 443 | 465 |
| distorted | photon | 1590 | 875 | 715 | 347 | 470 | 626 | 692 |
Technical detail for reproducing: significance test, data fingerprints
Spain, 2026-09-21 — 1,590 Spanish Wikidata items with a coordinate, each query
mechanically distorted; parent queries include locality descriptions, so this is not observed
human noise. One parent row outside the Spanish country contour (Overture 2026-08-19.0, land and maritime union) is excluded from all three engines; saved inputs and answers are unchanged. Release sheet spain.bin (v0.3.0)
c671b9a46089e32580189ee3c5a65e024779691a50ab26e77f5639023994819b, GridPin binary
9df585faa43b6766e29e14ea77b7153b3d7ae57d39665a5498b7eb8052e32f99; public Nominatim and a
local Photon (Spain extract).
Exact paired two-sided McNemar, ≤150 m: distorted vs Photon p=0.00344627 (297 / 229), vs Nominatim p=5.90642e-22 (340 / 133).
Brazil · 2026-10-06 · 3 sets
What we tested. Three sets with known coordinates: 2,376 places from Wikidata as written, the same 2,376 with one mechanical distortion each, and 1,000 health facilities from the national CNES register, spelled exactly as the register has them.
What it shows. Distorted addresses: GridPin and Photon are level (20.7% vs 19.8%, within chance), both well ahead of Nominatim (9.6%). Health-facility register: GridPin leads both (36.2% vs 28.2% and 20.7%), beyond chance. Clean addresses: Photon leads (25.5% vs 23.2%).
| Set | Engine | N | Found | Empty | ≤50 m | ≤150 m | ≤1,000 m | ≤5,000 m |
|---|---|---|---|---|---|---|---|---|
| clean | gridpin | 2376 | 1566 | 810 | 272 | 552 | 968 | 1249 |
| clean | nominatim | 2376 | 1009 | 1367 | 172 | 412 | 783 | 884 |
| clean | photon | 2376 | 1494 | 882 | 311 | 607 | 1114 | 1271 |
| distorted | gridpin | 2376 | 1399 | 977 | 231 | 492 | 847 | 1097 |
| distorted | nominatim | 2376 | 514 | 1862 | 100 | 229 | 413 | 461 |
| distorted | photon | 2376 | 1206 | 1170 | 241 | 471 | 879 | 996 |
| cnes | gridpin | 1000 | 751 | 249 | 267 | 362 | 596 | 699 |
| cnes | nominatim | 1000 | 512 | 488 | 122 | 207 | 449 | 504 |
| cnes | photon | 1000 | 802 | 198 | 160 | 282 | 643 | 756 |
Technical detail for reproducing: significance test, data fingerprints
Brazil, 2026-10-06 — three retained sets: clean Wikidata and mechanically distorted Wikidata (2,376 rows each) and CNES health-facility register as typed (1,000). Two clean rows outside the country contour are excluded equally for all three engines. Public Nominatim and public Photon answers were collected 2026-09-30 and retained; no new competitor requests were made. Top-1 great-circle distance to independent truth, computed with wikidata4_regress.py; empty answers remain in every denominator. These sets are not observed human search traffic.
Exact paired two-sided McNemar, ≤150 m: distorted vs Nominatim: p=1.72106e-34 (373 / 110); distorted vs Photon: p=0.385453 (276 / 255); cnes vs Nominatim: p=6.2216e-18 (243 / 88); cnes vs Photon: p=8.49867e-06 (199 / 119). These differences describe these sets only, not general superiority; the distorted Photon comparison is not proof of parity.
Measured engine SHA-256: 84bd75bc3264e71df57d3a76c9d69575ccaa24bcc4cd56975eb353830740cf4f; sheet br.bin SHA-256: 2d415c3a2abfd2df749b6a1d58625c12f8df1328a56248c9bc5eb5628cbc3ac7; release sheet brazil.bin (v0.4.0; metadata-only repack of the measured sheet, 2026-10-10) SHA-256: 016e102debb05aafad0ae409c3a2acec478b60bb48b74d03210b80dc52d42a6d. Corpora and raw receipts are retained evidence, not bundled in the public checkout.
France, Italy, the Netherlands, Serbia — covered by the free sheets; no independent comparison with Photon and Nominatim is published for them on this page yet.
Full counts, method and data fingerprints; corpora and raw receipts are retained evidence, not bundled in the public source checkout.
Drop-in compatible
GridPin answers in the Photon API format, forward and reverse (the reverse endpoint is implemented
since 2026-08-06). On the external geocoder-tester suite — a compatibility fixture set, not an
accuracy oracle — the full official Alsace numbered-address file passes 230 / 285
(2026-08-07; 0 → 173 → 208 → 230 as the adapter matured), tested binary SHA-256
47a6ecf2cee6835dec7c7dd2fb331ebb5c8708f084e3b02f6bb5239b6e2103b8.
How we measure
- Independent truth. The reference coordinate never comes from the data GridPin ships; a set whose truth copies any engine's source is thrown out before comparing.
- Same input for everyone. Each engine gets the identical query and returns one answer. Nominatim is the public service, queried at most once per second; Photon is either the public service or a local instance of the country's OpenStreetMap extract — each country block says which.
- No small samples as results. Every set shown has at least 1,000 rows; empty answers stay in the denominator.
- Mechanical distortions, not guesses. Distortion rules are fixed before any engine answers and applied by a published hash, so no rule is tuned to a result.
Throughput, measured and stated with its conditions
How fast, honestly
Single arm64 laptop core, one thread, France sheet, warm mmap. Speed depends entirely on query shape: an exact match is an FST lookup, while a typo is answered by exploring edit-distance variants — hundreds of times more work.
| Query shape | Per core | Median latency |
|---|---|---|
| Exact, short (“10 rue de rivoli paris”) | ~3,000/s | <1 ms |
| Full clean address | ~600/s | <1 ms |
| Reverse (coordinate → address) | ~1,800/s | <1 ms |
| Typo / messy (fuzzy path) | ~10–50/s | ~60 ms |
Fuzzy matching is the slow path, and it is our headline feature — so we say so.
Feed messy input through geocode_many() or the batch command,
which spread work across every core. Making the fuzzy path itself faster is on the roadmap;
until it lands we would rather you size for tens of fuzzy queries per second per core than
be surprised in production.
Reproduce it yourself
The public contract runs without private sets or network services:
$ git clone https://github.com/gridpin/gridpin $ cd gridpin $ make public-bench-contract $ make smoke
The full record — every set above with its counts, paired tests, competitor versions and data fingerprints — is in docs-public/BENCHMARK.md.