How to Scrape Google Maps Data Easily in 2026, Tested and Verified

By Anurag Pathak··Updated ·9 min read

Every Google Maps API tutorial shows the same happy path: send a search, read the name and rating, move on. None of them show the part that decides whether your pipeline survives contact with real data — which fields actually come back, and how often.

So I ran the Serpent Google Maps API against live places in August 2026 and measured the field coverage. This guide walks the exact flow I tested: an API key, a Quick search, a place detail, and paged reviews — with cURL, Python, and Node. Then I show you the honest field rates so you can plan your schema before you write code. If you want the field-by-field audit first, the place details post covers what survives the public place view.

1. Get an API Key

Create an account, then copy a sk_live_... key from the API keys page. There is no Google Cloud project, no billing account, and no Google credential to rotate. You send the key in a header on every request:

X-API-Key: sk_live_your_api_key

Every new account gets a shared 10-call free pool usable across all four Maps endpoints plus every other endpoint — enough to run this whole guide without paying. The playground has a Maps tab with country and language dropdowns if you want to try requests in the browser first.

2. Quick Search

Search returns up to 20 ranked places. The only required parameter is q; add location and country to scope the ranking.

curl --get "https://apiserpent.com/api/maps/search/quick" \
  -H "X-API-Key: sk_live_your_api_key" \
  --data-urlencode "q=coffee shop" \
  --data-urlencode "location=Austin, TX" \
  --data-urlencode "country=us"
import requests

r = requests.get(
    "https://apiserpent.com/api/maps/search/quick",
    params={"q": "coffee shop", "location": "Austin, TX", "country": "us"},
    headers={"X-API-Key": "sk_live_your_api_key"},
    timeout=60,
)
data = r.json()
for place in data["results"]["places"]:
    print(place["name"], "|", place["rating"], "|", place["address"]["formatted"])
const res = await fetch(
  "https://apiserpent.com/api/maps/search/quick?q=coffee+shop&location=Austin%2C+TX&country=us",
  { headers: { "X-API-Key": "sk_live_your_api_key" } }
);
const data = await res.json();
for (const p of data.results.places) {
  console.log(p.name, p.rating, p.address.formatted);
}

The response carries the richest fields available per place — name, rating, address, phone, website, coordinates, categories, hours, and a canonical maps_url. Each result also includes a detail_status: complete when full enrichment finished, or core_only when only the ranked core record was returned within the request deadline.

3. What Fields Actually Come Back

Here is the part the tutorials skip. Across 97 complete place records fetched in the August 2026 hardening run, the reliably-achievable fields measured like this:

FieldPresent on complete recordsNotes
business_status100%Always present on complete records
opening_hours100%Always present
images100%Always present
rating100%Always present
plus_code100%Always present
amenities96%Nearly always
website92%Missing on roughly 1 in 12
phone70%Missing on roughly 1 in 3

Rates from 97 complete places, August 2026. Floors from the live test suite: ~0.9 reliably-achievable fields, website 0.8, phone 0.6. Field coverage is per-place and changes; treat this as a dated measurement.

Phone is the one that surprises most teams — roughly a third of businesses simply do not expose one on their public place view. Plan your schema around null rather than assuming contact data, and you will never ship a bug that fabricates a missing value. For the pricing side of that same dataset, see the Maps pricing comparison.

4. Get a Place Detail

Each search result includes place_id and data_id. Pass either to the Place endpoint to fetch a single rich record:

curl --get "https://apiserpent.com/api/maps/place" \
  -H "X-API-Key: sk_live_your_api_key" \
  --data-urlencode "place_id=ChIJ..."
{
  "success": true,
  "place": {
    "place_id": "ChIJ...",
    "data_id": "0x...:0x...",
    "maps_url": "https://www.google.com/maps/place/...",
    "name": "Sample Coffee",
    "categories": ["Coffee shop", "Cafe"],
    "address": { "street": "...", "city": "Austin", "state": "TX", "postal_code": "78701", "country": "US", "formatted": "..." },
    "coordinates": { "latitude": 30.2672, "longitude": -97.7431 },
    "rating": 4.7,
    "opening_hours": { "hours": { "Monday": ["7:00 AM - 6:00 PM"] }, "is_open_now": true },
    "phone": "...",
    "website": "https://...",
    "business_status": "Open",
    "detail_status": "complete"
  }
}

The place record has up to 23 documented fields — identifiers, categories, structured address, coordinates, contact fields, rating, hours, status, amenities, links, ownership, and images. In a four-business audit, 12 of 15 standard fields were present on every record: place_id, data_id, maps_url, name, phone, website, rating, review_count, opening_hours, timezone, cover_image, and image_count. The absent ones were description, business_status, and price_range. Fields Google does not expose come back null: the honest-null contract, never fabricated data.

5. Reviews with Pagination

The Reviews endpoint returns up to 20 reviews per page. Sort with sort=relevant|newest|highest|lowest, and continue with the opaque next_page_token:

curl --get "https://apiserpent.com/api/maps/reviews" \
  -H "X-API-Key: sk_live_your_api_key" \
  --data-urlencode "place_id=ChIJ..." \
  --data-urlencode "sort=newest"
import requests

place_id = "ChIJ..."
url = "https://apiserpent.com/api/maps/reviews"
headers = {"X-API-Key": "sk_live_your_api_key"}
next_token = None
seen = set()

while True:
    params = {"place_id": place_id, "sort": "newest"}
    if next_token:
        params["next_page_token"] = next_token
    data = requests.get(url, params=params, headers=headers, timeout=60).json()
    for review in data["results"]["reviews"]:
        if review["review_id"] not in seen:
            seen.add(review["review_id"])
            print(review["rating"], "|", review["relative_date"], "|", review["text"]["original"][:80])
    next_token = data.get("next_page_token")
    if not next_token:
        break

Tokens are bound to the place and sort order and expire after 15 minutes, so page through promptly. In a two-business probe, the first business returned 20 reviews with a next token and owner replies on 19 of 20; the second returned 20 reviews with zero overlapping review IDs across pages — the pagination is duplicate-free by review_id. A full Python guide, including dedupe and the signed-out view gotcha (absolute timestamps come back null, so relative_date is the working field), is in Google Maps Reviews API in Python.

6. More Than 20 Places

Two options to widen the result set:

Country and language are two-letter codes (us, gb, de, jp; en, fr, ja, ...). Non-US markets work: in the August run, gb/de/jp each returned a full 20 of 20 places. You can also search by lat/lng coordinates, and zoom (3–21, default 14) tunes the map extent. Parallel quick searches are safe — 4 of 4 ran concurrently without a drop, and cached quick responses came back in 30–37ms.

Honest Field Limits

Because the API returns the public place view, a few fields are not guaranteed on every record. The pre-fix deep run is the cautionary tale: popular_times was missing on 89% of places, price_range on 89%, images on 88%, and review_count on 85%. All of those gaps were closed in the 2026-08-05 hardening sprint, but the lesson stands: field availability is dated and per-place. The contract is explicit — missing fields come back null rather than being invented. Plan your schema around that and the data stays trustworthy. The full 23-field place table and 9-field review table are in the API reference.

Start with 10 Free Maps Queries

Serpent's Google Maps API returns ranked places with website, phone, and hours in one JSON call — and every new account gets 10 free calls, no credit card. Enough to run this whole guide end-to-end, then pay from $0.75 per 1,000 places on Deep searches.

Get Your Free API Key

Explore: Maps API · Pricing · Playground

FAQ

Do I need a Google Cloud API key to use this API?

No. You use a Serpent API key (sk_live_...) in the X-API-Key header. You never provision Google Cloud services or manage Google billing.

How do I page through more than 20 places?

Use the Deep endpoint for up to 100 places, or pass start=20/40/60/80 on Quick to offset into the ranked list.

Which fields are guaranteed to come back?

In a 97-place sample, business status, opening hours, images, rating, and plus code appeared on 100% of complete records. Amenities hit 96%, website 92%, and phone 70%.

Are all place fields always present?

No. Fields like price_range, popular_times, and review_count are null when not available for a place. Absence is honest, never fabricated.

How do reviews paginate?

The Reviews endpoint returns up to 20 per page with an opaque next_page_token. Tokens are bound to the place and sort order and expire after 15 minutes.

Do I get owner replies to reviews?

Yes, when they exist. In an August 2026 two-business probe, 19 of 20 reviews on the first business included an owner response.

References & Further Reading

Related Posts