Use a secret key (gc_sk_…) from an environment variable. Install requests (pip install requests).
Search and reverse
import os
import requests
API = "https://api.geolith.app"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['GEOLITH_API_KEY']}"
def search(text: str, country: str | None = None, size: int = 1) -> list[dict]:
params = {"text": text, "size": size}
if country:
params["boundary.country"] = country
res = session.get(f"{API}/v1/search", params=params, timeout=10)
res.raise_for_status()
return res.json()["features"]
def reverse(lat: float, lon: float) -> dict | None:
res = session.get(
f"{API}/v1/reverse",
params={"point.lat": lat, "point.lon": lon, "size": 1},
timeout=10,
)
res.raise_for_status()
features = res.json()["features"]
return features[0] if features else None
hit = search("eiffel tower", country="FR")[0]
lon, lat = hit["geometry"]["coordinates"]
print(hit["properties"]["label"], lat, lon)
print(reverse(18.922, 72.8347)["properties"]["label"])
Retries
Retry 429 rate_limited after Retry-After. Stop on 429 quota_exceeded.
import time
def get_with_retry(path: str, params: dict, tries: int = 5) -> dict:
for attempt in range(tries):
res = session.get(f"{API}{path}", params=params, timeout=10)
if res.status_code == 429:
if res.json().get("error", {}).get("code") == "quota_exceeded":
res.raise_for_status()
time.sleep(float(res.headers.get("Retry-After", "1")))
continue
if res.status_code >= 500:
time.sleep(0.5 * 2**attempt)
continue
res.raise_for_status()
return res.json()
raise RuntimeError("geolith: gave up after retries")
A batch with pandas
import pandas as pd
df = pd.DataFrame({"address": ["Shaniwar Wada, Pune", "Gateway of India, Mumbai"]})
def first_point(address: str) -> pd.Series:
features = get_with_retry("/v1/search", {"text": address, "size": 1})["features"]
if not features:
return pd.Series({"label": None, "lat": None, "lon": None})
f = features[0]
return pd.Series({
"label": f["properties"]["label"],
"lat": f["geometry"]["coordinates"][1],
"lon": f["geometry"]["coordinates"][0],
})
df = df.join(df["address"].apply(first_point))
print(df)
Results may be stored permanently. Keep the attribution, © OpenStreetMap contributors (ODbL), Overture Maps Foundation, with any data you show.