Google Maps Charges $7 Per 1000 Requests. OpenStreetMap Charges $0.
OpenStreetMap (OSM) is the Wikipedia of maps. Community-maintained, completely free, and it has multiple APIs for geocoding, routing, and tile rendering.
Geocoding (Address to Coordinates)
Nominatim is the free geocoder:
import requests
def geocode(address):
r = requests.get("https://nominatim.openstreetmap.org/search", params={
"q": address, "format": "json", "limit": 1
}, headers={"User-Agent": "MyApp/1.0"})
if r.json():
result = r.json()[0]
return {"lat": result["lat"], "lon": result["lon"], "display": result["display_name"]}
return None
location = geocode("Eiffel Tower, Paris")
print(location)
# {lat: 48.858, lon: 2.294, display: Tour Eiffel, Paris, France}
Reverse Geocoding (Coordinates to Address)
def reverse_geocode(lat, lon):
r = requests.get("https://nominatim.openstreetmap.org/reverse", params={
"lat": lat, "lon": lon, "format": "json"
}, headers={"User-Agent": "MyApp/1.0"})
return r.json().get("display_name")
address = reverse_geocode(40.7128, -74.0060)
print(address) # New York, NY, USA
Routing (Directions)
OSRM (Open Source Routing Machine) provides free routing:
def get_route(start_lat, start_lon, end_lat, end_lon):
url = f"http://router.project-osrm.org/route/v1/driving/{start_lon},{start_lat};{end_lon},{end_lat}"
r = requests.get(url, params={"overview": "false"})
route = r.json()["routes"][0]
return {
"distance_km": round(route["distance"] / 1000, 1),
"duration_min": round(route["duration"] / 60, 1)
}
route = get_route(48.8566, 2.3522, 51.5074, -0.1278) # Paris to London
print(route) # {distance_km: 456.3, duration_min: 285.7}
Search for Places (POI)
def find_places(query, lat, lon, radius=1000):
overpass_url = "http://overpass-api.de/api/interpreter"
overpass_query = f"""
[out:json];
node["amenity"="{query}"](around:{radius},{lat},{lon});
out body 5;
"""
r = requests.get(overpass_url, params={"data": overpass_query})
return [{"name": e.get("tags", {}).get("name", "Unknown"),
"lat": e["lat"], "lon": e["lon"]}
for e in r.json()["elements"]]
cafes = find_places("cafe", 48.8566, 2.3522)
for c in cafes:
print(f"{c[name]} ({c[lat]}, {c[lon]})")
Google Maps vs OpenStreetMap
| Feature | Google Maps | OpenStreetMap |
|---|---|---|
| Geocoding | $5/1000 req | Free |
| Directions | $5-10/1000 req | Free |
| Map tiles | $7/1000 loads | Free |
| API key | Required + billing | Not needed |
| Data ownership | Community | |
| Self-hosting | No | Yes |
When to Use Google Maps Instead
- You need Street View
- You need real-time traffic data
- You need indoor maps
- Your app requires guaranteed SLA
For everything else, OSM is free and good enough.
More from me: 10 Dev Tools I Use Daily | 77 Scrapers on a Schedule | 150+ Free APIs
Top comments (0)