gmaps-async-client
Async Python client for Google Maps APIs (Places & Geocoding) with httpx and Pydantic.
Problem: Need async Google Places (New) and Geocoding API access with proper typing, rate limiting, and flexible configuration. Solution: Unified client with Places (nearby/text search, details, autocomplete) and Geocoding APIs, HTTP/2 support, and centralized settings.
Note
This is a work-in-progress. Response models are not yet implemented, and not all routes are implemented. Feel free to contribute!
Installation
# Basic
pip install gmaps-async-client
# With Google ADC auth support
pip install gmaps-async-client[google]
Quick Start
from gmaps import GmapsClient
async def main():
async with GmapsClient() as client:
# Places API - search nearby
response = await client.places.nearby_search_simple(
latitude=37.7749, longitude=-122.4194, radius=1000
)
# Places API - text search
response = await client.places.text_search_simple(
query="coffee shops in San Francisco"
)
# Geocoding API - address to coords
response = await client.geocoding.geocode_simple(
address="1600 Amphitheatre Parkway, Mountain View, CA"
)
# Geocoding API - place ID to address
response = await client.geocoding.place_geocode_simple(
place_id="ChIJd8BlQ2BZwokRAFUEcm_qrcA"
)
# Parse responses
data = response.json()
print(data)
import asyncio
asyncio.run(main())
Authentication
Auth priority: API key (param/env) → Google ADC → error
# Option 1: Environment variable
export GOOGLE_PLACES_API_KEY="your-key"
# Option 2: Google ADC (requires gmaps[google])
gcloud auth application-default login
# Explicit API key
client = GmapsClient(api_key="your-key")
# Force ADC mode
client = GmapsClient(auth_mode=AuthMode.ADC)
Configuration
Basic Configuration
from gmaps import GmapsClient, ClientOptions, RetryConfig
import httpx
options = ClientOptions(
timeout=httpx.Timeout(30.0),
retry=RetryConfig(max_attempts=3),
enable_logging=True
)
client = GmapsClient(
options=options,
places_qpm=100, # Places API rate limit
geocoding_qpm=50 # Geocoding API rate limit
)
Environment Variables
Centralized configuration via environment variables (prefix: GMAPS_):
GMAPS_GOOGLE_PLACES_API_KEY - The Google Places API key. Also accepts GOOGLE_PLACES_API_KEY as an alias.
GMAPS_STRICT_PLACE_TYPE_VALIDATION - Whether to strictly validate place types against the types in Table A. Possible values: true or false. Default is true.
Custom Type Registration
Register custom place types, components, or extra computations. Useful if the API changes and the SDK is not updated yet.
from gmaps import register_custom, get_custom, clear_custom_registries
# Register custom place types
register_custom("place_types", "custom_restaurant", "special_shop")
# Register custom geocoding components
register_custom("components", "custom_area", "special_zone")
# Register custom extra computations
register_custom("extra_computations", "CUSTOM_COMPUTATION", "SPECIAL_FEATURE")
# View registered values
print(get_custom("place_types")) # {'custom_restaurant', 'special_shop'}
print(get_custom("components")) # {'custom_area', 'special_zone'}
# Clear
clear_custom_registries()
API Methods
Places API
# Nearby search
response = await client.places.nearby_search_simple(
latitude=37.7749, longitude=-122.4194, radius=1000,
included_types=["restaurant"], max_results=10
)
# Text search
response = await client.places.text_search_simple(
query="pizza restaurants", max_results=10
)
# Place details
response = await client.places.place_details_simple(
place_id="ChIJN1t_tDeuEmsRUsoyG83frY4",
session_token="your-session-token" # Optional for billing optimization
)
# Autocomplete
response = await client.places.autocomplete_simple(
input_text="coffee shop",
included_primary_types=["cafe"],
session_token="your-session-token", # Optional for billing optimization
field_mask=["suggestions.placePrediction.text.text"] # Control returned fields
)
Geocoding API
# Address to coordinates
response = await client.geocoding.geocode_simple(
address="1600 Amphitheatre Parkway, Mountain View, CA"
)
# Place ID to address (place geocoding)
response = await client.geocoding.place_geocode_simple(
place_id="ChIJd8BlQ2BZwokRAFUEcm_qrcA",
language="en",
region="us"
)
Advanced Usage
from gmaps import (
GmapsClient, NearbySearchRequest, Circle, LatLng,
LocationRestriction, GeocodingRequest
)
# Full request objects for complex queries
request = NearbySearchRequest(
location_restriction=LocationRestriction(
circle=Circle(
center=LatLng(latitude=37.7749, longitude=-122.4194),
radius=1500.0
)
),
included_types=["restaurant"],
max_result_count=20
)
response = await client.places.nearby_search(
request=request,
field_mask=["places.displayName", "places.rating"]
)
Response Handling
response = await client.places.text_search_simple(query="pizza")
data = response.json()
# Places API responses
for place in data.get("places", []):
name = place.get("displayName", {}).get("text")
address = place.get("formattedAddress")
rating = place.get("rating")
# Geocoding API responses
for result in data.get("results", []):
coords = result["geometry"]["location"]
lat, lng = coords["lat"], coords["lng"]
Field Masks: Control returned data for performance
field_mask = ["places.displayName", "places.location"]
Error Handling
import httpx
from gmaps import GmapsClient
async with GmapsClient() as client:
try:
response = await client.places.text_search_simple(query="restaurants")
data = response.json()
except httpx.HTTPStatusError as e:
print(f"HTTP {e.response.status_code}: {e.response.text}")
except httpx.RequestError as e:
print(f"Network error: {e}")
Available Models
All models can be imported directly from gmaps:
from gmaps import (
# Clients
GmapsClient, PlacesClient, GeocodingClient,
# Configuration
ClientOptions, RateLimitConfig, AuthMode, RetryConfig,
# Request models
NearbySearchRequest, TextSearchRequest, DetailsRequest,
AutocompleteRequest, GeocodingRequest,
# Location models
LatLng, Circle, LocationRestriction, LocationBias, Viewport,
# Component models
ComponentFilter, Component,
# Enums
RankPreference, PriceLevel, EVConnectorType, ExtraComputations,
# Custom registration hooks
register_custom, get_custom, clear_custom_registries, CustomField
)
Requirements
- Python 3.9+
- httpx >= 0.25.0
- pydantic >= 2.0.0
- pydantic-settings >= 2.0.0
- h2 >= 4.3.0 (for HTTP/2)
- google-auth (for ADC)
Links
Metadata
Release files for gmaps-async-client 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gmaps_async_client-1.0.1.tar.gz | 61.1 kB | Without provenance | Details for gmaps_async_client-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gmaps_async_client-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for gmaps_async_client-1.0.1-py3-none-any.whl |
Total release size: 94.9 kB
Release files / gmaps_async_client-1.0.1.tar.gz
| Download URL | gmaps_async_client-1.0.1.tar.gz |
|---|---|
| Size | 61.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
28f49c12f53884eb5d6766603ff01f1b9e6e1b6ac88cefaf64df001dafe3fec4
|
|
BLAKE2b-256 checksum How to use checksums |
72071ed63a82d30a129606b5dae9593100f01d2fb044ca871b9ac3ac150e3eb6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Release files / gmaps_async_client-1.0.1-py3-none-any.whl
| Download URL | gmaps_async_client-1.0.1-py3-none-any.whl |
|---|---|
| Size | 33.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f9dc897376cdfb42e340071660f152d6a3befaa38383f5497b196a1f25f13d98
|
|
BLAKE2b-256 checksum How to use checksums |
04e8394198bc97f175b39638734689b2cf8b8c5367b8e797183258959ecd7a07
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Security for gmaps-async-client 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.