Geocoding with Python: Convert Any Address to Coordinates

Convert addresses to coordinates in Python with geopy and Nominatim – rate limits, reverse geocoding, batch geocoding a CSV with pandas, and API options.

Geocoding with Python

Last updated: July 2026

Geocoding turns “Ellis Bridge, Ahmedabad” into latitude/longitude — and reverse geocoding does the opposite. The quickest free route in Python is geopy with the OpenStreetMap Nominatim service.

Setup

pip install geopy

Address → coordinates

from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="my-geocoder-demo")  # a real identifier, required
location = geolocator.geocode("Ellis Bridge, Ahmedabad, India")

print(location.address)
print(location.latitude, location.longitude)
# 23.02, 72.56 (approx.)

Always set a meaningful user_agent — Nominatim rejects the default one.

Coordinates → address (reverse)

location = geolocator.reverse((23.0225, 72.5714))
print(location.address)

Batch geocoding a CSV (the right way)

Nominatim’s public server allows 1 request per second — hammer it and you get banned. geopy ships a rate limiter for exactly this:

import pandas as pd
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter

df = pd.read_csv("addresses.csv")            # column: address
geolocator = Nominatim(user_agent="my-batch-geocoder")
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)

df["location"]  = df["address"].apply(geocode)
df["latitude"]  = df["location"].apply(lambda l: l.latitude  if l else None)
df["longitude"] = df["location"].apply(lambda l: l.longitude if l else None)
df.drop(columns="location").to_csv("geocoded.csv", index=False)

Failed lookups come back as None rather than crashing the run — keep those rows and retry them with a cleaned-up address string.

When Nominatim isn’t enough

For high volume, guaranteed uptime, or better rooftop-level accuracy, switch the geocoder class, not your code — geopy wraps the commercial APIs too:

from geopy.geocoders import GoogleV3
geolocator = GoogleV3(api_key="YOUR_KEY")

Google, HERE, Mapbox, and OpenCage all follow the same geocode() interface; they require an API key and bill past their free tiers. My rule of thumb: Nominatim for prototypes and small batches, a paid API once addresses number in the tens of thousands or the results ship to customers.

Accuracy tip: include city and country in the query string. Bare street names geocode to the wrong continent more often than you’d think.

Comments

comments