geopy
Geocoding library for Python — convert addresses to coordinates and back, calculate distances. geopy features: Nominatim geocoder (OpenStreetMap, free), GoogleV3 geocoder, ArcGIS, Bing, HERE, and 20+ other geocoders, geocode() for address→coordinates, reverse() for coordinates→address, GeocoderTimedOut handling, geopy.distance.geodesic() for great-circle distance calculation, geopy.distance.great_circle() for haversine, and User-Agent rate limiting compliance. Unified interface across 20+ geocoding providers — switch backends with one line change.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
API keys for commercial geocoders must be stored in environment variables. Location data sent to geocoding providers — use self-hosted Nominatim for sensitive address data. No credential storage in geopy itself.
⚡ Reliability
Best When
Converting addresses to coordinates, reverse geocoding GPS positions, or calculating geographic distances — geopy's unified interface supports 20+ geocoding providers and handles the tedious API-specific formatting.
Avoid When
You need routing/directions, high-volume geocoding (>1M/month), or complex geospatial analysis (use Shapely/GeoPandas).
Use Cases
- • Agent address geocoding — from geopy.geocoders import Nominatim; geolocator = Nominatim(user_agent='my-agent-app'); location = geolocator.geocode('1600 Pennsylvania Ave, Washington DC'); print(location.latitude, location.longitude) — convert address to coordinates; agent location-aware service geocodes user-provided addresses for mapping or proximity queries
- • Agent reverse geocoding — from geopy.geocoders import Nominatim; geolocator = Nominatim(user_agent='my-agent'); location = geolocator.reverse('48.8566, 2.3522') — GPS coordinates to human address; agent fleet tracker converts vehicle GPS coordinates to human-readable locations for driver logs
- • Agent distance calculation — from geopy.distance import geodesic; nyc = (40.7128, -74.0060); london = (51.5074, -0.1278); dist = geodesic(nyc, london).km; dist_miles = geodesic(nyc, london).miles — accurate great-circle distance in km or miles; agent delivery optimizer calculates distances between depot and customer locations
- • Agent proximity filtering — from geopy.distance import geodesic; center = (37.7749, -122.4194); nearby = [loc for loc in locations if geodesic(center, (loc.lat, loc.lng)).km < 5] — filter locations within 5km radius; agent local search finds nearby restaurants, stores, or agents within proximity threshold
- • Agent batch geocoding with rate limiting — from geopy.extra.rate_limiter import RateLimiter; geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1); results = [geocode(addr) for addr in address_list] — rate-limited batch geocoding; agent data enrichment pipeline adds coordinates to address list without violating Nominatim 1 req/sec policy
Not For
- • High-volume geocoding — Nominatim is 1 req/sec limited; for 100K+ geocodes use Google Maps API (paid) or batch geocoding services
- • Routing and directions — geopy is geocoding only; for turn-by-turn routing use OSRM, GraphHopper, or Google Directions API
- • Geospatial analysis — geopy does distance and geocoding; for polygon operations and spatial joins use Shapely and GeoPandas
Interface
Authentication
Nominatim (OpenStreetMap) requires User-Agent string only — no API key. Google Maps requires API key. Most commercial geocoders need API keys. Keys passed to geocoder constructor.
Pricing
geopy library is MIT licensed and free. Geocoding API costs depend on chosen provider. Nominatim (OpenStreetMap) is free for non-commercial and light commercial use.
Agent Metadata
Known Gotchas
- ⚠ geocode() returns None not exception for failed lookup — geolocator.geocode('nonexistent address 99999') returns None, not raises exception; agent code doing location.latitude fails with AttributeError on None; always check: location = geolocator.geocode(addr); if location is None: handle_not_found()
- ⚠ Nominatim requires unique User-Agent — Nominatim ToS requires identifying User-Agent: Nominatim(user_agent='my-agent-app/1.0 (contact@example.com)'); using generic user_agent='test' or 'myapp' risks being blocked; blocked Nominatim users get 403 responses for all requests
- ⚠ Nominatim 1 req/sec limit must be respected — sending more than 1 request/second to Nominatim violates ToS and results in ban; agent batch geocoding must use RateLimiter: from geopy.extra.rate_limiter import RateLimiter; geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
- ⚠ GeocoderTimedOut should be retried — network timeouts are transient; agent code must wrap in retry: from tenacity import retry, stop_after_attempt; @retry(stop=stop_after_attempt(3)); geopy doesn't retry automatically; add tenacity or similar retry logic for production agent geocoding
- ⚠ location.raw contains full geocoder response — location.address is formatted string; location.raw is the full provider JSON/dict response with detailed fields (neighborhood, city, country_code); agent code needing specific address components should access location.raw directly rather than parsing location.address string
- ⚠ Different geocoders return different accuracy — Nominatim returns neighborhood-level for some addresses where Google returns exact building location; agent geocoding for delivery routing should test accuracy with representative addresses before choosing provider; accuracy varies significantly by geography
Alternatives
Full Evaluation Report
Comprehensive deep-dive: security analysis, reliability audit, agent experience review, cost modeling, competitive positioning, and improvement roadmap for geopy.
AI-powered analysis · PDF + markdown · Delivered within 30 minutes
Package Brief
Quick verdict, integration guide, cost projections, gotchas with workarounds, and alternatives comparison.
Delivered within 10 minutes
Score Monitoring
Get alerted when this package's AF, security, or reliability scores change significantly. Stay ahead of regressions.
Continuous monitoring
Scores are editorial opinions as of 2026-03-06.