Google Maps scraper API and MCP
A Google Maps scraper API runs a bounded business search from your app or an agent. One scoped workspace key, an explicit task budget and a stable idempotency key cover each retry. Results are JSON, and a missing field stays empty.
Before you run · Live research requires a configured data source. Sample data is clearly labeled. Paid plans are not available yet.

Create a bounded job
Connect a scoped workspace key to REST or an HTTP MCP client. Estimate tasks, set explicit budgets and retrieve structured results.
curl -X POST https://mapsscraper.dev/api/v1/jobs \
-H "Authorization: Bearer $MAPSSCRAPER_API_KEY" \
-H "Idempotency-Key: dentists-austin-tx-001" \
-H "X-Max-Units: 1" \
-H "Content-Type: application/json" \
-d '{"kind":"search","query":"Dentists in Austin, TX","limit":20,"region":"us"}'
HTTP/1.1 202 Accepted
{"id":"6f1c2b3a-0000-4000-8000-000000000000","status":"queued","reserved":1}Retry the same business operation using the same idempotency key. A changed request with that key returns 409. Jobs progress through queued, running, completed, partial, failed, cancelled or uncertain. An uncertain data source request requires reconciliation instead of an automatic paid replay.
What is a Google Maps scraper API?
A Google Maps scraper API accepts a category and an area, returns public listings as JSON, and shows the maximum task budget before the request runs. Each task uses a scoped key and an idempotency key. Reviews are a separate request.
Read the results
Completed and partial jobs keep their results for your workspace retention period. Read them page by page with offset and limit; reading stored results never runs new research.
Sample response, shortened. Values are illustrative, not real business data.
{
"items": [
{
"business_id": "sample-business-id",
"name": "Sample Dental Studio",
"full_address": "100 Example Ave, Austin, TX 78701",
"phone_number": "+1 512-555-0100",
"website": "https://dental.example",
"type": "Dentist",
"rating": 4.8,
"review_count": 214,
"latitude": 30.2672,
"longitude": -97.7431,
"_source": {
"provider": "live_maps",
"fetched_at": "2026-11-01T12:00:00Z",
"website_status": "provided_unverified"
}
}
],
"count": 1,
"offset": 0,
"next_offset": null,
"provider": "live_maps",
"coverage": "bounded_sample",
"fetched_at": "2026-11-01T12:00:00Z"
}Google Maps reviews API
Request reviews for one business ID per task, up to 100 per page, sorted by relevance, newest, highest or lowest rating. Each review includes its text, rating, date, author and any owner response when available. A further page needs its own task and budget.
Reviews scraperPOST /api/v1/jobs
Idempotency-Key: reviews-sample-business-001
X-Max-Units: 1
{"kind":"reviews","business_id":"sample-business-id","limit":50,"review_options":{"sort_by":"newest"}}Python example
Call the Google Maps scraper API from Python: estimate a search, create the job, wait for a final status and read the results with the requests library.
import os
import time
import uuid
import requests
API = "https://mapsscraper.dev/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['MAPSSCRAPER_API_KEY']}"}
task = {"kind": "search", "query": "Dentists in Austin, TX", "limit": 20, "region": "us"}
# An estimate reserves nothing.
units = requests.post(f"{API}/estimate", json=task, headers=HEADERS, timeout=30).json()["units"]
# Keep the key: a retry of the same task must send it again.
key = str(uuid.uuid4())
job = requests.post(
f"{API}/jobs",
json=task,
headers={**HEADERS, "Idempotency-Key": key, "X-Max-Units": str(units)},
timeout=30,
)
job.raise_for_status()
job_id = job.json()["id"]
while True:
status = requests.get(f"{API}/jobs/{job_id}", headers=HEADERS, timeout=30).json()["status"]
if status not in ("queued", "running"):
break
time.sleep(5)
if status in ("completed", "partial"):
page = requests.get(
f"{API}/jobs/{job_id}/results",
params={"offset": 0, "limit": 100},
headers=HEADERS,
timeout=30,
).json()
for business in page["items"]: # follow page["next_offset"] for more
print(business.get("name"), business.get("phone_number"), business.get("website"))Google Maps scraper API questions
DocumentationIs this the Google Places API?
No. MapsScraper.dev is an independent service and is not affiliated with Google. Results come from a third-party business data source and use our own JSON format.
How are requests charged?
Most tasks use one unit. Contact enrichment on a search or rank snapshot reserves one more unit per requested record and charges only for records delivered. Business details use one unit, or two with contacts; enrichment uses two. Set X-Max-Units to at least the estimate.
Are emails and phone numbers guaranteed?
No. Coverage depends on the source and business. Optional enrichment may return public contact details, but missing or stale data should be checked before use.
Resources
Your next list starts with a place.
Explore the workflow with labeled sample records, then connect your workspace for live research.
Explore a sample