Offline geocoder — a country in a file.
No server, no database import, no per-request fees.
GridPin packs a country into a memory-mapped file. Forward and reverse geocoding, millisecond exact lookups on a single laptop core — no server, and the engine and every query stay offline.
Fits: local, privacy-sensitive or high-volume address workloads in France, Italy, the Netherlands and Serbia. Does not fit today: worldwide coverage, a hosted endpoint, or POI-first search outside France.
Rust engine · CLI · Python wheel · DuckDB extension · batch mode
$ gridpin query france.bin "8 Boulevard du Port, Amiens" -k 1 {"lat":49.897442,"lon":2.290084,"precision":"house","confidence":0.94, "street":"Boulevard du Port","housenumber":"8","commune":"Amiens","postcode":"80000", …} $ gridpin reverse france.bin 49.894600 2.294900 # millisecond, fully offline {"lat":49.894538,"lon":2.294934,"precision":"house","confidence":0.95, "street":"Passage du Bailliage","housenumber":"19","commune":"Amiens","distance_m":7.3, …}
Zero calls home
The engine sends no telemetry and no license pings — not a byte of what you geocode leaves your machine. The only network use is you downloading a sheet.
Opens instantly
Memory-mapped country files. No database, no data import, no warm-up.
Forward & reverse
Address to coordinates and coordinates to address, single or batch.
Speaks your stack
CLI, Python wheel via pip, and a DuckDB extension for SQL.
Your geocoding bill is rent.
Make it a purchase.
Hosted geocoders charge per request, forever — and the biggest one won't even let you keep what you paid for.
| Approach | Cost at 1M req / month | Keep your results? | Runs on |
|---|---|---|---|
| Google Maps Geocoding | ~$3,550 / mo | Storing forbidden; coordinates for 30 days max | Google's cloud |
| Mapbox Permanent | ~$4,500 / mo | Yes — at 7.5× the temporary price | Mapbox's cloud |
| Geoapify on-prem | €700 / mo + setup | Yes | Your server |
| Nominatim self-host | Your ops time | Yes | A beefy server, days of import |
| GridPin | $0 static Freeplanned fresh-data plans from $59/mo; no per-query fee | Yes — forever. It's your file. | Any laptop |
The optional France POI layer is available in every tier alongside the France sheet (static build on Free; on subscriptions it refreshes on its own cadence and may briefly lag the address release — the address atlas is the delivery contract, POI is best-effort).
Cost comparison: List prices as of 2026-08, 1M requests/month; hosted-API figures are provider list prices before storage add-ons — see each provider's current terms.
The grid is ours. The pin is yours. We ship fresh data sheets; every result you compute belongs to you — store it, join it, sell your product on top of it, forever.
Three steps. No server anywhere.
A sheet is one data file per country — a few regional datasets add a small companion file, and the optional POI layer is its own file. The full set is the atlas. Fresh sheets ship monthly on subscription; free builds are static, with no update schedule.
Download a sheet
France is a single 365 MB sheet with 26.1M addresses — most countries are one file (a few regional datasets add a small companion). Put it anywhere on disk.
Point the engine
CLI, Python, or DuckDB — the Rust engine memory-maps the sheet and is ready instantly. No import, no schema.
Geocode offline
Forward, reverse, and batch — exact lookups in well under a millisecond per core. On a plane, in an air-gapped VPC, on a laptop.
# forward: top hit as JSON $ gridpin query france.bin \ "19 Rue Béranger, Paris" -k 1 {"lat":48.866402,"lon":2.363412, "precision":"house", …} # reverse $ gridpin reverse france.bin \ 48.8664 2.3634 # batch: JSONL in, JSONL out $ gridpin batch france.bin \ in.jsonl out.jsonl -k 1
import gridpin g = gridpin.Geocoder("france.bin") # mmap, instant hits = g.geocode("8 Bd du Port, Amiens", 1) print(hits[0]["lat"], hits[0]["lon"]) near = g.reverse(49.8945, 2.2949, 1) # exact lookups: ~3,000/s per core; # geocode_many() batches across cores
-- install: see docs → Install LOAD gridpin_ext; SELECT gridpin_load('france.bin'); -- forward, straight from SQL SELECT gridpin_geocode(address) FROM customers; -- reverse SELECT gridpin_reverse(lat, lon) FROM gps_pings;
Four countries, ready to download. More coming.
Builds v7, August 2026. New sheets are added country by country — tell us which one you need next.
| Country | Sheet size | Addresses | Source | Data license | POI layer |
|---|---|---|---|---|---|
| France | 365 MB | 26.1M | BAN national registry | Licence Ouverte | ✓ optional, 231 MB |
| Italy | 247 MB | 25.9M | Overture / ANNCSU | CC BY 4.0 | — |
| Netherlands | 103 MB | 9.9M | Overture / Nationaal Georegister (BAG) | Public Domain Mark 1.0 | — |
| Serbia | 32 MB | 2.6M | Overture / RGZ | data.gov.rs Terms of use | — |
A sheet is smaller than its own raw source. France's national registry download is an 885 MB gzip that unpacks to 4.9 GB of CSV — the finished sheet is 365 MB, and that already includes every index: typo automata, spatial cells, ranking. You download less than the raw data and get a ready-to-query engine file instead of a CSV to import.
Optional POI layer for France: 231 MB of places from Overture (mixed permissive: CDLA-Permissive-2.0 / Apache-2.0 / CC0-1.0) — geocode "pharmacie gare de Lyon", not just street addresses.
Prebuilt binaries cover Linux x86_64 (x86_64-unknown-linux-gnu),
macOS Apple Silicon (aarch64-apple-darwin) and Windows x86_64
(x86_64-pc-windows-msvc); any other target (Intel macOS, Linux arm64/musl,
Windows arm) builds from source with stable Rust.
Which country should we build next?
Nothing to sign up for and nothing to fill in but the country itself. We keep one number per country — no cookie, no identifier, nothing stored on your device, nothing that says it was you. What we hold.
Two kinds of evidence, not one shiny number.
Every geocoder benchmark hides a choice: what counts as the truth, and how messy the queries are. We publish both tiers.
Tier 1 — official-registry test sets
99.3–99.7% recall@1
Clean and typo-corrupted queries where the truth is the national registry itself (France: BAN). Median coordinate error: 0.00 m. On the same BAN reference set, Photon scores 44.9% recall@1 — and to be fair, most of that gap is data, not code: OSM coverage versus the official registry. That's exactly why we build from registries where they exist.
Tier 2 — head-to-head on disclosed truth
78.5% on Overture Places truth
One run, three services, 1,200 provenance-bearing rows. On the 1,000 rows taken from OSM we are last — Photon 97.3%, Nominatim 94.2%, GridPin 86.9%. On the 200 Overture Places rows — whose relationship to all three engines is unknown — the descriptive order inverts: GridPin 78.5%, Nominatim 66.5%, Photon 59.5%. Both competitors search OSM-derived data, so the mixed total (GridPin 85.5%) is descriptive, not a winner ranking.
CI: cargo test on three operating systems, plus a public smoke test
that builds Monaco from a raw OSM extract and runs live queries on every commit.
The full quality lab (internal stress sets, live corpora, coordinate-truth oracles) is private.
Flat price. Unlimited requests.
You're paying for fresh sheets, not for lookups. Run a billion queries — the price doesn't move.
Free
$0
For side projects and evaluation
- France, Italy, the Netherlands, Serbia
- Static builds, no update schedule — monthly rebuilds are subscriber-only
- Forward + reverse + batch
- Engine is Apache-2.0, forever
Starter
$59 / mo
For one country in production — in preparation
- One country of your choice
- Fresh sheets monthly
- Forward + reverse + batch
- Email support
Pro
$149 / mo
For teams that geocode everywhere — in preparation
- The whole atlas — all available countries
- Fresh sheets monthly
- Provenance journal per build
- Invoice billing
- Email support (priority)
Every “Notify me” above opens your mail client. If nothing happens — no client is
configured, which is common — write to contact@gridpin.dev instead; the address is
the same one those buttons use.
When paid plans open: annual billing = 10× the monthly price — two months free.
All plans: unlimited requests, results are yours forever.
Questions people actually ask
Can I store the geocoding results?
Yes — forever. That's the point. Everything GridPin computes on your machine is yours: cache it, put it in your database, ship it in your product. Compare: Google's terms forbid storing results and cap coordinates at 30 days; Mapbox charges 7.5× for permanent storage rights.
Free has all available countries too — why pay $199 for a Snapshot?
Freshness. Free builds are static — they can be far behind the registry. A Snapshot is today's monthly build, the exact sheets subscribers receive, plus a proper invoice for procurement. It deliberately costs more than one month of Pro: it's the no-subscription option — one invoice, no card on file, nothing to cancel. If a subscription works for you, a month of Pro is cheaper. And if older data is fine for your use case — honestly, use Free.
How does this work with GDPR?
Your customer addresses never leave your infrastructure: no API call to geocode, no third-party processor, no data transfer to review — the geocoder runs where your data already lives, and the engine sends no telemetry at all. The only network action is you downloading a sheet, and it carries no query data.
How fresh is the data?
Subscribers get fresh sheets monthly (Pro also gets a provenance journal for every build). The free tier gets static builds, with no update schedule. Each sheet states its source and build date.
Is it open source?
The engine (Rust), the DuckDB extension, the data pipeline, and the docs are public under Apache-2.0. The paid part is the data service: fresh, tested, ready-to-use sheets every month — plus country-specific rule tables that ship inside the paid data files.
What hardware do I need?
A laptop. Sheets are memory-mapped, so they open instantly and don't need to fit in RAM. On a single arm64 core, exact lookups run at ~3,000/s and reverse geocoding at ~1,800/s; typo-tolerant fuzzy matching is much slower (tens of ms per query), so batch messy input across cores. See the benchmarks for the per-shape method and numbers.