Tony Wang8 min readGeocoding API: How to Geocode Addresses in 2026
Geocode addresses in 2026 three ways — free DIY with Nominatim/OSM, Google Maps' paid API, or a structured Crawlora API — with real pricing and code.
The fastest way to turn an address into coordinates (or a coordinate into an address) in 2026 is to call a geocoding API — you don't need to scrape a map site or write your own address parser. The real decision is which API: the free public Nominatim/OpenStreetMap instance, Google Maps' paid Geocoding API, or a structured API that wraps the same open data behind one key. This guide covers all three, with real 2026 pricing, real rate limits, and runnable code for each.
Why geocode addresses at scale
- Logistics and delivery routing — convert a customer address list into coordinates for route optimization, or reverse-geocode a driver's GPS ping into a readable stop.
- Real estate and store-locator datasets — plot listings or store locations on a map from an address field, or back-fill missing coordinates in an existing dataset.
- User-generated location tagging — reverse-geocode a lat/lon a mobile app captured (check-in, photo EXIF, delivery drop pin) into a city, postcode, or neighborhood for search and filtering.
- Data enrichment — normalize inconsistent address formats across a CRM or lead list into a common structured shape (city, state, country, postcode) for deduplication and segmentation.
- Market and site-selection research — geocode a batch of competitor or candidate addresses to compute proximity, density, or coverage gaps.
Is it legal to geocode addresses?
Yes, generally. Geocoding public street-address data — converting an address to coordinates or back — is a well-established, uncontroversial public-data use; it's the same operation every map app performs when you type in a destination. The nuance is on the data source side, not the geocoding itself: OpenStreetMap data is licensed under the Open Database License (ODbL), which requires attribution and share-alike terms if you redistribute the underlying map data (not just coordinates you compute from it); Google's terms restrict displaying its geocoding results anywhere other than a Google Map. Don't geocode data tied to a person (a home address linked to an identity) without a lawful basis under GDPR/CCPA, and respect each provider's usage policy and rate limits. See is web scraping legal for the broader legal framework. Not legal advice.
Option 1: DIY with Nominatim/OpenStreetMap (free, and the catches)
Nominatim is the open-source geocoder behind OpenStreetMap's own search box, and the OpenStreetMap Foundation runs a free public instance anyone can call — no signup, no API key:
import requests
import time
HEADERS = {"User-Agent": "MyApp/1.0 (contact@example.com)"} # required by the usage policy
def geocode_nominatim(address: str):
resp = requests.get(
"https://nominatim.openstreetmap.org/search",
params={"q": address, "format": "jsonv2", "addressdetails": 1, "limit": 1},
headers=HEADERS,
)
resp.raise_for_status()
results = resp.json()
return results[0] if results else None
addresses = ["350 5th Ave, New York, NY", "1600 Pennsylvania Ave, Washington, DC"]
for addr in addresses:
place = geocode_nominatim(addr)
if place:
print(addr, place["lat"], place["lon"])
time.sleep(1) # the policy's hard 1 request/second cap
It's genuinely free and it works — but the Nominatim Usage Policy is strict, and it's worth reading before you build on it:
- Absolute 1 request/second cap. No bursting, no exceptions, for any single client.
- Bulk one-off jobs are further limited to 4 requests/minute, from a single machine, with no distributed scripts.
- A real
User-AgentorRefereris required, and you must display attribution to OpenStreetMap. - You must cache results on your side — re-querying the same address repeatedly is against policy.
- No SLA, no uptime guarantee. It's a free public service run on donated infrastructure. It occasionally returns transient
429/503errors or timeouts under load — we've hit this ourselves proxying the same instance in Option 3 below, and had to add retry classification on our side rather than assume every request succeeds first try.
For a handful of addresses or a side project, this is the right call — it costs nothing and there's no key to manage. For a production pipeline geocoding thousands of rows a day, the 1 req/sec ceiling alone makes it impractical (10,000 addresses take at least 2.8 hours sequentially), and you're building retry/caching logic yourself against a service with no uptime commitment.
Region-specific free alternatives exist too. If your addresses are all in one country, a national mapping agency's own API is often faster and more accurate than a global index for that country — for example Japan's 国土地理院 (GSI) offers a free, no-signup geocoding endpoint for Japanese addresses with CORS enabled, a common swap-in when a team only needs domestic coverage and wants to avoid Google Maps pricing entirely.
Option 2: Google Maps Geocoding API (official, paid)
Google's Geocoding API is the incumbent, and its pricing changed materially in the last year: the old blanket $200/month credit was retired in March 2025. In its place, each API now gets its own free monthly cap — the Geocoding API's is 10,000 free requests/month, then:
| Monthly volume | Price per 1,000 requests |
|---|---|
| 0 – 10,000 | Free |
| 10,001 – 100,000 | $5.00 |
| 100,001 – 500,000 | $4.00 |
| 500,001 – 1,000,000 | $3.00 |
| 1,000,001 – 5,000,000 | $1.50 |
| 5,000,000+ | $0.38 |
import requests
resp = requests.get(
"https://maps.googleapis.com/maps/api/geocode/json",
params={"address": "350 5th Ave, New York, NY", "key": "YOUR_GOOGLE_API_KEY"},
)
location = resp.json()["results"][0]["geometry"]["location"]
print(location["lat"], location["lng"])
The catches:
- You need a Google Cloud project with billing enabled — a credit card on file — even to use the 10,000/month free tier. New customers get a one-time $300 trial credit, not an ongoing monthly one.
- Google also sells subscription plans now: Starter ($100/month, 50,000 calls, bundles Geocoding with Dynamic Maps), Essentials ($275/month, 100,000 calls across more products), and Pro ($1,200/month, 250,000 calls) — worth comparing against pay-as-you-go if your usage is steady.
- Attribution and display terms apply: Google's terms restrict showing geocoded results on any map other than Google's own, which matters if you're building a public-facing map product, not just an internal pipeline.
- If you're already deep in Esri's GIS ecosystem, ArcGIS's World Geocoding Service is another enterprise-oriented paid option, credit-metered per request — a reasonable mention if your stack is GIS-first, though most web-app teams won't need it.
Option 3: A structured Geocoding API
For a pipeline that needs predictable JSON without standing up a Google Cloud billing account or hand-rolling rate-limit and retry logic against the public Nominatim instance, a geocoding API gives you the same underlying open geocoding data behind one key, with normalized responses across forward search, reverse, and OSM-id lookup. Forward geocode an address:
curl "https://api.crawlora.net/api/v1/geocoding/search?q=350+5th+Ave%2C+New+York%2C+NY&limit=1" \
-H "x-api-key: $CRAWLORA_API_KEY"
The same call in Python, batched over a list:
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/geocoding"
addresses = ["350 5th Ave, New York, NY", "1 Infinite Loop, Cupertino, CA"]
rows = []
for addr in addresses:
data = requests.get(f"{base}/search", headers=h, params={"q": addr, "limit": 1}).json()["data"]
if data["results"]:
top = data["results"][0]
rows.append({"query": addr, "lat": top["lat"], "lon": top["lon"], "display_name": top["display_name"]})
print(rows)
A real response (Empire State Building, trimmed to the top result):
{
"data": {
"query": "350 5th Ave, New York, NY",
"results": [
{
"address": {
"house_number": "350",
"road": "5th Avenue",
"neighbourhood": "Koreatown",
"suburb": "Manhattan",
"city": "New York",
"county": "New York County",
"state": "New York",
"postcode": "10118",
"country": "United States",
"country_code": "us"
},
"display_name": "Empire State Building, 350, 5th Avenue, Koreatown, Manhattan Community Board 5, Manhattan, New York County, New York, 10118, United States",
"lat": "40.7484421",
"lon": "-73.9856589",
"osm_id": 34633854,
"osm_type": "way",
"importance": 0.5803438355141769,
"category": "office",
"addresstype": "office"
}
]
}
}
Reverse geocode a coordinate:
data = requests.get(f"{base}/reverse", headers=h, params={"lat": 40.7484, "lon": -73.9857}).json()["data"]
print(data["display_name"])
Look up a place by its OpenStreetMap id (useful when you already have an osm_id from a prior search result):
data = requests.get(f"{base}/lookup", headers=h, params={"osm_ids": "W34633854"}).json()["data"]
Worth being honest about: this endpoint proxies the same open Nominatim/OSM data as the DIY option, not a proprietary index — it doesn't magically guarantee uptime the public instance can't. What you get instead is one key across search/reverse/lookup with a consistent JSON shape, rate-limit and retry handling on our side (upstream 429/503/timeouts are classified and retried rather than surfaced raw), and no separate Google Cloud billing account to set up. For addresses where Google's proprietary index genuinely resolves better (ambiguous or very new addresses), Option 2 still wins on accuracy.
Which approach should you use?
| DIY (Nominatim direct) | Google Maps Geocoding API | Structured Geocoding API | |
|---|---|---|---|
| Cost | Free | 10,000/mo free, then $5.00/1,000 | Included in the free tier (2,000 credits/mo, no card), then per-credit |
| Setup | No key, but User-Agent + attribution required | Google Cloud project + billing card | One API key |
| Rate limit | 1 req/sec absolute, 4/min for bulk jobs | 25 QPS default (raisable on request) | Handled behind the key |
| Retry/backoff logic | You write it | Google's infra | Handled server-side |
| Data source | OpenStreetMap | Google's own index | OpenStreetMap |
| SLA | None — best-effort public service | Google's commercial terms | No formal SLA; same upstream, retries handled for you |
| Best for | Prototypes, hobby projects, very low volume | Teams needing Google's proprietary accuracy, already on GCP | One key across geocoding and 500+ other scraping/data endpoints |
What you can collect
Per address or coordinate: coordinates (lat/lon), a full display name, and a structured address breakdown (house number, road, neighbourhood, suburb, city, county, state, postcode, country, and ISO country code) where OpenStreetMap has that level of detail mapped. Each result also carries its OpenStreetMap identity (osm_id, osm_type), a place classification (category, addresstype, type), a relative importance score, and a boundingbox — useful for deciding which of several same-named results is the right one.
Limitations and common challenges
- Coverage varies by region. OpenStreetMap's address density is excellent in most of Europe and North America but thinner in some countries — if a national alternative like GSI covers your target region better, it's worth checking first.
- Free tiers cap out fast at real volume. 10,000 requests/month (Google) or 1 req/sec (Nominatim) both sound generous until a batch job of 50,000 addresses needs to run overnight.
- Ambiguous addresses need a fallback. "350 5th Ave" without a city can return results in multiple states; always pass as much structure (
city,state,country) as you have, and checkimportance/place_rankon multi-result responses. - No source here is a real-time uptime guarantee. Whether you call Nominatim directly or through a structured API sitting on the same data, budget for occasional retries in a production pipeline.
Sources
Start collecting
Try it first, free: run any public URL through the Free Web Scraper, or check whether a site blocks bots with the Anti-Bot Checker — no signup.
Test the search, reverse, and lookup endpoints in the Playground, check the schema in the API docs, and review pricing. Pair coordinates with a Google Maps places pull for local-business context, real estate listings or Zillow for property addresses that need geocoding, or Numbeo cost-of-living data to enrich a location with quality-of-life stats. See also is web scraping legal for the broader legal basics, and property market intelligence for the end-to-end use case.
Part of our how-to-scrape guide series — every platform we cover, in one index.
Frequently asked questions
Is there a free geocoding API?
Yes. The public Nominatim/OpenStreetMap instance is free with no signup or API key, but it caps at 1 request/second absolute, restricts one-off bulk jobs to 4 requests/minute from a single machine, requires a real User-Agent or Referer plus attribution, and carries no uptime SLA. It's a solid fit for prototypes and low-volume use, not a guaranteed-uptime production dependency.
How does geocoding API pricing compare across providers?
Nominatim/OpenStreetMap is free but rate-limited to 1 req/sec with no SLA. Google's Geocoding API gives 10,000 free requests/month (Cloud billing required), then $5.00 per 1,000 up to 100,000, tiering down to $0.38 per 1,000 past 5 million. Mapbox offers 100,000 free geocoding requests/month, then roughly $0.45–$0.75 per 1,000. OpenCage's free tier (2,500/day) is for testing only, not production; LocationIQ's free tier (about 5,000/day) does allow commercial use. A structured API sitting on the open data can undercut all of these for a general-purpose pipeline that doesn't need Google's proprietary index.
What's a good alternative to the Google Maps geocoding API?
For most use cases, the free public Nominatim/OpenStreetMap API or a structured geocoding API built on the same open data cover it without a Google Cloud billing account. Mapbox and LocationIQ are also viable paid alternatives with more generous free tiers. If your addresses are concentrated in one country, that country's own mapping agency (e.g. Japan's 国土地理院/GSI) can be free and more accurate than any global index. Esri's ArcGIS World Geocoding Service is the enterprise-GIS-oriented option if you're already on that stack.
What is reverse geocoding and how do I call it?
Reverse geocoding converts a coordinate (latitude/longitude) into a readable address instead of the other way around — useful for turning a GPS ping, delivery drop pin, or photo location into a city, postcode, or neighborhood. Call a reverse endpoint with lat and lon (e.g. GET /geocoding/reverse?lat=..&lon=..) and it returns the nearest place with a full structured address breakdown.
What are typical geocoding API rate limits?
They vary sharply by provider: Nominatim's free public instance is capped at 1 request/second absolute (4/minute for bulk jobs), Google's default is 25 queries/second (raisable on request), and paid providers like Mapbox and LocationIQ typically scale requests/second with plan tier. Always check the specific provider's current policy before building a batch job around an assumed limit.
Is it legal to geocode a list of addresses?
Generally yes — converting a public address to coordinates (or back) is an uncontroversial, well-established use of public data. The nuance is licensing on the data source (OpenStreetMap's ODbL requires attribution and share-alike if you redistribute the underlying map data) and personal-data rules if the address is tied to an identifiable person (GDPR/CCPA). Not legal advice.
Can I geocode addresses outside the US?
Yes — Nominatim, Google, Mapbox, and a structured API built on OpenStreetMap data all cover addresses worldwide, though coverage density varies by country. For a single country you know well, check whether that country's national mapping agency offers its own free geocoder before defaulting to a global provider.