Disclosure: I operate Geocoding.info. This tutorial and code were generated with AI assistance. The example client has been checked locally with mocked responses; authenticated production requests require your own key.
Reverse geocoding turns latitude and longitude into readable place information. It is useful when your application already has coordinates from a map pin or GPS reading and needs to describe that location.
In this example, we will call a hosted API from Python using only the standard library. The script also supports forward geocoding: searching for a place name or address.
Get an API key
Create an account, verify your email if prompted, and create an API key in your dashboard. A free tier is available; check the current plans and limits.
Use Python 3.10 or later. Store the key in an environment variable on the machine running the script.
On macOS or Linux:
export GEOCODING_API_KEY='YOUR_API_KEY'
In Windows PowerShell:
$env:GEOCODING_API_KEY = 'YOUR_API_KEY'
Keep the real key out of your repository, screenshots and logs.
The Python client
Save the following as geocode.py:
import json
import os
import sys
from urllib.parse import urlencode
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
def build_url(operation, values, key):
if operation not in ('search', 'reverse'):
raise ValueError('Use search or reverse.')
if not key:
raise ValueError('Set GEOCODING_API_KEY.')
params = {'format': 'json', 'accept-language': 'en', 'key': key}
if operation == 'search':
if len(values) != 1 or not values[0].strip():
raise ValueError('Provide one quoted address.')
params['q'] = values[0]
else:
if len(values) != 2:
raise ValueError('Provide latitude and longitude.')
lat, lon = map(float, values)
if not (-90 <= lat <= 90 and -180 <= lon <= 180):
raise ValueError('Invalid coordinates.')
params.update(lat=str(lat), lon=str(lon))
return 'https://api.geocoding.info/' + operation + '?' + urlencode(params)
def geocode(operation, values, key):
url = build_url(operation, values, key)
try:
with urlopen(url, timeout=20) as response:
return json.load(response)
except HTTPError as error:
raise RuntimeError(
'API returned HTTP ' + str(error.code) + '. Check your key and limits.'
) from None
except (URLError, TimeoutError):
raise RuntimeError('Could not reach the API.') from None
if __name__ == '__main__':
try:
if len(sys.argv) < 3:
raise ValueError(
'Usage: geocode.py search "Paris, France" '
'OR reverse 48.8584 2.2945'
)
result = geocode(
sys.argv[1], sys.argv[2:], os.getenv('GEOCODING_API_KEY', '')
)
print(json.dumps(result, indent=2))
except (ValueError, RuntimeError) as error:
print(str(error), file=sys.stderr)
sys.exit(1)
The client URL-encodes parameters, checks coordinate ranges, sets a timeout, and reports HTTP errors without printing the URL containing your key. It requests JSON and English names where available.
Reverse geocode a point
python geocode.py reverse 48.8584 2.2945
Latitude comes first, then longitude. The reverse endpoint returns a JSON object for a matching feature. Useful fields can include display_name, lat, lon and address, depending on available map data. This example prints the actual response rather than assuming every address field exists.
Search for an address
python geocode.py search "Paris, France"
Search returns candidate locations as a list. An empty list is possible, and an ambiguous query can produce multiple matches. Include a city or country when you can.
Handle limits and map-data differences
Handle authentication errors (401), rate or quota limits (429), and temporary failures (5xx). Both daily and 30-day allowances apply. Send requests sequentially for this example; production clients should use bounded retries and respect their account rate limit.
The service uses OpenStreetMap/Nominatim data. Coverage varies, and reverse lookup can describe a nearby mapped feature rather than an exact postal address. It is not postal-address validation. Follow the applicable OpenStreetMap attribution and licensing requirements.
Try another integration
- Python, Node.js and cURL examples on GitHub
- Public Postman collection and getting-started guide
- Interactive demo
What location feature are you building? Feedback on the integration and documentation is welcome.
Top comments (0)