Google Business Profile Review Scraper
Pricing
from $0.42 / 1,000 results
Google Business Profile Review Scraper
Find recent low-star Google Business Profile reviews by search term and location, with the business's contact details on every row.
Pricing
from $0.42 / 1,000 results
Rating
0.0
(0)
Developer
String
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Google Business Profile Review Scraper — recent 1-star reviews across a whole area
This Actor finds recent low-star reviews on Google Business Profiles across a search term and a
location, and puts the business's contact details on every one of them. Give it plumber and
Austin, TX and you get back each 1-star review left in the last six months — the review text, its
date and its author, alongside the phone number, website and postal address of the business it
was left on.
The rating filter and the recency window are both yours to set, so the same Actor answers "every 1-star this month", "everything at 2 stars or below this year", or simply "every review these profiles have".
No Google account, API key or cookies are used — this reads what a logged-out visitor sees.
What it returns
One row per review. A business with three matching reviews returns three rows, each carrying the full business record so any single row is enough to act on.
| Field | Type | Notes |
|---|---|---|
rating | number | The review's stars, 1–5 |
publishedAt | string | ISO timestamp — an exact date, not "3 months ago" |
relativeDate | string | Google's own wording, e.g. "3 days ago" |
text | string | The review body, with the reviewer's line breaks intact. null for a rating-only review |
authorName | string | |
authorReviewCount | number | How many reviews the author has written overall — a credibility signal. 0 is a real value |
imageCount | number | Photos attached to the review |
reviewUrl | string | Link straight to the review |
reviewId | string | Stable, use it to de-duplicate across runs |
businessName | string | The business as Google lists it |
businessRating | number | The profile's overall star average, e.g. 4.7 |
phone | string | Formatted phone number, e.g. (512) 309-1487 |
website | string | The business's own site, as Google links it |
address | string | Street address; null for a service-area business, which Google also shows without one |
categories | string[] | Google's own labels, e.g. ["Plumber", "Electrician"] |
latitude, longitude | number | Exact coordinates, ready to map |
matchedReviewCount | number | How many matching reviews this business had in this run — group or prioritise on it |
placeId | string | Google's ChIJ… Place ID |
dataId | string | The 0x…:0x… id Google keys the profile's reviews on |
mapsUrl | string | Link straight to the profile |
lowestRatedReviewsRead | number | How much of the profile's low-star history this run saw (see Reliability) |
searchTerm, sourceUrl, collectedAt | string | Provenance for every row |
Input
{"searches": ["plumber", "hvac"],"location": "Austin, TX","maxReviewRating": 1,"withinDays": 180,"maxItems": 1000}
| Field | Description |
|---|---|
searches | Search terms, e.g. "plumber". Up to 50, each searched separately. |
location | City, state, ZIP or country, appended to every term. Leave empty if your terms already carry a location. |
places | Optional. Google Maps place or review URLs to read directly, instead of or as well as a search. |
maxReviewRating | Returns any review at or below this rating. 1 finds 1-star only; 5 returns every review. Default 1. |
withinDays | How recent a review has to be to be returned. Default 180, roughly six months. |
maxProfilesPerSearch | How deep to page each search before filtering. Default and maximum 120. |
countryCode, language | The market the search runs in, e.g. US / en, or GB / en. |
maxItems | Cap on dataset items. Default 1000. Free plans stop at 250 requests and 250 results — see below. |
concurrency | Requests in flight at once. Default 3, maximum 5. |
Supply either searches or places — a run with neither is rejected before it starts. A business
whose reviews all miss your filter simply contributes no rows.
Use cases
- Reputation-management prospecting: a fresh 1-star review is a business in the market for help, and the row already has the number to call
- Agency churn signals: watch your own clients' profiles and get the bad review the day it lands
- Competitor monitoring across a category and city, with the complaint text, not just the average
- Complaint-theme analysis across a whole market segment from the review bodies
- Franchise and multi-location oversight, one row per piece of bad feedback
Input by URL
places accepts a Google Maps place or review URL — the long kind containing !1s0x…:0x… — or that
0x…:0x… id on its own. A maps.app.goo.gl short link and a bare ChIJ… Place ID do not carry
that id, and are reported in failures rather than guessed at. A profile supplied this way returns
its reviews and whatever name its URL contained; phone, website, address, categories and the
coordinates come from the search surface, so those fields are null on a URL-only run.
Reliability
Both halves read Google's own JSON endpoints rather than scraping rendered markup, so every value is
exact: ratings are numbers, review dates are absolute timestamps, and the reviewer's own line breaks
survive into text.
Reviews are read worst-first, which is why one request per profile is enough. Sorted that way, a
single page carries the profile's entire low-star history rather than its most recent 50 reviews — on
a busy profile that page held all 16 one-star and all 6 two-star reviews it had ever received, and the
next page was already entirely five-star, while reading newest-first would have needed eight pages to
cover the same six months. lowestRatedReviewsRead reports how many that page held; a value of 50
means it filled up, so a profile with more than 50 reviews at or below its floor may have others this
run did not read.
A search pages up to Google's own ceiling of 120 results per term, and consecutive pages overlap, so
the distinct total per term lands nearer 100. Profiles are de-duplicated on dataId before any
reviews are fetched, so a profile that appears on two search pages is never fetched twice.
A profile whose reviews cannot be read is recorded in the run's SUMMARY under failures rather than
silently contributing nothing — an intercepted response and a profile with genuinely no matching
reviews look identical otherwise, and the difference decides whether a list is complete.
There are no retries by design: the String Unblocker owns proxy rotation and anti-bot solver selection, so a retry loop here would only re-roll the same block.
Frequently asked questions
How do I find businesses with recent bad reviews? Run this Actor with your search terms and
location and leave maxReviewRating at 1 and withinDays at 180. Every row is a 1-star review
from the last six months, with the business it was left on attached.
Can I widen it beyond 1-star? Yes. maxReviewRating returns any review at or below the value you
set, so 2 catches 1- and 2-star, and 5 returns everything the worst-first page held.
Does it return the review text? Yes, with the reviewer's line breaks intact. A rating-only review
with no words returns null text and keeps its rating, date and author.
Why do I get several rows for the same business? Because each row is one review. Group on
dataId, or read matchedReviewCount, which tells you how many that business had in this run.
How many businesses does one search cover? Up to 120, which is Google's own ceiling per search term; overlapping pages mean the distinct count is usually nearer 100. Use more search terms, or more specific ones, to cover a market more deeply.
Do I need a Google account, API key or cookies? No. It reads public Google Business Profiles as a logged-out visitor and never signs in.
Can I monitor specific businesses instead of searching? Yes — put their Google Maps URLs in
places. See "Input by URL" for which URL forms carry the id this needs.
Can I search several cities in one run? location is one value applied to every term, so run the
Actor once per city — or put each city into the search terms themselves and leave location empty.
Limitations
Search and review data only: no opening hours, no menus, no photos, no popular-times data and no
"about" text. Reviews are read one worst-first page deep, so this is not a full review-history export
for a profile with more than 50 low-rated reviews. Profiles supplied by URL in places carry no
address, phone, website or coordinates, because those come from the search surface rather than the
review endpoint. Google orders a search by its own relevance rather than anything stable, so
re-running can surface a business at a different rank; de-duplicate on reviewId.
Free plan limit
Runs started from an Apify free plan stop at 250 requests and 250 results, and the run reports
that it reached the limit. Any paid plan runs the full input and maxItems you set.
The limit exists because this Actor fetches through our own infrastructure, which Apify does not cover for free-plan runs. It binds on requests as well as results, and one ceiling covers both the search and the review stage together, so a large input cannot spend those fetches for rows the run will not return.