How to use the Google Maps API for Geocoding with Python to get Latitude and Longitude
Using Python to geocode locations using the google maps api can help you avoid situations like this:
Client: I want to show a marker on a google map for each of my Hot Dog Stands!
You: Great! Do you have the geolocation for each of your Hot Dog Stands?
Client: What? Maybe someone else can help me…
Have you ever found yourself asking a client something like this? Putting markers on a map is a common request, since google maps provides an interactive experience.
Everyone wants their users to have fun navigating their site. Including an interactive map is a great way to do that. But to do it we need to geocode locations into latitude and longitude. The locations may be specific like addresses. But sometimes they are general like postal codes or even cities (or in the picture above, beaches).
People want simple solutions – they don’t want to mess with coordinates. The intent is to have these locations appear on a google map. On the server, address or location info needs to be geocoded into coordinates. Then the latitude and longitude need to be associated with the user entered data.
Enter the Google Maps Geocoding API, which has an excellent tutorial using JavaScript and a command line example using React.
Yet in this scenario we have locations stored in a database and need to add latitude and longitude to them. We’ll use a python script to interact with the database. Then it will communicate with the geocoding api to populate those coordinate fields.
Is the Google Maps API Free?
It can be depending on how much you use it. Here is a table with pricing for the Geocoding API:
How to Begin? Here are the basic steps to get started with the API:
- Signup for a free account at RapidAPI.com
- Subscribe to Google Maps Geocoding API. What this means is you select one of the plans from the Google Maps Geocoding API pricing page. The prices for the plans are shown in the table above.
- Pick your language! Let’s walk through an example use case now in Python. The one we started with has locations in a database. These locations need latitude and longitude in order for a webpage to place markers on a map for them.
How to use the Google Maps API with Python
For this example, we’ll have a simple database table in MySQL. The name of the table is `hotdog_stand_locations` and it has the following fields:
- hotdog_stand_location_id – autoincrement integer, primary key
- location_name – like “Bondi Beach”, this could also be a street address like “123 Main St”
- city – like “Bondi”
- state – like “NSW”
- postal code – like 2026
- country – like Australia
- latitude – float value, null until we populate it.
- longitude – float value, null until we populate it.
We will assume it will start with the following data. Note that not all of the fields are populated. Often we deal with incomplete data. Fortunately Google Maps API does a good job of handling incomplete inputs:
Goal
The latitude and longitude fields of the database table need to be populated for the hot dog stands. The coordinates correspond to locations listed in the database. This will enable the vendor locations to be added to a google map using markers.
Step 1 – Grab the Python Code Snippet
Start with the code snippet for python from the Google Maps Geocoding API page. I developed the solution below using the http.connect option. The reason for this choice is that it uses only a built-in python module:
import http.client conn = http.client.HTTPSConnection("google-maps-geocoding.p.rapidapi.com") headers = { 'x-rapidapi-host': "google-maps-geocoding.p.rapidapi.com", 'x-rapidapi-key': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } conn.request("GET", "/geocode/json?language=en&address=164%20Townsend%20St.%252C%20San%20Francisco%252C%20CA", headers=headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8"))
I’ve replaced my personal RapidAPI key with a string of x’s, once you are logged in to RapidAPI yours will populate within each of the code samples. There are several languages and libraries you can choose from on the endpoints page.
Step 2 – Include the API Connection
Include the API connection within item 3 of the following pseudo code:
- Query the database to pull a list of location records needing latitude or longitude
- For each location record, construct an API call using the address
- Call the google maps geocoding API (defined in a function above). Then parse the results to pull out latitude and longitude
- Update the database record to include the latitude and longitude
Step 3 – Expand the Code
Expand the pseudo code. Written in Python the complete example code looks like this (replace the x’s with your credentials):
#! python """ File: geocode_addresses.py Description: This script pulls a list of locations which need lat/lng added, uses an api to retrieve them from google maps, then updates the database records. """ #Import python modules used below import http.client import mysql.connector from mysql.connector import errorcode import pandas as pd import json #Setup api details here api_conn = http.client.HTTPSConnection("google-maps-geocoding.p.rapidapi.com") headers = { 'x-rapidapi-host': "google-maps-geocoding.p.rapidapi.com", 'x-rapidapi-key': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } #Connect to the local database try: cnx = mysql.connector.connect(user='xxxxxx', password='xxxxxxx', host='localhost', database='xxxxxxxxxx') except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") elif err.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") else: print(err) #Function to get json response from google api def get_geocode_response(this_address): api_conn.request("GET", "/geocode/json?language=en&address="+this_address, headers=headers) res = api_conn.getresponse() data = res.read().decode("utf-8") thejson = json.loads(data) return thejson #STEP 1: Query the database to pull a list of location records needing latitude or longitude sql = ("select * from hotdog_stand_locations where isNull(latitude) or isNull(longitude)") cursor = cnx.cursor() try: number_of_rows = cursor.execute(sql) table_rows = cursor.fetchall() except mysql.connector.DataError as e: print("DataError") print(e) except mysql.connector.InternalError as e: print("InternalError") print(e) except mysql.connector.IntegrityError as e: print("IntegrityError") print(e) except mysql.connector.OperationalError as e: print("OperationalError") print(e) except mysql.connector.NotSupportedError as e: print("NotSupportedError") print(e) except mysql.connector.ProgrammingError as e: print("ProgrammingError") print(e) except : print("Unknown error occurred") if len(table_rows)>0: mydf = pd.DataFrame(table_rows, columns=cursor.column_names) #STEP 2: For each location record, construct an api call using the address for index, row in mydf.iterrows(): #Setup address string to send to google maps api. It is ok to have some blank inputs but spaces have to be encoded as %20 this_address = str(row['location_name'])+' '+str(row['city'])+' '+str(row['state'])+' '+str(row['postal_code'])+' '+str(row['country']) this_address = this_address.replace(' ','%20') #STEP 3: Call the google maps geocode api (defined in a function above). # Then parse the results to pull out latitude and longitude #print("about to get api response for this_address "+str(this_address)) api_response = get_geocode_response(this_address) this_lat = api_response['results'][0]['geometry']['location']['lat'] this_lng = api_response['results'][0]['geometry']['location']['lng'] #print("lat is "+str(this_lat)+" from api_response") #STEP 4: Update the database record to include the latitude and longitude sql = ("update hotdog_stand_locations set latitude='"+str(this_lat)+"', longitude='"+str(this_lng)+"' " "where hotdog_stand_location_id='"+str(row['hotdog_stand_location_id'])+"'") try: cursor.execute(sql) cnx.commit() except mysql.connector.DataError as e: print("DataError") print(e) except mysql.connector.InternalError as e: print("InternalError") print(e) except mysql.connector.IntegrityError as e: print("IntegrityError") print(e) except mysql.connector.OperationalError as e: print("OperationalError") print(e) except mysql.connector.NotSupportedError as e: print("NotSupportedError") print(e) except mysql.connector.ProgrammingError as e: print("ProgrammingError") print(e) except : print("Unknown error occurred from query: "+sql) else: print("All coordinates are already in place!")
The code above runs on windows with python in the path (installed from python.org). It queries a local mysql database which comes with a local install of xampp. The mysql module for python can be installed on windows using “pip3 install mysql-connector”. For a linux server you would change the first line to something like “#!/usr/bin/env python”. This is depending on where python lives on the server. In addition you might need to change your database host from localhost to a domain or IP address if it is not local.
Conclusion
In this tutorial we’ve walked through an example of how to use the Google Maps API with Python. We’ve seen how the Geocoding API can fill in missing information in a database. This process can augment an existing internal admin area for business owners. Those who want simple solutions can manage their locations by name and address. This way, the server manages coordinates needed for map markers. The coordinates are what helps to put markers onto google maps. This can all happen behind the scenes. Also, you will never have to ask your clients if they know any geolocations! 🙂
Full Disclosure
I made up the story but the code is real. I found the image in a stack overflow article that describes how to put multiple markers on a google map. Are any hot dog stands at the beach in Australia? I don’t know. If not, there may be a market opportunity for a new business there.
Rik Graulus says
Hi,
Do you also support reverse geocoding? If so, where can I find a write-up or tutorial on that?
Regards
Rik
Robert Davis says
Hi Rik,
If you are interested in reverse geocoding I would recommend reviewing the article at rapidapi.com/blog/google-maps-geocoding-api/.
Regards,
Robert