ScreenshotNeo

BlogHow-to

How to Use the Google Maps API in Python

Learn to geocode addresses, calculate routes, search places, and secure Google Maps API calls in Python with runnable examples.

By the ScreenshotNeo team1 October 20268 min read

Short answer: use Google’s community-supported googlemaps Python client or call the Maps Web Services over HTTPS. You need a Google Cloud project with billing enabled, the specific Maps APIs enabled, and a restricted API key kept on your server.

This guide shows setup, geocoding, reverse geocoding, directions, distance matrices, Places, address validation, error handling, retries, quotas, security, and production patterns.

1. What you need before writing Python code

  1. Create or select a project in Google Cloud Console.
  2. Attach a billing account. Google requires billing and a valid key for Maps Platform products.
  3. Enable only the APIs your application needs, such as Geocoding, Directions, Places, or Address Validation.
  4. Create an API key under APIs & Services > Credentials.
  5. Restrict the key by API and application where possible. A server-side Python service normally uses server-side restrictions.
  6. Store the key in an environment variable or secret manager.

Every Maps Web Service request needs an API key or client ID. Keep the key out of source control, browser bundles, logs, and error pages. If it is exposed, rotate it immediately and review usage.

2. Install the Python client

python -m pip install -U googlemaps

The googlemaps package brings Maps Web Services to Python, including geocoding, reverse geocoding, directions, distance matrices, Places, elevation, roads, time zone, geolocation, static maps, and address validation. It is community-supported, so pin the version you deploy and monitor release notes and current Google API documentation.

3. Configure the API key safely

export GOOGLE_MAPS_API_KEY='your-key-here'
import os
import googlemaps

api_key = os.environ['GOOGLE_MAPS_API_KEY']
gmaps = googlemaps.Client(key=api_key)

In production, inject the variable through your deployment platform or secret manager. Do not put it in a committed .env file unless that file is excluded and managed securely.

4. Geocode an address

Geocoding converts a street address into one or more results containing coordinates, formatted addresses, and address components.

import os
import googlemaps

address = '1600 Amphitheatre Parkway, Mountain View, CA'
gmaps = googlemaps.Client(key=os.environ['GOOGLE_MAPS_API_KEY'])

results = gmaps.geocode(address)
if not results:
    raise LookupError('No geocoding result')

first = results[0]
location = first['geometry']['location']
print(first['formatted_address'])
print(location['lat'], location['lng'])

Do not assume the first result is always the one you want. Inspect address_components, types, viewport, and the formatted address before storing or displaying it.

5. Reverse geocode coordinates

import os
import googlemaps

gmaps = googlemaps.Client(key=os.environ['GOOGLE_MAPS_API_KEY'])
results = gmaps.reverse_geocode((37.4221, -122.0841))

for result in results:
    print(result['formatted_address'], result.get('types', []))

Coordinates can map to several levels, such as a premise, street, locality, or country. Select the result type your application requires instead of relying on list position.

6. Get driving, walking, bicycling, or transit directions

import os
from datetime import datetime, timezone
import googlemaps

gmaps = googlemaps.Client(key=os.environ['GOOGLE_MAPS_API_KEY'])

routes = gmaps.directions(
    'Sydney Town Hall',
    'Parramatta, NSW',
    mode='transit',
    departure_time=datetime.now(timezone.utc),
)

for route in routes:
    leg = route['legs'][0]
    print(leg['start_address'], 'to', leg['end_address'])
    print(leg['distance']['text'], leg['duration']['text'])

Use mode='driving', 'walking', 'bicycling', or 'transit'. Transit requests need an appropriate departure or arrival time. A response can contain multiple routes and multiple legs, so do not hard-code a single route shape beyond checking the schema.

7. Compare many origins and destinations with Distance Matrix

import os
import googlemaps

gmaps = googlemaps.Client(key=os.environ['GOOGLE_MAPS_API_KEY'])
response = gmaps.distance_matrix(
    origins=['New York, NY', 'Boston, MA'],
    destinations=['Philadelphia, PA', 'Washington, DC'],
    mode='driving',
)

for row in response['rows']:
    for element in row['elements']:
        print(element['status'], element.get('distance'), element.get('duration'))

The result is a matrix: each row corresponds to an origin and each element to a destination. Check each element’s status; one failed pair does not necessarily invalidate the entire response.

8. Search Places and control returned fields

Places requests can search for or retrieve place information. For Places API (New), use a field mask and request only the fields you need. This can reduce latency and usage charged for the request.

import os
import googlemaps

gmaps = googlemaps.Client(key=os.environ['GOOGLE_MAPS_API_KEY'])
results = gmaps.places('coffee near Mountain View, CA')

for place in results.get('results', []):
    print(place.get('name'), place.get('formatted_address'))

Check the current Places API reference for the exact endpoint, request body, field-mask syntax, and enabled service. Google has both current and legacy service shapes; do not copy an older example without checking its API version.

9. Address validation and specialized services

Use Address Validation where supported when you need to validate postal addresses rather than merely find a likely geocode. The Python client also exposes elevation, roads, time zone, geolocation, and Maps Static functionality. Enable each service separately and follow its current request schema.

10. Direct HTTPS requests with cURL

The client library is convenient, but direct HTTPS gives you explicit control over URLs, timeouts, retries, and logging. A simple geocoding request looks like this:

curl --get 'https://maps.googleapis.com/maps/api/geocode/json' \
  --data-urlencode 'address=1600 Amphitheatre Parkway, Mountain View, CA' \
  --data-urlencode 'key=YOUR_API_KEY'

Use the endpoint and parameters documented for the specific Maps service you enabled. Never place a production key in a public shell history, script repository, or client-side application.

11. Direct HTTPS requests with Python

import os
import requests

params = {
    'address': '1600 Amphitheatre Parkway, Mountain View, CA',
    'key': os.environ['GOOGLE_MAPS_API_KEY'],
}
response = requests.get(
    'https://maps.googleapis.com/maps/api/geocode/json',
    params=params,
    timeout=10,
)
response.raise_for_status()
data = response.json()
if data.get('status') != 'OK':
    raise RuntimeError(data)
print(data['results'][0]['formatted_address'])

Direct requests make it your responsibility to validate HTTP status, the API’s JSON status, response shape, timeouts, and retry behavior.

12. Calling the API from Node.js

const key = process.env.GOOGLE_MAPS_API_KEY;
const params = new URLSearchParams({
  address: '1600 Amphitheatre Parkway, Mountain View, CA',
  key,
});

const response = await fetch(
  `https://maps.googleapis.com/maps/api/geocode/json?${params}`,
  { signal: AbortSignal.timeout(10000) }
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (data.status !== 'OK') throw new Error(JSON.stringify(data));
console.log(data.results[0].formatted_address);

13. Timeouts, retries, and response validation

  • Set a finite timeout on every request.
  • Retry only transient network failures and service-over-limit responses, using exponential backoff with jitter.
  • Do not blindly retry invalid keys, disabled APIs, malformed requests, or denied requests.
  • Validate both the HTTP status and the service-level status in the JSON body.
  • Record request type, latency, status, and quota errors without logging the API key or sensitive addresses.
  • Cache stable geocoding or place results when your product’s data policy permits it.
import random
import time
import requests

RETRYABLE = {429, 500, 502, 503, 504}

def get_json(url, params, attempts=4):
    for attempt in range(attempts):
        try:
            response = requests.get(url, params=params, timeout=10)
            if response.status_code not in RETRYABLE:
                response.raise_for_status()
                return response.json()
        except requests.RequestException:
            if attempt == attempts - 1:
                raise
        time.sleep((2 ** attempt) + random.random())
    raise RuntimeError('Request failed after retries')

14. Billing, quotas, and cost control

Google Maps Platform requires a billing account. Usage limits are generally expressed as queries per minute, although some products use other units. Configure project quotas, alerts, and monitoring in Cloud Console. Pricing, credits, and service limits can change, so consult Google’s current pricing page before publishing an estimate.

Control Why it matters
Enable only required APIs Reduces accidental usage and limits key exposure.
Set quotas and alerts Detects unexpected traffic and runaway jobs.
Use Places field masks Requests only the fields needed and can reduce latency and usage.
Cache eligible results Avoids repeating identical lookups where permitted.

15. Security checklist

  • Keep the key server-side in an environment variable or secret manager.
  • Apply API and application restrictions.
  • Use separate keys for development, staging, and production.
  • Rotate keys after exposure and review Cloud Console usage.
  • Redact keys and personal location data from logs.
  • Review IAM permissions and quota alerts regularly.

16. Common errors and fixes

Error or symptom Likely cause Fix
REQUEST_DENIED API is disabled, key is invalid, or restrictions reject the request. Enable the API, verify the key, and adjust restrictions for the server.
OVER_QUERY_LIMIT or HTTP 429 Quota or rate limit reached. Inspect quotas, reduce concurrency, add backoff, and request a limit review if appropriate.
Empty results Ambiguous or unsupported address/query. Normalize input, include region or bounds where supported, and handle no-match results.
Missing Places fields Field mask omitted a required field. Add only the needed field to the mask and verify the current Places API schema.
Timeouts Network delay, overloaded worker, or an overly short timeout. Set a finite but realistic timeout, retry transient failures, and measure latency.
Key appears in repository Secret was committed or logged. Revoke and replace it, remove it from history where necessary, and move it to secret storage.

17. Performance and reliability guidance

Batch independent work carefully, respect service quotas, and avoid unbounded concurrency. Use field masks for Places, cache repeatable lookups, and keep network timeouts explicit. Pin the community client dependency, test response parsing against the current API documentation, and monitor release notes because the library is not covered by Google’s standard deprecation policy or support agreement.

18. Or skip the browser setup

If your real goal is to capture a rendered map or any website page as an image or PDF, ScreenshotNeo provides a single GET request. See the ScreenshotNeo API documentation for all options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

19. FAQ

Do I need a credit card?

You need a billing account for Google Maps Platform. Google pricing and credits change, so check the current billing documentation for your project.

Is the Python client official?

googlemaps is a community-supported client library. The underlying Maps Platform services are Google’s products, but dependency maintenance remains your responsibility.

Can I expose the key in a desktop or browser app?

Keep server-side keys private. Use a backend service that makes the Web Service request and returns only the data your client needs.

Which API should I enable first?

Enable the service matching the data type: Geocoding for addresses, Directions for routes, Distance Matrix for many origin-destination comparisons, Places for place search and details, and Address Validation for postal-address checks.

How do I avoid paying for unnecessary Places data?

For Places API (New), use a field mask containing only the fields your feature needs, then monitor usage and latency.