Google Maps Reviews Scraper – Ratings, Text, Owner Replies
Pricing
from $0.50 / 1,000 review scrapeds
Google Maps Reviews Scraper – Ratings, Text, Owner Replies
Extract Google Maps reviews by place ID, cid, or Maps URL, or by search query: rating, review text (original + translated), author, owner replies and photos.
Pricing
from $0.50 / 1,000 review scrapeds
Rating
0.0
(0)
Developer
SERP King
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Google Maps Reviews Scraper – Ratings, Review Text, Owner Replies
Extract Google Maps reviews for any business: rating, review text (original and translated), author, whether they're a Local Guide, owner replies, and review photos. Give it a place ID, a cid, or a Google Maps URL — or just a search query — and it calls a licensed data provider directly. No proxies, no headless browser, no IP bans, no CAPTCHAs.
What data you get
One dataset row per review:
placeId,cid— Google's identifiers for the place the review belongs toplaceName,placeAddress,placeRating,placeReviewsCount— the place's own current stats, attached to every one of its reviewsreviewId,reviewUrlauthor,authorUrl,isLocalGuide,authorReviewsCountrating— the reviewer's star rating (0-5) for this reviewtext,originalText,originalLanguage— review text in the requestedlanguage, the untranslated original, and its detected languagepublishedAt(ISO 8601 UTC)ownerAnswer,ownerAnswerAt— the business's reply, if anyimagesCount,imageUrls— photos attached to the reviewquery— the search query that surfaced this place,nullfor a place passed directly viaplaceIds
Why this scraper
- Fast — reviews come from a real-time, expedited data pipeline, typically under a minute per batch of places, not minutes of browser automation per place.
- Cheap — pay only for reviews actually returned, a flat $0.0005 per review regardless of your Apify plan (see Pricing).
- Up to 4,000 reviews per place — far past what Google's own UI shows without heavy scrolling.
- Three ways in — a
place_id, a numericcid, or a Google Maps URL (both the?cid=and the!1s0x...:0x...link formats work); or skip IDs entirely and search byquerieslike the Maps actor does. - Original + translated text — both
text(in your requestedlanguage) andoriginalText/originalLanguageare returned, so you can tell a translation from a native-language review.
Pricing
This actor uses Apify's pay-per-event pricing, flat across all plans:
| Event | What it means | Price |
|---|---|---|
apify-actor-start | Apify's platform-billed "run started" event, charged once per run automatically — no code call needed, so a run that finds zero reviews costs almost nothing | $0.00005 |
apify-default-dataset-item ("Review scraped" in Console) | Charged once per review written to the output dataset | $0.0005 |
Worked example: scraping 1,000 reviews costs 1,000 × $0.0005 + $0.00005 ≈ $0.50.
Input
Two ways to tell the actor which places to fetch reviews for — fill one, or both:
By ID:
{"placeIds": ["ChIJrTLr-GyuEmsRBfy61i59si0"],"maxReviewsPerPlace": 100}
By search query (used as the prefill; searches Google Maps, takes the top maxPlacesPerQuery results):
{"queries": ["coffee shops in Austin, TX"],"country": "US","maxPlacesPerQuery": 2,"maxReviewsPerPlace": 20}
| Field | Type | Default | Description |
|---|---|---|---|
placeIds | array of strings | — | Places to fetch reviews for. Accepts a place_id (e.g. "ChIJrTLr-GyuEmsRBfy61i59si0"), a numeric cid (e.g. "9542840243817508540"), or a Google Maps URL containing a ?cid= query parameter or a !1s0x...:0x... feature id. Optional if queries is set. |
queries | array of strings | ["coffee shops in Austin, TX"] | Google Maps search queries; each takes its first maxPlacesPerQuery results. Optional if placeIds is set. |
country | string (ISO-2) | "US" | Used to resolve the location for every review request, and (unless coordinates is set) to anchor queries. |
coordinates | string | — | Query mode only: anchor queries to a map viewport instead of country, "lat,lng,zoom" (e.g. "30.2672,-97.7431,14"). |
maxPlacesPerQuery | integer | 10 (1-100) | How many places to take from each query's search results. |
language | string | "en" | Language code for review text and query results. |
maxReviewsPerPlace | integer | 100 (10-4,000) | Reviews to fetch per place. Must be a multiple of 10 — Google's reviews API pages in tens. |
reviewsSort | string | "newest" | One of newest, relevant, highest_rating, lowest_rating. |
reviewsNewerThan | string (ISO-8601) | — | Keep only reviews published on or after this date/datetime (inclusive), e.g. "2026-09-01" or "2026-09-01T00:00:00Z". Applied after fetching, before writing to the dataset — see below. |
reviewsOlderThan | string (ISO-8601) | — | Keep only reviews published on or before this date/datetime (inclusive), e.g. "2026-09-08". Must be on or after reviewsNewerThan. |
DataForSEO's reviews API has no date filter of its own, so reviewsNewerThan/reviewsOlderThan are applied by this actor after fetching up to maxReviewsPerPlace reviews and before writing rows to the dataset — only rows inside the window get pushed, and only pushed rows are charged, so an out-of-window review costs nothing. The run's STATS record (reviewsFilteredByDate) reports how many were dropped this way.
A run is capped at 100 places total (placeIds count + maxPlacesPerQuery x queries) and 4,000 reviews per place — so the input fails validation up front, with a message telling you exactly how far over you are, rather than letting a typo turn into a runaway bill. Need more than 100 locations? See Monitoring at scale below.
Output
One real dataset row, from an actual run against a public Google Maps place on September 8, 2026:
{"placeId": null,"cid": "9920705898319708454","placeName": "Cacao Much - Chocolate Café","placeAddress": "Av. Providencia 2400, 7510034 Providencia, Región Metropolitana, Chile","placeRating": 4.5,"placeReviewsCount": 3261,"reviewId": "Ci9DQUlRQUNvZENodHljRjlvT25WemVXa3pNblpoY1ZOblFsY3llV1ZwTTBZeFVVRRAB","author": "Nahime Mostafá","authorUrl": "https://www.google.com/maps/contrib/102272400702552550088/reviews?hl=es-419","isLocalGuide": true,"authorReviewsCount": 54,"rating": 5,"text": "Personalmente me encantó que ofrezcan el chocolate caliente en su versión espesa y ligera. Opté por el ligero y es ideal para acompañar con los churros.","originalText": null,"originalLanguage": "es","publishedAt": "2026-09-08T00:57:25Z","ownerAnswer": "Gracias por tu increíble reseña! Te esperamos nuevamente para más cositas ricas ","ownerAnswerAt": "2026-09-08T02:06:20Z","imagesCount": 3,"imageUrls": ["https://lh3.googleusercontent.com/grass-cs/ACvplmPyV1Y2boQQd_IiPxCNzcRRj_H4xKqiC5FsyY228kXEfOEz-E9eopWRITHuzN7ZD-t7bTdxXZdq3YBuF2PWFTxZwZ3_xlGOTCZZhaqdCmpWJl9two6UgsXy71WDz0DsIUnk5WuTarNqA_ed=k-no","https://lh3.googleusercontent.com/grass-cs/ACvplmNGHnWahaniFQAoBtOvACPQj15OYxrIRgspNJlecjwXl-ijWm-XxdImmQlX8zlRNEPJ8CCak9Hwzs5VGoHHKayLicxBUMRcf2xWsfCt9D-COS0QGBBl6u3HF8ExN_ui7eQOfMrzKKBqSv1y=k-no","https://lh3.googleusercontent.com/grass-cs/ACvplmN3ATMOr1PfjQM6qaoZuObWplPfurFHqdz7Un2CU3r-7Zg9iQ05YBL10h6-eoDNaHLMiNSTfgMfgN2j1I5tYfWRansMGS9mqcG8ofAPYD-4EMmmwW2zKaYoMybvrGADU0mMReUHk_9RXNAn=k-no"],"reviewUrl": "https://www.google.com/maps/reviews/data=!4m8!14m7!1m6!2m5!1sCi9DQUlRQUNvZENodHljRjlvT25WemVXa3pNblpoY1ZOblFsY3llV1ZwTTBZeFVVRRAB!2m1!1s0x0:0x89ad6d73ce780126!3m1!1s2@1:CAIQACodChtycF9oOnVzeWkzMnZhcVNnQlcyeWVpM0YxUUE%7C%7C?hl=es-419","query": "cafeterías en Providencia, Santiago"}
| Field | Type | Description |
|---|---|---|
placeId | string | null | Google's place identifier |
cid | string | null | Google's numeric identifier for the place |
placeName | string | null | Business name |
placeAddress | string | null | The place's address, as shown alongside its reviews |
placeRating | float | null | The place's current overall rating (0–5) |
placeReviewsCount | integer | null | The place's current total review count |
reviewId | string | null | Google's identifier for this specific review |
author | string | null | Reviewer's display name |
authorUrl | string | null | Link to the reviewer's Google Maps profile |
isLocalGuide | boolean | null | Whether the reviewer has Local Guide status |
authorReviewsCount | integer | null | Total reviews the author has written (not just for this place) |
rating | float | null | This review's star rating (0–5) |
text | string | null | Review text, translated to language if needed |
originalText | string | null | Untranslated review text |
originalLanguage | string | null | Detected language of originalText |
publishedAt | string | null | ISO 8601 UTC |
ownerAnswer | string | null | The business's reply text, if any |
ownerAnswerAt | string | null | ISO 8601 UTC |
imagesCount | integer | null | Number of photos attached to the review |
imageUrls | array of strings | Direct URLs of attached photos (empty if none) |
reviewUrl | string | null | Direct link to the review |
query | string | null | The queries entry that surfaced this place, null for a placeIds entry |
Limits
- Maximum 4,000 reviews per place, and 100 places per run (see Input) — this actor's own cap, to keep a typo from turning into a runaway bill.
maps.app.goo.glshort links (the ones "Share" in the Google Maps app produces) aren't supported: resolving them needs an HTTP redirect, and this actor never makes requests to Google directly. Expand the link in a browser first and pass the resultingmaps.google.com/google.com/mapsURL instead.authorReviewsCountcounts the author's total reviews across Google Maps, not reviews of this specific place.- Auto-generated vs. manually-written reviews aren't distinguished — Google itself doesn't expose that flag through this data source.
- A place found via
queriesbut not yet indexed with any reviews returns zero rows for it (not an error) — check the run'sSTATSkey-value record (placesWithoutReviews) to see how many. - Results reflect Google Maps at the moment the run executes; ratings, reply text, and review counts can change between runs.
Monitoring at scale
Tracking more than 100 locations on a recurring schedule (e.g. a reputation-management agency watching 300 client locations weekly)? Chunk your place list across multiple runs rather than trying to fit it into one:
- Chunk
placeIdsinto batches of ≤100 — e.g. 300 locations become 3 chunks of 100, each its own scheduled run (3 Apify Schedules, or 3 calls from your own orchestrator to the Apify API's run-actor endpoint). - Prefer
placeIdsoverqueriesfor monitoring — aplaceIdslist targets the same locations every run, while aqueriessearch can surface a different set of places as Google Maps' own ranking shifts. - Set
reviewsNewerThanto your last successful run's date, withreviewsSort: "newest"— this keeps a run from re-charging for reviews it already pulled last time (see Input above for how the filter works). An Apify Schedule sends the same fixed input on every trigger, so it can't compute "since last run" by itself: drivereviewsNewerThanfrom your own cron/orchestrator, updating the run's input to the previous run's date (via the Apify API) before each trigger. - Dedupe by
reviewIdon your side across runs — if you padreviewsNewerThana day earlier than strictly necessary as a safety margin (clock drift, a review that lands mid-run), you'll see a handful of the same reviews again rather than relying on the filter alone for a perfectly disjoint set. - Watch
reviewsFilteredByDateandplaceReviewsCountinSTATS/each row — if a place picked up more new reviews thanmaxReviewsPerPlacesince your last run, the oldest ones in that window are lost (withreviewsSort: "newest", only the newestmaxReviewsPerPlaceare fetched at all); raisemaxReviewsPerPlacefor that place if this happens.
Worked weekly example: 300 locations, chunked into 3 runs of 100 places each, averaging ~20 new reviews per location per week: 300 × 20 × $0.0005 = $3.00 in review charges, plus 3 × $0.00005 = $0.00015 for the 3 run starts — about $3.00/week total.
FAQ
Is this legal? The actor retrieves publicly available review data through a licensed data provider, the same category of source used by reputation-management and local-SEO tools. You're responsible for how you use the extracted data under your local regulations.
Which languages are supported?
Any language Google Maps itself supports for reviews. Set language to get text translated into that language; originalText/originalLanguage always carry the review as the author wrote it, regardless of language.
Can I pass a place_id I got from the Google Maps Places API or another Apify actor?
Yes — placeIds accepts a place_id directly, no conversion needed. It also accepts a cid or a full Google Maps URL if that's what you have instead.
Why did I get fewer reviews than maxReviewsPerPlace?
The place may simply not have that many. placeReviewsCount on each returned row tells you the place's actual total; if it's lower than maxReviewsPerPlace, that's the ceiling regardless of what you requested.
Can I run this via API, on a schedule, or trigger it from a webhook? Yes. Any Apify actor can be started, monitored and read back through the Apify API, run on a recurring schedule, and wired to webhooks on run events from the Apify Console.