Google Maps Fresh Reviews
Pricing
from $10.00 / 1,000 results
Google Maps Fresh Reviews
Get only the newest Google Maps reviews for any business — never re-scrape history. Tracks each business's last-seen review automatically, so every run returns just the delta, sorted chronologically. Optional instant alerts (Slack, Zapier, or any webhook) when a new review comes in at 3★ or below.
Pricing
from $10.00 / 1,000 results
Rating
0.0
(0)
Developer
CANCAP
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Google Maps Fresh Reviews Scraper
Apify Actor that extracts only the newest reviews since the last run for a given Google Maps business, sorted chronologically. Built for reputation monitoring — call it on a schedule and it returns just the delta each time.
How it works
- Opens the place URL, opens the Reviews panel, sets sort order to Newest.
- Scrolls and reads review cards one batch at a time.
- Stops as soon as it reaches a review it already saw on a previous run (tracked per-business in Apify's Key-Value Store) — it does not re-scrape the whole review history every time.
- Pushes only the new reviews to the Dataset, and updates the "last seen" cutoff for next time.
⚠️ What has and hasn't been tested
This was built and unit-tested in a sandboxed environment with no network access to Google (only npm/GitHub/PyPI-type registries are reachable there). So:
- ✅ Syntax-checked, dependencies install cleanly, and the custom logic
(relative-date parsing, CID/URL key extraction) is covered by
test/utils.test.js— runnode test/utils.test.jsyourself to see it pass. - ❌ The actual browser-scraping flow (opening Maps, clicking Sort, reading review cards) has NOT been run against a live page. It's written against Google's currently-documented DOM structure, but this is the part most likely to need a tweak on first real run.
Do not skip the first test run — deploy to Apify, run it against one business you control or don't mind testing on, and check the Dataset output before you point it at real customers.
Deploying to Apify
- Push this folder to a GitHub repo.
- In the Apify Console: Actors → Create new → Link Git repository, point it at your repo.
- Apify will build the Docker image automatically (it reads
.actor/actor.jsonand theDockerfile). - Set input, e.g.:
Use the full Maps URL for the business (right-click the pin → "What's here?" or just copy the URL from your browser address bar when viewing the place).{"startUrls": [{ "url": "https://www.google.com/maps/place/.../@lat,lng,17z/data=...!4m5!3m4!1s0x...:0x...!8m2!3d...!4d..." }],"maxReviews": 100} - Run it. Check the Dataset tab for output, and the Key-Value Store
tab (
fresh-reviews-state) to see the per-business cutoff being tracked. - Run it again a day or two later — on a business with no new reviews, the Dataset should come back empty. That's the actual "fresh reviews only" behavior working.
When Google changes their DOM (selector maintenance)
Google's class names are obfuscated and do drift over time. If a run starts returning empty/null fields where it used to return data, here's the fastest way to fix it:
- Open the business's Maps page in a normal Chrome browser, open Reviews.
- Right-click a review's author name → Inspect.
- Find the new class name and swap it into
src/main.js— the relevant lines are clearly commented:const authorName = await card.locator('div.d4r55')... // author nameconst ratingLabel = await card.locator('span[role="img"]')... // star ratingconst relativeDate = await card.locator('span.rsqaWe')... // "3 weeks ago"const reviewText = await card.locator('span.wiI7pd')... // review bodyconst ownerResponse = await card.locator('div.CDe7pd div.wiI7pd')... // owner reply - Push the fix, redeploy. Consider adding a scheduled daily smoke-test run on one known business so you catch breakage same-day.
Files
.actor/actor.json Apify actor manifest.actor/input_schema.json Input form shown in Apify ConsoleDockerfile Apify Playwright+Chrome base imagepackage.json Dependencies (apify, crawlee, playwright)src/main.js Main scraping logicsrc/utils.js Date parsing + place-key extraction (unit-tested)src/webhook.js Low-rating alert webhook sender (unit-tested)test/utils.test.js Standalone tests for the logic abovetest/webhook.test.js Tests the webhook sender against a real local HTTP server
Low-rating alert webhook
Set webhookUrl in the input to get a POST request whenever new reviews at
or below lowRatingThreshold (default 3★) show up. This is the actual
reputation-monitoring differentiator -- without it, this is "just" a
scraper.
- Slack: paste a Slack Incoming Webhook URL directly into
webhookUrl. The payload includes atextfield Slack reads automatically. - Zapier / Make.com / your own endpoint: point
webhookUrlat your trigger URL. The full payload (place info, threshold, and the complete review objects) is included as JSON alongsidetext. - Only fires when there's at least one matching review in that run, and a failed webhook delivery is logged as a warning -- it never fails the scrape itself.
Suggested next features (not built yet)
- Owner-response-missing flag (reviews with no reply after N days).
- Scheduled runs via Apify's built-in Scheduler (no code needed -- just point a Schedule at this actor with your business list as input).
