How to scrape Google Maps results with Python
Get places, ratings, review counts and contact details from Google Maps as JSON, why the official Places API gets expensive, and what a Maps search actually costs. With a tested example, August 2026.

You want the businesses Google Maps shows for a query: names, ratings, review counts, addresses, phone numbers, websites. This post covers the three ways to get them, with real numbers for what each one costs, and a Python example that we ran before publishing.
Why not the official Places API?
The official route exists and is the right answer for some products, but three properties surprise people at the point where it is too late to change course:
- Price. Text Search on the Places API costs $32.00 per 1,000 requests on the Pro tier, checked on Google’s pricing page on 20 October 2026, with 5,000 free calls a month. The unit price only starts dropping meaningfully past 100,000 monthly requests.
- Result caps. A Text Search returns at most 60 places over three pages. For “restaurants in a city” style queries the map interface knows far more than the API will give you.
- Licensing. Places data comes with restrictions on storing and displaying it. If your use case is building a lead list or a dataset, the terms are the real constraint, not the code.
The DIY alternative, driving a headless browser over the Maps interface, breaks for the same reasons scraping Google Search breaks: IP blocks, rotating obfuscated markup, and a scroll-to-load results panel that needs a real browser session per query. It is a maintenance project, not a script.
The version that works
Send the query to an API that owns the browsers and the parsing, and get JSON back:
import requests
API_KEY = "faf_live_..." # your FastAF key
resp = requests.get(
"https://api.fastaf.co/v1/maps",
params={
"query": "best pizza in Naples Italy",
"page": 0,
},
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=60,
)
resp.raise_for_status()
for place in resp.json()["search_results"]:
print(f'{place["rating"]} ({place["reviews"]:>6}) {place["title"]}')
We ran exactly this request while writing this post (August 2026). It returned 20 places for 5 credits, the first being L’Antica Pizzeria da Michele: rating 4.3, 54,724 reviews, price range, address, phone number, website, opening state and GPS coordinates, all as plain JSON fields. No browser, no proxies, no parsing.
What fields do you get per place?
Each entry in search_results carries the business data the Maps panel shows:
| Field | Example from our test run |
|---|---|
title |
L’Antica Pizzeria da Michele |
rating / reviews |
4.3 / 54724 |
type, types |
Pizza restaurant, Italian restaurant, … |
price |
€1–10 |
address |
Via Cesare Sersale, 1, 80139 Napoli NA, Italy |
phone |
+39 392 … |
website |
the business’s own site |
open_state |
Closed · Opens 10:30 AM |
gps_coordinates |
latitude / longitude |
place_id, data_id |
stable identifiers for follow-up lookups |
Two parameters worth knowing beyond query: ll pins the search to coordinates and zoom (@40.85,14.26,14z) so you control the map viewport instead of letting the query text guess it, and page moves through result pages, roughly 20 places at a time, past the official API’s 60-place ceiling.
What does a Maps search cost?
A Google Maps search on FastAF costs 5 credits, the same as a Google Search request. On the Scale pack ($99 for 300,000 credits) that is 60,000 Maps searches, or $1.65 per 1,000. The same 60,000 searches on the official Places API Text Search at $32.00 per 1,000 come to $1,760 (55,000 billed after the 5,000 free calls of the month), and return at most 60 places each.
The free tier is 500 credits with no card, which is 100 Maps searches, enough to check field coverage on your actual queries before deciding anything. Failed requests are never billed: credits are reserved when a request starts and returned if it does not come back with a result.
Lead lists: the practical loop
The most common use of this endpoint is local lead generation. The loop is: search a category in a city, filter on the fields, and you have a qualified list in minutes:
def places(query, pages=3):
for page in range(pages):
resp = requests.get(
"https://api.fastaf.co/v1/maps",
params={"query": query, "page": page},
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=60,
)
resp.raise_for_status()
yield from resp.json()["search_results"]
# Businesses with real traction but no website: classic web-agency prospects.
leads = [
p for p in places("dentist in Austin TX")
if p.get("reviews", 0) > 50 and not p.get("website")
]
Three pages of one query is 15 credits. A 50-city sweep of the same category at three pages each is 750 credits, about $0.29 on the Growth pack: the follow-up emails will cost you more than the data.