DEV Community

Wesley Chun (@wescpy)
Wesley Chun (@wescpy)

Posted on • Updated on

Explore the world with Google Maps APIs

TL;DR:

The US Memorial Day holiday is traditionally a time when many travel to visit friends or family for a long weekend in remembrance of military personnel who made the ultimate sacrifice while serving in the country's armed forces, and traveling makes me think of Google Maps and its APIs. While there's a brief intro to one of the Maps APIs in a post on API keys, Maps needs its own treatment, so this is your formal introduction to the Maps Platform. To avoid an overwhelming amount of content, we're exploring its server-side APIs, those you'd access from a web app or mobile backend.

Google Maps Platform

Introduction

Welcome to the blog focused on showing Python (and sometimes Node.js) developers how to use a variety of Google APIs. On this blog, you'll find content covering a broad variety of topics such as serverless computing, generative AI with Gemini, and Google credentials like API keys and OAuth client IDs, the latter specifically for use with Google Workspace (GWS) APIs. Other posts dive into a specific solution, such as using one of those GWS APIs to export Google Docs as PDF files. This post exposes readers to several APIs from yet another product group, Google Maps.

The platform features many different services, APIs, and SDKs (~20), and covering them all isn't really "digestible" in one go. Maps is also a visual product, so many of its services are on the client-side as one would expect. If you're a developer reading a blog covering APIs and frequently using APIs however, there's a good chance you work on server-side software, so covering the Maps APIs accessible from that perspective makes the most sense here.

Maps services are grouped into four distinct categories, each summarized below:

Category Description
Maps (M) Static & dynamic mapping, Street View imagery, elevation, aerial/geospatial imagery, map tiles
Routes (R) Location of roads; routing/directions for various transportation modes; traffic info, times & distances
Places (P) Place & location information: details, search, lat-long coordinates, addressing & geolocation, time zones
Environment (E) Solar energy potential, air quality indexes, location-based pollen/pollutant info & health recommendations
Google Maps Platform service categories

 

The server-side APIs are known as the Web Service APIs. There are 15 of them at the time of this writing, and that's still too much to cover in a single post. To further whittle down what to cover, we're going to focus on those that are supported by the Maps client libraries. The others require you to use raw REST and HTTP, and hopefully the Maps team will soon support those with their client libraries.

In the meantime, we can help you get started with supported APIs. Client libraries encapsulate much of the boilerplate and do a lot of the heavy lifting so developers can focus on using API features. At the time of this writing, they support the 7 APIs listed below and account for nearly a third of all Maps services about half of all Maps APIs:

  1. Directions API (R)
  2. Distance Matrix API (R)
  3. Elevation API (M)
  4. Geocoding API (P)
  5. Roads API (R)
  6. Places API (P)
  7. Time Zone API (P)

Of the APIs listed, I'll be demonstrating the bolded ones in this post.

Prerequisites

As with other Google APIs, there are several distinct steps that you must take before you can use them from your application:

  1. Get credentials from DevConsole; Maps uses API keys
  2. Install client library for your development language
  3. Enable desired API(s) in developer's console ("DevConsole")

These actions are unrelated to each other, meaning you can do them in any order.

Get credentials (API key)

The first task is to get an API key:

  1. Go to the DevConsole credentials page
  2. Click + Create Credentials at the top
  3. Select API key and wait a few seconds for completion
  4. Copy and save API key as a variable API_KEY = '<YOUR-API-KEY>' to settings.py for Python or .env for Node.js (may need to refresh credentials page and click Show key to see it)
⚠️ WARNING: Keep API keys secure
Storing API keys in files (or hard-coding them for use in actual code or even assigning to environment variables) is for prototyping and learning purposes only. When going to production, put them in environment variables or in a secrets manager. Files like settings.py or .env containing API keys are susceptible. Under no circumstances should you upload files like those to any public or private repo, have sensitive data like that in TerraForm config files, add such files to Docker layers, etc., as once your API key leaks, everyone in the world can use it.

If you're new to Google developer tools, API keys are one of the credentials types supported by Google APIs, and they're the only type supported by Maps APIs. Other credentials types include OAuth client IDs, mostly used by GWS APIs, and service accounts, mostly used by Google Cloud (GCP) APIs.

Install client library (Maps)

The core Maps client libraries are available in four languages:

  1. Java
  2. Python
  3. Go
  4. Node.js
📝 NOTE: Other client libraries
In the documentation, you may find reference to additional client libraries, for example in C# and Objective-C. However, these are resources used to either access REST API interfaces directly or are custom-built for specific APIs like the Address Validation API, so they aren't part of the "core" Maps client libraries.

Install the one for your development language, and any others if you work with more than one. Here are the commands for Python (2 or 3) and Node.js:

Language Command
Python pip install -U googlemaps html2text # (or pip3)
Node.js npm install core-js dotenv @googlemaps/google-maps-services-js
Maps client library installation commands

 

Confirm all required packages have been installed correctly with these validation commands:

Language Command
Python python -c "import googlemaps, html2text" # (or python3)
Node.js node -e "require('@googlemaps/google-maps-services-js')"
Maps client library validation commands

 

If they complete without error, the installation(s) succeeded and they're ready for use.

Enable APIs (Maps)

Now it's time to enable the Maps APIs used in the samples. All Google APIs must be enabled before they can be used. While many Google APIs are free to use, Maps APIs are not. However, all users are granted a monthly "quota" of $200USD of usage before incurring billing. Review the Maps Platform billing page to understand all the terms and conditions, then create a billing account backed by some financial instrument like a credit card or trial credit as described on that billing page.

Once you have a billing account, the next step is to create a project and assign that billing account to that project. You can also reuse an existing project if you have one. Now you can enable the Maps APIs. There are generally three different ways of enabling Google APIs.

  1. DevConsole manually -- Enable one API at a time by following these steps:
    • Go to DevConsole
    • Click on Library tab and search for "Maps" to see all the Maps APIs
    • Scroll down and look for Geocoding API, Time Zone API, and Directions API
    • Click Enable API button for each API
  2. DevConsole link -- You may be new to Google APIs or don't have experience enabling APIs in the DevConsole. If this is you, the above steps can be simplified with a single DevConsole link (and click) that enables all three APIs.
  3. gcloud/command-line -- For those who prefer working in a terminal, you can enable APIs with a single command in the Cloud Shell or locally on your computer if you installed the Cloud SDK (which includes the gcloud command-line tool [CLI]) and initialized its use. If this is you, issue the following command to enable all three APIs: gcloud services enable geocoding-backend.googleapis.com timezone-backend.googleapis.com directions-backend.googleapis.com. Confirm which APIs you've enabled in-all with gcloud services list.

Any which way you've enabled the APIs, it's time to look at code.

Code samples

This section covers use of the three Maps APIs enabled above, the Geocoding, Time Zone, and Directions APIs. Let's start with the Geocoding API since it was previously covered in an earlier post on API keys.

Maps Geocoding API

Available in the repo, the maps_geocode.py script is the same as from the other post on API keys: it takes an address and geocodes it to a latitude-longitude ("lat/long") pair or 2-tuple:

'''
maps_geocode.py -- geocode address in Google Maps
'''
from __future__ import print_function
import googlemaps
from settings import API_KEY

ADDRESS = '1600 Amphitheatre Pkwy 94043'
GMAPS = googlemaps.Client(key=API_KEY)
res = GMAPS.geocode(ADDRESS)[0]
geo = res['geometry']['location']
print('** Geocode for %r: (%s, %s)' % (ADDRESS, geo['lat'], geo['lng']))
Enter fullscreen mode Exit fullscreen mode

The script creates an API client, passes in the API key for authorization, then calls the geocode() function with the target address. The lat/long is extracted from the payload and displayed with the origin address.

All scripts in this post are Python 2/3-compatible, meaning this code can help those on 2.x finally migrate to 3.x.

$ python3 maps_geocode.py
** Geocode for '1600 Amphitheatre Pkwy 94043': (37.4226277, -122.0841644)
Enter fullscreen mode Exit fullscreen mode

The input is an imperfect address for Google's headquarters, but Maps still has enough information to do its job and returns the lat/long as requested. I don't use it in the script above, but the API also returns a more "formal" formatted_address field that you can use if desired:

>>> res['formatted_address']
'1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA'
Enter fullscreen mode Exit fullscreen mode

As I'm also learning JavaScript, here's my attempt porting the script to Node.js:

/**
 * maps_geocode.js -- geocode address in Google Maps
 */
require('dotenv').config();
const { Client } = require("@googlemaps/google-maps-services-js");

const ADDRESS = '1600 Amphitheatre Pkwy 94043';
const GMAPS = new Client();
const args = {
  params: {
    key: process.env.API_KEY,
    address: ADDRESS,
  }
};

async function main() {
  const rsp = await GMAPS.geocode(args);
  const res = rsp.data.results[0];
  const geo = res.geometry.location;
  console.log(`** Geocode for "${ADDRESS}": (${geo.lat}, ${geo.lng})`);
}

main();
Enter fullscreen mode Exit fullscreen mode

You'll find this new script in the repo, and running it results in nearly the same output as the Python version:

$ node maps_geocode.js
** Geocode for "1600 Amphitheatre Pkwy 94043": (37.4226277, -122.0841644)
Enter fullscreen mode Exit fullscreen mode

For those who prefer a modern ECMAScript module, here's the equivalent .mjs file, which is also in the repo:

/**
 * maps_geocode.mjs -- geocode address in Google Maps
 */
import dotenv from "dotenv";
import { Client } from "@googlemaps/google-maps-services-js";

dotenv.config();
const ADDRESS = '1600 Amphitheatre Pkwy 94043';
const GMAPS = new Client();
const args = {
  params: {
    key: process.env.API_KEY,
    address: ADDRESS,
  }
};

async function main() {
  const rsp = await GMAPS.geocode(args);
  const res = rsp.data.results[0];
  const geo = res.geometry.location;
  console.log(`** Geocode for "${ADDRESS}": (${geo.lat}, ${geo.lng})`);
}

main();
Enter fullscreen mode Exit fullscreen mode

Take my word for it that its output is identical to the CommonJS version. The remaining samples are only in Python, and you can use this example to extrapolate porting the others to Node.js.

Next is the Time Zone API, which is a natural follow-up to the Geocoding API because it requires the lat/long coordinates of a location to determine its time zone.

Maps Time Zone API

The maps_tzone.py script found in the repo takes a geolocation and returns its time zone and offset from GMT/UTC:

'''
maps_tzone.py -- geocode address and get Google Maps time zone
'''
from __future__ import print_function
import googlemaps
from settings import API_KEY

ADDRESS = '1600 Amphitheatre Pkwy 94043'
GMAPS = googlemaps.Client(key=API_KEY)
rsp = GMAPS.geocode(ADDRESS)[0]['geometry']['location']
rsp = GMAPS.timezone((rsp['lat'], rsp['lng']))

offset = rsp['rawOffset'] + rsp['dstOffset']
sign = '-' if offset < 0 else '+'
offset, frac = divmod(abs(offset), 3600)
frac_str = str(round(frac/3600, 2))[1:] if frac else ''
tz_abbr = ''.join(c[0] for c in rsp['timeZoneName'].split())
print('** Time zone for %r:' % ADDRESS, rsp['timeZoneId'],
        '(%s/GMT%s%s%s)' % (tz_abbr, sign, offset, frac_str))
Enter fullscreen mode Exit fullscreen mode

This script starts with a similar recipe to maps_geocode.py, and extends it after the geocoding takes place. An additional call to timezone() passing in the resulting geocode returns several key fields:

Field Description Example
rawOffset Number of seconds away from GMT/UTC; positive if ahead of UTC, negative if behind -28800 (for GMT-8)
dstOffset Daylight saving time adjustment (in seconds) from standard GMT offset 3600 (for 1-hour DST offset)
timeZoneId IANA time zone identifier in "continent/locale" format America/Los_Angeles (for PST/GMT-8 or PDT/GMT-7)
timeZoneName Localized descriptive time zone name Pacific Daylight Time (for GMT-7)
Key fields returned by geocode() function

 

Here's the output running this script:

$ python3 maps_tzone.py
** Time zone for '1600 Amphitheatre Pkwy 94043': America/Los_Angeles (PDT/GMT-7)
Enter fullscreen mode Exit fullscreen mode

The rawOffset is combined with any possible DST adjustment (dstOffset) for the current time zone offset (in seconds) away from GMT. The sign variable tracks whether the time zone is ahead of GMT or behind. The overall offset is then split up into an hourly offset and a fractional remainder, if any -- this applies to time zones that don't start a multiple of hours away from UTC. For example, replacing the Google headquarters address with that of its Bangalore office reveals that India Standard Time isn't on an hourly boundary away from GMT; it's further offset by a half-hour:

$ python3 maps_tzone-india.py
** Time zone for '3 Old Madras Rd, Bengaluru 560016 IN': Asia/Calcutta (IST/GMT+5.5)
Enter fullscreen mode Exit fullscreen mode

For an even more interesting time zone, change the address to that of the Pashupatinath Temple, a well-known Hindu temple in Kathmandu:

$ python3 maps_tzone-nepal.py
** Time zone for 'Pashupati Nath Road, Kathmandu 44600 NP': Asia/Katmandu (NT/GMT+5.75)
Enter fullscreen mode Exit fullscreen mode

You're reading it correctly: Nepal Time is ahead of India Standard time by another 15 minutes, totaling 5.75 hours ahead of GMT, but this script (via frac & frac_str) can handle scenarios like these from south Asia. NOTE: There are no files in the repo named maps_tzone-india.py and maps_tzone-nepal.py... I merely copied maps_tzone.py to different files and changed the ADDRESS in each for illustrative purposes only. Create your own versions and try different addresses as you see fit.

Now let's move on to the final sample using the Directions API.

Maps Directions API

The Directions API returns driving (default), walking, cycling, or public transit directions to get from point A to point B. The sample below, maps_wlkdir.py, also found in the repo, calculates the walking directions, distance, and time to walk from one side of Google's main New York office building to the other side but from the outside rather than through the building itself:

'''
maps_wlkdir.py -- get Google Maps walking directions
'''
from __future__ import print_function
from datetime import datetime
import googlemaps
from html2text import html2text
from settings import API_KEY

ADDRESSES = ('111 8th Ave, New York', '76 9th Ave')
GMAPS = googlemaps.Client(key=API_KEY)
rsp = GMAPS.directions(*ADDRESSES, mode='walking',
        departure_time=datetime.now())
dirs = rsp[0]['legs'][0]

print('** Walking directions...')
print('STARTING from:', dirs['start_address'])
print('CONCLUDING at:', dirs['end_address'])
print('DISTANCE:', dirs['distance']['text'])
print('DURATION:', dirs['duration']['text'])
print('DIRECTIONS:')
for i, step in enumerate(dirs['steps']):
    print('\t%d.' % (i+1), html2text(
        step['html_instructions']).strip().replace('\n\n', '\n\t'))
Enter fullscreen mode Exit fullscreen mode

This script relies on a 3rd-party package, html2text, to convert the directions into plain text for our command-line script because they only come in HTML from the API.

The directions() function is called with the origin and destination addresses, the desired transportation mode, and the departure_time used by the API to determine the duration based on any extra traffic that may be around on that day at that time.

Running this script results in the following output:

$ python3 maps_wlkdir.py
** Walking directions...
STARTING from: 111 8th Ave, New York, NY 10011, USA
CONCLUDING at: 76 9th Ave, New York, NY 10011, USA
DISTANCE: 0.2 mi
DURATION: 4 mins
DIRECTIONS:
        1. Head **southwest** on **8th Ave** toward **W 15th St**
        2. Turn **right** onto **W 15th St**
        3. Turn **right** onto **9th Ave**
        Destination will be on the right
Enter fullscreen mode Exit fullscreen mode

Summary

Google provides a wide variety of developer tools and APIs for users to integrate their technologies programmatically. There is a definite bias towards GCP and GWS APIs on this blog because of my personal experience as a member of both of those teams during my time at Google, but Maps is another API family that deserves some attention too. This post provides a basic introduction to several of its server-side APIs to help you get your users where they need to go as well as get information about places found on Maps.

If you find yourself needing to know how to use these APIs, I hope this post helps kick off your journey into the Maps family of APIs. If you find any errors or have suggestions on content you'd like to see in future posts, be sure to leave a comment below, and if your organization needs help integrating Google technologies via its APIs, reach out to me by submitting a request at https://cyberwebconsulting.com. Lastly, below are links relevant to the content in this post for further exploration.

References

This post covered quite a bit, so there is a good amount of documentation to link you to:



WESLEY CHUN, MSCS, is a Google Developer Expert (GDE) in Google Cloud (GCP) & Google Workspace (GWS), author of Prentice Hall's bestselling "Core Python" series, co-author of "Python Web Development with Django", and has written for Linux Journal & CNET. He runs CyberWeb specializing in GCP & GWS APIs and serverless platforms, Python & App Engine migrations, and Python training & engineering. Wesley was one of the original Yahoo!Mail engineers and spent 13+ years on various Google product teams, speaking on behalf of their APIs, producing sample apps, codelabs, and videos for serverless migration and GWS developers. He holds degrees in Computer Science, Mathematics, and Music from the University of California, is a Fellow of the Python Software Foundation, and loves to travel to meet developers worldwide at conferences, user group events, and universities. Follow he/him @wescpy & his technical blog. Find this content useful? Contact CyberWeb if you may need help or buy him a coffee (or tea)!

Top comments (0)