white and green state maps

Python 101: Geocoding for a location with Nominatim

Posted on December 25, 2022

Many APIs that provide location-specific information require information like an address or geographical coordinates to provide the correct data. Some APIs specifically require longitude and latitude coordinates for successful calls. How do you get that information for a specific location? It has not been easy to find in the past, but many services now provide geocoding. I’ll share a sample using an API that Nominatim/OpenStreetMap exposes to retrieve the necessary information.

Geocoding is the process of taking a text-based description of a location, such as an address or the name of a place, and returning geographic coordinates, frequently latitude/longitude pair, to identify a location on the Earth’s surface. 

In this example, we’ll get information about a location by providing only the city and state of the location we’re looking for.

Note: At the time of this writing, this API was freely accessible without a token or key. Also, you can get more detailed coordinate information by providing a complete street address.

Putting it all together

Since we’ll be calling a server hosting the API, we’ll need to import the requests library for use in our script.

import requests

Then we’ll set up a couple of variables for our city and state that we want to find out more about. In this case, let’s find out more information about the location of Duluth, Minnesota.

city = "Duluth"
state = "MN"

And put together our URL for the API call to Nominatim. We’ve incorporated the variables for the location we set above, so their values are used in the call to the URL. We’ll add some parameters to return JSON as the response for us to consume and limit the list of responses to just one. Remember that if you’re querying for a large city, this list could be long because of multiple zip codes and other factors. The more specific query, the smaller that list will be. Regardless, in this sample, we’ll take just the first item. You can dig into more about the parameters in the Nominatim API documentation.

url = "https://nominatim.openstreetmap.org/?addressdetails=1&q=" + city + "+" + state + "&format=json&limit=1"

OK, we’re now ready to make the request to the API, and we’ll store the responses in an object. Since we know that the list only had a single item in the array, we’ll print out the longitude and latitude of the location we requested.

response = requests.get(url).json()

print(f'Coordinates for {response[0]["display_name"]}')
print(f'Latitude: {response[0]["lat"]}')
print(f'Longitude: {response[0]["lon"]}')

When we run the script, we see the output:

Coordinates for Duluth, Saint Louis County, Minnesota, United States
Latitude: 46.7729322
Longitude: -92.1251218

The API returns more useful information than what we’re looking for. Here’s a sample of the JSON response that is returned:

[
  {
    "place_id": 298008823,
    "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
    "osm_type": "relation",
    "osm_id": 136669,
    "boundingbox": [
      "46.6491584",
      "46.880571",
      "-92.301192",
      "-91.920178"
    ],
    "lat": "46.7729322",
    "lon": "-92.1251218",
    "display_name": "Duluth, Saint Louis County, Minnesota, United States",
    "class": "boundary",
    "type": "administrative",
    "importance": 0.751658795796653,
    "icon": "https://nominatim.openstreetmap.org/ui/mapicons/poi_boundary_administrative.p.20.png",
    "address": {
      "city": "Duluth",
      "county": "Saint Louis County",
      "state": "Minnesota",
      "ISO3166-2-lvl4": "US-MN",
      "country": "United States",
      "country_code": "us"
    }
  }
]

Final code

Here’s the full script when complete:

import requests

city = "Duluth"
state = "MN"

url = "https://nominatim.openstreetmap.org/?addressdetails=1&q=" + city + "+" + state + "&format=json&limit=1"

response = requests.get(url).json()

print(f'Coordinates for {response[0]["display_name"]}')
print(f'Latitude: {response[0]["lat"]}')
print(f'Longitude: {response[0]["lon"]}')

That’s it!

In this sample, we were able to retrieve geocode information like geographical coordinates about a location with a freely accessible API.

You might find these interesting...

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments