Guide
Geocode a CSV without an API key
A spreadsheet of addresses in, latitude and longitude out, on your own machine. No sign-up, no quota, no per-row bill.
In Python
import csv
import gridpin
from gridpin_mcp import sheets
g = gridpin.Geocoder(str(sheets.download("rs"))) # pick the country of your addresses
with open("addresses.csv", newline="", encoding="utf-8") as f:
rows = list(csv.DictReader(f)) # needs a column named "address"
hits = g.geocode_many([r["address"] for r in rows], 1) # spreads the list across all cores
with open("geocoded.csv", "w", newline="", encoding="utf-8") as f:
out = csv.DictWriter(f, fieldnames=[*rows[0], "lat", "lon", "precision"])
out.writeheader()
for row, found in zip(rows, hits):
best = found[0] if found else {}
out.writerow({**row, "lat": best.get("lat", ""), "lon": best.get("lon", ""),
"precision": best.get("precision", "")})
An address the file cannot place gets empty lat and lon, not a guess. Filter on precision: house is a door-level match.
In DuckDB
INSTALL gridpin_ext FROM community;
LOAD gridpin_ext;
SELECT gridpin_load('serbia.bin');
CREATE TABLE orders AS SELECT * FROM read_csv('addresses.csv');
COPY (
SELECT id, address,
(hit ->> 'lat')::DOUBLE AS lat,
(hit ->> 'lon')::DOUBLE AS lon,
hit ->> 'precision' AS precision
FROM (SELECT *, gridpin_geocode(address)::JSON AS hit FROM orders)
) TO 'geocoded.csv';
Use the path that gridpin-fetch rs printed. More on the extension: geocode inside DuckDB.