Appearance
Google Maps API
Two endpoints for local data from Google Maps. Search sends a query and an area and returns one page of places with their ids, address, rating, review count, category, phone, website, coordinates, open state, opening hours and photo. Place looks one place up by its place_id, data_id, cid or Maps URL and adds the description, the address split into parts, the Plus Code, the booking link, the photo count, the review count per star, review quotes and topics, the hours of its services, attributes, photos and the top reviews Google shows. Reviews returns the reviews of one place in the order you choose - most relevant, newest, highest or lowest rating first - optionally only those that mention a keyword, each with its text and translation, likes, photos, visit details, owner response and reviewer. Requests leave from a residential exit in the market country you pick, so names, categories and hours are localized like a local visitor sees them. No proxies, browsers, CAPTCHAs or parser maintenance on your side.
| Product | Type | Product code | What it does |
|---|---|---|---|
| Google Maps Search API | Scraper API (synchronous) | google_maps_search | One page of twenty places for a query and area. |
| Google Maps Place API | Scraper API (synchronous) | google_maps_place | One place with hours, attributes, photos and top reviews. |
| Google Maps Reviews API | Scraper API (synchronous) | google_maps_reviews | Reviews of one place by order and keyword. |
Every field is snake_case, the same convention as the Web Scraping API.
What people build with it
| Use case | What you pull |
|---|---|
| Lead generation | Businesses of a category in a city, with phone, website and address. |
| Local SEO and rank checks | Which places Google Maps lists first for a query around a point. |
| Market and location research | Density, ratings and opening hours of competitors in an area. |
| Reputation monitoring | Rating, review count and the latest top reviews of your own locations. |
| Directory and data enrichment | Coordinates, categories and contact details for places you already know. |
Search places
GET https://api.scrapeit.io/api/v1/scrape/google/maps/search
x-api-key: YOUR_SCRAPEIT_API_KEYSearch parameters
| Parameter | Type | Example | Description |
|---|---|---|---|
q | string | coffee shops | Required. What to search for, e.g. coffee shops, dentist, pizza (up to 2048 characters). |
location | string | Austin, TX | A city, region or address to search in: Austin, TX, Berlin, 10 Downing St, London. Added to the query, exactly as Google reads coffee shops Austin TX. |
ll | string | @30.2672,-97.7431,14z | Map centre and zoom as in a Google Maps URL: @lat,lng,zoomz, e.g. @40.7455,-74.0083,14z (zoom 1–21, defaults to 14). Places are ranked around it. |
gl | string | us | Market country, two-letter ISO code (us, de, gb, fr…); Google's own uk works as gb. The request runs from an exit in this country; a country ScrapeIt has no exit in answers 422 PROXY_PROVIDER_NOT_FOUND and is not charged. Defaults to us. |
hl | string | en | Interface language (en, de, fr, pt-BR…). Defaults to en. |
page | number | 2 | Results page, 1–6. Google Maps serves twenty places per page and stops listing a query at about 120. Defaults to 1. |
Send location, ll or both. Without either, Google picks the area itself - usually somewhere in the gl country - so results are not stable from one request to the next. An unknown parameter is rejected with VALIDATION_ERROR.
Example search
Coffee shops around downtown Austin:
bash
curl -G 'https://api.scrapeit.io/api/v1/scrape/google/maps/search' \
-H 'x-api-key: YOUR_SCRAPEIT_API_KEY' \
--data-urlencode 'q=coffee shops' \
--data-urlencode 'll=@30.2672,-97.7431,14z' \
--data-urlencode 'gl=us' \
--data-urlencode 'hl=en'js
const response = await fetch(
'https://api.scrapeit.io/api/v1/scrape/google/maps/search?' +
new URLSearchParams({ q: 'coffee shops', ll: '@30.2672,-97.7431,14z', gl: 'us', hl: 'en' }),
{ headers: { 'x-api-key': 'YOUR_SCRAPEIT_API_KEY' } },
);
const { data } = await response.json();
for (const place of data.local_results) {
console.log(place.position, place.title, place.rating, place.phone);
}python
import requests
response = requests.get(
"https://api.scrapeit.io/api/v1/scrape/google/maps/search",
headers={"x-api-key": "YOUR_SCRAPEIT_API_KEY"},
params={"q": "coffee shops", "ll": "@30.2672,-97.7431,14z", "gl": "us", "hl": "en"},
timeout=120,
)
data = response.json()["data"]
for place in data["local_results"]:
print(place["position"], place["title"], place["rating"], place["phone"])Search response
json
{
"data": {
"search_metadata": {
"request_id": "8c1f4b2e-3d7a-4e59-9b61-2f0a7c9d1e34",
"query": "coffee shops",
"ll": "@30.2672,-97.7431,14z",
"location": null,
"country": "us",
"language": "en",
"page": 1,
"proxy_tier": "residential",
"duration_ms": 1840,
"processed_at": "2026-10-22T15:01:10.637Z"
},
"local_results": [
{
"position": 1,
"title": "Black Fox Coffee",
"place_id": "ChIJKxa8FmW1RIYRnDlOJujvQjo",
"data_id": "0x8644b56516bc162b:0x3a42efe8264e399c",
"cid": "4198181583016835484",
"address": "323 W 6th St, Austin, TX 78701",
"rating": 4.6,
"reviews_count": 82,
"price_level": null,
"type": "Coffee shop",
"types": ["Coffee shop"],
"phone": null,
"website": "https://www.blackfoxcoffee.com/",
"coordinates": { "latitude": 30.2686451, "longitude": -97.7460543 },
"timezone": "America/Chicago",
"open_state": "Open · Closes 5 PM",
"hours": [
{ "day": "Thursday", "hours": ["7 AM–5 PM"] },
{ "day": "Friday", "hours": ["7 AM–5 PM"] }
],
"thumbnail": "https://lh3.googleusercontent.com/grass-cs/AABkmLefeR2a…"
}
],
"pagination": { "current_page": 1, "next_page": 2 }
}
}A query Google answers with a single place (an exact name and address) returns that one place. A query with no match answers 200 with an empty local_results - Google's own "nothing found, here is what is nearby" list is not passed off as results.
Look up a place
GET https://api.scrapeit.io/api/v1/scrape/google/maps/place
x-api-key: YOUR_SCRAPEIT_API_KEYPlace parameters
Send exactly one of place_id, data_id, cid or url.
| Parameter | Type | Example | Description |
|---|---|---|---|
place_id | string | ChIJKxa8FmW1RIYRnDlOJujvQjo | Places API id of a business or landmark, e.g. ChIJKxa8FmW1RIYRnDlOJujvQjo. |
data_id | string | 0x8644b569562669d5:0x4b06cbdfc7196e9e | The data_id a search returned, e.g. 0x8644b56516bc162b:0x3a42efe8264e399c. |
cid | string | 5406232564683337374 | The decimal customer id of the place - the ?cid= of a Maps link. |
url | string | https://www.google.com/maps/place/Cipollina/@30.2805901,-97.7584946,17z/data=!3m1!4b1!4m6!3m5!1s0x8644b569562669d5:0x4b06cbdfc7196e9e!8m2!3d30.2805901!4d-97.7584946 | A Google Maps place URL (https://www.google.com/maps/place/…, …?cid=…, …?query_place_id=…). Only the place id is read from it; the URL itself is never fetched. Short maps.app.goo.gl links are not supported - open them once and send the long URL. |
gl | string | us | Market country, two-letter ISO code. Defaults to us. |
hl | string | en | Language of names, categories, hours and reviews. Defaults to en. |
Example lookup
bash
curl -G 'https://api.scrapeit.io/api/v1/scrape/google/maps/place' \
-H 'x-api-key: YOUR_SCRAPEIT_API_KEY' \
--data-urlencode 'place_id=ChIJ1WkmVmm1RIYRnm4Zx9_LBks'js
const response = await fetch(
'https://api.scrapeit.io/api/v1/scrape/google/maps/place?' +
new URLSearchParams({ place_id: 'ChIJ1WkmVmm1RIYRnm4Zx9_LBks' }),
{ headers: { 'x-api-key': 'YOUR_SCRAPEIT_API_KEY' } },
);
const { data } = await response.json();
console.log(data.place.title, data.place.rating, data.place.reviews.length);python
import requests
response = requests.get(
"https://api.scrapeit.io/api/v1/scrape/google/maps/place",
headers={"x-api-key": "YOUR_SCRAPEIT_API_KEY"},
params={"place_id": "ChIJ1WkmVmm1RIYRnm4Zx9_LBks"},
timeout=120,
)
place = response.json()["data"]["place"]
print(place["title"], place["rating"], len(place["reviews"]))Place response
json
{
"data": {
"search_metadata": {
"request_id": "2b7e9c41-5a0d-4f3b-8e62-7d1c0a9f3b58",
"data_id": "0x8644b569562669d5:0x4b06cbdfc7196e9e",
"country": "us",
"language": "en",
"proxy_tier": "residential",
"duration_ms": 1520,
"processed_at": "2026-10-22T15:05:08.107Z"
},
"place": {
"title": "Cipollina",
"place_id": "ChIJ1WkmVmm1RIYRnm4Zx9_LBks",
"data_id": "0x8644b569562669d5:0x4b06cbdfc7196e9e",
"cid": "5406232564683337374",
"address": "1213 W Lynn St, Austin, TX 78703",
"rating": 4.4,
"reviews_count": 641,
"price_level": null,
"type": "Italian restaurant",
"types": ["Italian restaurant", "Bistro", "Takeout Restaurant", "Pizza restaurant"],
"phone": "(512) 477-5211",
"website": "http://www.cipollina-austin.com/",
"coordinates": { "latitude": 30.2805901, "longitude": -97.7584946 },
"timezone": "America/Chicago",
"open_state": "Open · Closes 9 PM",
"hours": [{ "day": "Thursday", "hours": ["11 AM–9 PM"] }],
"thumbnail": "https://lh3.googleusercontent.com/grass-cs/AABkmLcs…",
"editorial_summary": "Modern, often local & seasonal, fare, plus gourmet pizza & panini, in a spacious dining room.",
"description": "A hidden gem in Austin since 1999. …",
"address_components": {
"neighborhood": "Old West Austin",
"street": "1213 W Lynn St",
"city": "Austin",
"postal_code": "78703",
"state": "Texas",
"country_code": "US"
},
"plus_code": "862476JR+6J",
"reservation_link": "https://www.opentable.com/restaurant/profile/60658?ref=1068",
"photos_count": 303,
"rating_distribution": [
{ "stars": 1, "count": 29 },
{ "stars": 2, "count": 13 },
{ "stars": 3, "count": 40 },
{ "stars": 4, "count": 145 },
{ "stars": 5, "count": 415 }
],
"review_highlights": ["Great selection of small plates and excellent wood-fired pizza."],
"review_topics": ["tagliatelle alfredo", "garlic knots", "wood fired pizza"],
"secondary_hours": [
{ "type": "Happy hours", "hours": [{ "day": "Monday", "hours": ["3–6 PM"] }] }
],
"attributes": [
{
"group": "Accessibility",
"items": [{ "name": "Wheelchair accessible entrance", "available": true }]
}
],
"photos": ["https://lh3.googleusercontent.com/grass-cs/AABkmLeADEXf…"],
"reviews": [
{
"author_name": "A. Reviewer",
"rating": 5,
"text": "Great pasta and friendly staff.",
"date": "2 months ago",
"published_at": "2026-08-03T07:14:49.078Z"
}
]
}
}
}Response fields
Every place (local_results[] and place)
| Field | Type | Description |
|---|---|---|
position | number | Search only: 1-based position across pages (page 2 starts at 21). |
title | string | The place name. |
place_id | string | null | Places API id (ChIJ…). |
data_id | string | null | Google's feature id (0x…:0x…); send it to the place endpoint. |
cid | string | null | Decimal customer id; https://maps.google.com/?cid=<cid> opens the place. |
address | string | null | The address as Google prints it. |
rating | number | null | Average star rating, 1–5. |
reviews_count | number | null | Number of reviews. |
price_level | string | null | The price band (e.g. $$) when Google publishes one for the place; null for most places. |
type | string | null | Primary category, e.g. Coffee shop. |
types | string[] | Every category Google lists, primary first. |
phone | string | null | Phone number in the local format. |
website | string | null | The website the place links. |
coordinates | object | null | latitude and longitude. |
timezone | string | null | IANA time zone of the place, e.g. America/Chicago - the zone hours and open_state are in. |
open_state | string | null | The status line as Google shows it at request time: Open · Closes 5 PM, Closed · Opens 7 AM. |
hours[] | object[] | The week from today on: day and the hours ranges as printed (7 AM–5 PM, Closed, Open 24 hours). |
thumbnail | string | null | The main photo. |
Place only
| Field | Type | Description |
|---|---|---|
editorial_summary | string | null | Google's own short description of the place. |
description | string | null | The description the business wrote ("From the business"). |
address_components | object | null | The address in parts: neighborhood, street, city, postal_code, state and country_code (ISO 3166-1 alpha-2), each null when Google has none. |
plus_code | string | null | Global Plus Code of the location, e.g. 862476JR+6J. |
reservation_link | string | null | The table-booking page the place links (OpenTable, Resy…). |
photos_count | number | null | How many photos the place has on Google Maps. |
rating_distribution[] | object[] | Review counts per star, one to five: stars and count. Empty when Google publishes none. |
review_highlights[] | string[] | Short quotes Google lifts from reviews for the place summary. |
review_topics[] | string[] | The topics Google offers to filter the reviews by, e.g. garlic knots. |
secondary_hours[] | object[] | Hours of the place's services that differ from the main hours: type (Happy hours, Kitchen, Delivery…) and hours[] like hours[] above. |
attributes[] | object[] | The "About" groups: group (e.g. Accessibility) and items[] with name and available (false for "No …"). |
photos[] | string[] | Photo URLs of the place panel. |
reviews[] | object[] | The top reviews Google shows on the panel (up to five): author_name, rating, text, date (as shown) and published_at (ISO 8601). Only the author's public display name is returned - no profile link or photo. |
search_metadata reports what was asked and how it ran; proxy_tier is the tier of the exit that served the request (datacenter or residential). pagination.next_page is the next page to ask for, or null when the list has ended.
Reviews of a place
GET https://api.scrapeit.io/api/v1/scrape/google/maps/reviews
x-api-key: YOUR_SCRAPEIT_API_KEYGoogle Maps shows a visitor who is not signed in up to five reviews per order and keyword, with no "more" page: the full list needs a Google sign-in. Each request returns that set for the order and keyword you choose; another sort or query returns another set, so combining them collects more reviews of the same place.
Reviews parameters
Send exactly one of place_id, data_id, cid or url, as in the place lookup.
| Parameter | Type | Example | Description |
|---|---|---|---|
place_id | string | ChIJCar0f49ZwokR6ozLV-dHNTE | Places API id of the place. |
data_id | string | 0x89c2598f7ff4aa09:0x313547e757cb8cea | The data_id a search returned. |
cid | string | 3545819340560108778 | The decimal customer id of the place - the ?cid= of a Maps link. |
url | string | https://www.google.com/maps/place/Katz%27s+Delicatessen/data=!4m2!3m1!1s0x89c2598f7ff4aa09:0x313547e757cb8cea | A Google Maps place URL; only the place id is read from it. |
sort | string | newest | relevant (default), newest, highest or lowest rating first. newest orders by the last edit of a review. |
query | string | pastrami | Only reviews that mention this keyword (up to 100 characters). No match returns an empty reviews list. |
gl | string | us | Market country, two-letter ISO code. Defaults to us. |
hl | string | de | Language of dates and visit details, and of the translation of reviews written in another language. Defaults to en. |
Example reviews request
bash
curl -G 'https://api.scrapeit.io/api/v1/scrape/google/maps/reviews' \
-H 'x-api-key: YOUR_SCRAPEIT_API_KEY' \
--data-urlencode 'place_id=ChIJCar0f49ZwokR6ozLV-dHNTE' \
--data-urlencode 'sort=newest'js
const response = await fetch(
'https://api.scrapeit.io/api/v1/scrape/google/maps/reviews?' +
new URLSearchParams({ place_id: 'ChIJCar0f49ZwokR6ozLV-dHNTE', sort: 'newest' }),
{ headers: { 'x-api-key': 'YOUR_SCRAPEIT_API_KEY' } },
);
const { data } = await response.json();
for (const review of data.reviews) console.log(review.rating, review.date, review.text);python
import requests
response = requests.get(
"https://api.scrapeit.io/api/v1/scrape/google/maps/reviews",
headers={"x-api-key": "YOUR_SCRAPEIT_API_KEY"},
params={"place_id": "ChIJCar0f49ZwokR6ozLV-dHNTE", "sort": "newest"},
timeout=120,
)
for review in response.json()["data"]["reviews"]:
print(review["rating"], review["date"], review["text"])Reviews response
json
{
"data": {
"search_metadata": {
"request_id": "8d0c6e2a-41f7-4b9e-9a55-1f3e0c7b2d64",
"data_id": "0x89c2598f7ff4aa09:0x313547e757cb8cea",
"sort": "newest",
"query": null,
"country": "us",
"language": "en",
"proxy_tier": "residential",
"duration_ms": 1240,
"processed_at": "2026-10-30T18:02:11.512Z"
},
"reviews": [
{
"review_id": "Ci9DQUlRQUNvZENodHljRjlvT2xVeE9WOVBSMmREWTBocFNqRmZWRzFqWldseVgyYxAB",
"rating": 5,
"text": "The pastrami is as good as everyone says. Worth the wait.",
"original_language": "en",
"translated_text": null,
"date": "3 weeks ago",
"published_at": "2026-10-09T14:21:52.626Z",
"updated_at": "2026-10-09T14:21:52.626Z",
"likes": 1,
"photos": ["https://lh3.googleusercontent.com/geougc-cs/AB3k…=w1200-h900"],
"attributes": [
{
"key": "GUIDED_DINING_MODE",
"label": "Order type",
"values": ["Dine in"],
"rating": null
},
{
"key": "GUIDED_DINING_PRICE_RANGE",
"label": "Price per person",
"values": ["$30–40"],
"rating": null
},
{ "key": "GUIDED_DINING_FOOD_ASPECT", "label": "Food", "values": [], "rating": 5 }
],
"owner_response": null,
"author": {
"name": "Alex R.",
"profile_url": "https://www.google.com/maps/contrib/100000000000000000001/reviews",
"photo_url": "https://lh3.googleusercontent.com/a/reviewer=s120-c",
"reviews_count": 101,
"photos_count": 312,
"is_local_guide": true
},
"link": "https://www.google.com/maps/reviews/data=!4m8!14m7!1m6!2m5!1sCi9DQUlRQUNv…"
}
]
}
}| Field | Description |
|---|---|
text | The review in the language it was written in. |
original_language | Language of text, e.g. hu. |
translated_text | Google's translation into hl when the review was written in another language, otherwise null. |
date | The relative date Google prints, e.g. 3 weeks ago or Edited 3 hours ago. |
published_at | When the review was posted, ISO 8601; updated_at is its last edit. |
likes | How many people marked the review helpful. |
photos | Photos attached to the review. |
attributes | Details of the visit the reviewer filled in (order type, meal, price per person, wait, parking…) and the aspects they rated 1-5 (food, service, atmosphere), in hl. |
owner_response | The business owner's reply with its text and date, or null. |
author | The reviewer's public profile: name, profile link, photo, reviews and photos count, Local Guide flag. |
No-code Google Maps scrapers
Prefer a dashboard run and a file? Scrapers without code has two Google Maps scrapers. Each produces JSON, CSV and XML files and is also available over HTTP with an API key (x-api-key; scope scrapers:run to start, scrapers:read to poll):
POST https://api.scrapeit.io/api/v1/scrapers/{scraper}/jobs
GET https://api.scrapeit.io/api/v1/scrapers/{scraper}/jobs/{jobId}| Scraper | {scraper} | Parameters | One record per |
|---|---|---|---|
| Google Maps Scraper | google-maps | q (required), location, ll, gl, hl, max_pages (1–20, default 5), include_detail, output_format | place |
| Google Maps Reviews Scraper | google-maps-reviews | places (required: up to 20 place ids, data ids, cids or place URLs), gl, hl, output_format | review, with its place |
| Parameter | Type | Example | Description |
|---|---|---|---|
q | string | coffee shops | Maps Scraper: required, what to search for. |
location | string | Austin, TX | Maps Scraper: a city, region or address to search in. |
ll | string | @30.2672,-97.7431,14z | Maps Scraper: map centre and zoom, as in the Search API. |
places | array | ["ChIJKxa8FmW1RIYRnDlOJujvQjo"] | Reviews Scraper: required, up to 20 place ids (ChIJ…), data ids (0x…:0x…), cids or Google Maps place URLs. |
gl | string | us | Market country, two-letter ISO code; the proxy exit country. Defaults to us. |
hl | string | en | Interface language (en, de, pt-BR…). Defaults to en. |
max_pages | number | 10 | Maps Scraper: search pages to sweep, 1–20. Defaults to 5; Google Maps stops at about six. |
include_detail | boolean | true | Maps Scraper: also look each place up and nest it under detail (the place fields, with attributes, photos and top reviews), billed per place like the Place API. Defaults to false. |
output_format | array | ["json", "csv"] | One or more of json, csv, xml. Defaults to ["json"]; an empty list is rejected. |
The reviews scraper collects what Google Maps shows a signed-out visitor: up to five most relevant reviews per place, with the author's public name, rating, text and date - the full review list, sorting and review search need a Google sign-in. A place without reviews still gets one row with its place fields.
A run of five pages or places or fewer without include_detail finishes inline and the POST already answers with the result-file ids; a larger one, or any run with include_detail, answers queued, so poll the GET endpoint until status is finished (or failed). Each search page is billed like one Search API request and each place like one Place API request - the places of include_detail too; a place whose lookup fails keeps its search fields with detail: null and a detail_error code, and that lookup costs nothing. A listed place Google does not know, or blocks on every attempt, becomes a row with its place and an error code and costs nothing; the other places still run.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | A missing q; an ll in the wrong shape or off the globe; a page outside 1–6; no place id or more than one; an id in the wrong shape; a url that is not a Google Maps place URL with an id. Reviews: a place id Google itself rejects (the request reached Google and is charged). |
| 404 | NOT_FOUND | Place only (reviews of an unknown place come back as an empty list): Google answered with its own "no place under this id" response. |
| 502 | TARGET_BLOCKED | Every attempt was answered with Google's CAPTCHA, consent wall or another response that is not Maps data. error.details.block_reason says which: captcha, consent, unrecognized_response or no_response. Retry later. |
A place response ScrapeIt cannot read - Maps data in a format it does not know, an error frame - is 502 TARGET_BLOCKED with block_reason: unrecognized_response, not 404: it says nothing about whether the place exists. The same goes for a first search page that carries neither places nor Google's "no match" answer: it is not passed off as an empty, charged result.
All other errors follow the platform's error codes.
Credits and billing
Each endpoint bills per request under its own product code (google_maps_search, google_maps_place, google_maps_reviews) - see billing & credits.
Price per request: 30 credits for search and place, 15 for reviews, flat. The proxy is included: a request costs the same whichever exit served it. This is an introductory price for a new product and may change; the dashboard Pricing page always shows the current one.
Limits and behavior
- Every request is fetched live - never served from the shared cache - so hours, ratings and reviews are current.
- One search request returns one page of up to twenty places; use
pageto walk further, up to page 6. - The place endpoint returns the reviews Google embeds in the place panel (the top few). The reviews endpoint chooses the order and a keyword, but Google shows a signed-out visitor at most five reviews per order and keyword and no next page. Popular times are not included: the place panel Google serves does not carry them.
- Each request is a fresh session; nothing from one request (cookies, consent, location) carries into the next.
- The consent dialog shown to visitors in the EU is accepted automatically, so
glvalues in the EU return data, not the consent page. - Places, names and categories are localized by the exit's country (
gl) and the language (hl). - Google changes its data format from time to time; fields it stops sending come back
nullor empty rather than failing the request.
Related pages
- Google SERP API - Google web search results as structured JSON.
- Billing & credits - credit prices and plans.
- Concurrency & limits - how many requests can run at once on your plan.
- Managed Google Maps scraping - ScrapeIt builds, runs and monitors the scraper for you and delivers ready-to-use data.