Google Maps Review Opportunity Finder
Pricing
from $4.80 / 1,000 review-opportunity-results
Google Maps Review Opportunity Finder
Find local businesses on Google Maps that show review-growth or reputation-management opportunities, such as low review count, weak rating, missing review momentum signals, or under-reviewed competitors in a category/location.
Pricing
from $4.80 / 1,000 review-opportunity-results
Rating
0.0
(0)
Developer
Delowar Munna
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share

Find local businesses on Google Maps that show review-growth or reputation-management opportunities — low review counts, weak ratings, missing review momentum, or under-reviewed competitors in a category/location. Returns a clean, flat, CSV-friendly row per business with a transparent review opportunity score, opportunity tags, and a recommended pitch angle ready for outreach.
V1 deliberately avoids full review text scraping, reviewer profiles, owner responses, photos, AI generation, and website crawling so the run stays fast and cheap. You only pay for unique opportunity rows that pass your filters and are successfully written to the dataset.
✨ Why this scraper
- Built for review/reputation outreach — 25 flat fields tuned for review generation, local SEO, and Google Business Profile improvement leads.
- Transparent opportunity scoring — rule-based 0–100 score with reason tags and a recommended pitch angle. No AI, no black box.
- Pay-Per-Event —
$per saved unique opportunity row. Duplicates, filtered rows, and failed pushes are not charged. - No login, no cookies, no sessions — just keyword + location.
- CSV-friendly output — flat structure, no nested objects, drops cleanly into Sheets/Excel/CRMs.
🚀 Quick start — sample inputs
Example 1 — single query, default opportunity score gate
{"searchQueries": [{ "key": "plumbers", "value": "Canberra ACT" }],"maxResults": 100,"country": "AU","language": "en","minOpportunityScore": 25,"opportunityMode": "balanced","maxRating": 4.2,"maxReviewCount": 30,"minRating": 0,"minReviewCount": 0,"websiteFilter": "any","phoneRequired": false,"categoryFilter": "","includeCoordinates": true,"deduplicateResults": true,"proxyConfiguration": { "useApifyProxy": true }}
Example 2 — multi-query, reputation-risk hunt (low-rating, phone required, has website to fix)
{"searchQueries": [{ "key": "dentists", "value": "Melbourne VIC" },{ "key": "electricians", "value": "Sydney NSW" },{ "key": "cafes", "value": "Brisbane QLD" }],"maxResults": 200,"country": "AU","language": "en","minOpportunityScore": 50,"opportunityMode": "reputationRisk","maxRating": 3.9,"maxReviewCount": 100,"minRating": 0,"minReviewCount": 5,"websiteFilter": "hasWebsite","phoneRequired": true,"categoryFilter": "","includeCoordinates": true,"deduplicateResults": true,"proxyConfiguration": { "useApifyProxy": true }}
The
searchQueriesfield uses Apify's Key/Value form editor — the Key column is the business keyword (e.g.plumbers), the Value column is the location (e.g.Canberra ACT). Add one row per search.
📦 Output
The dataset has one view: Review opportunities — a 25-column flat table.

Sample record — Review opportunities
{"search_keyword": "electricians","search_location": "New York","business_name": "Nair Electric Corp","category": "Electrician","rating": 3,"review_count": 4,"phone": "718) 323-1408","website": "https://nairelectric.com/contact-us/","website_domain": "nairelectric.com","address": "266 Smith St","city": "New York","state": "","postcode": "","country": "","google_maps_url": "https://www.google.com/maps/place/Nair+Electric+Corp/data=!4m7!3m6!1s0x89c25a50b6173cd7:0xa65ef26c98ffef52!8m2!3d40.6827888!4d-73.9933416!16s%2Fg%2F11rghq418b!19sChIJ1zwXtlBawokRUu__mGzyXqY","place_id": "0x89c25a50b6173cd7:0xa65ef26c98ffef52","latitude": 40.6827888,"longitude": -73.9933416,"has_website": true,"has_phone": true,"review_opportunity_score": 80,"review_opportunity_label": "High Review Opportunity","review_opportunity_tags": ["very_low_review_count","under_reviewed_business","low_rating","has_phone","has_website","complete_address","review_generation_opportunity","reputation_opportunity","local_seo_opportunity"],"recommended_pitch_angle": "Review generation opportunity","scraped_at": "2026-05-08T06:35:15.076Z"}
Output fields (25)
search_keyword, search_location, business_name, category, rating, review_count, phone, website, website_domain, address, city, state, postcode, country, google_maps_url, place_id, latitude, longitude, has_website, has_phone, review_opportunity_score, review_opportunity_label, review_opportunity_tags, recommended_pitch_angle, scraped_at.
🎯 Review opportunity score
Transparent rule-based score (0–100) computed from visible fields — no AI, no external enrichment. Higher score = stronger review/reputation opportunity.
Base formula
| Signal | Points |
|---|---|
| Review count missing | +25 |
Review count < 10 | +30 |
Review count 10–29 | +20 |
Review count 30–49 | +10 |
| Rating missing | +15 |
Rating < 3.5 | +30 |
Rating 3.5–3.9 | +20 |
Rating 4.0–4.2 | +10 |
| Has phone | +10 |
| Has website | +5 |
| Complete address | +5 |
Score is capped at 100.
opportunityMode adjustments
opportunityMode adds a bonus on top of the base score (no extra scraping needed):
| Mode | Adjustment |
|---|---|
balanced | Default formula only. |
lowReviews | +15 if review count missing or < maxReviewCount. |
lowRating | +15 if rating missing or <= maxRating. |
reputationRisk | +20 if rating missing or < 3.8. |
underReviewed | +20 if review count missing or < 10. |
Labels
| Score | Label |
|---|---|
| 75–100 | High Review Opportunity |
| 50–74 | Medium Review Opportunity |
| 25–49 | Low Review Opportunity |
| 0–24 | Opportunity Not Clear |
Recommended pitch angle
Derived from the highest-priority opportunity tag:
| Top opportunity | Pitch angle |
|---|---|
very_low_review_count | Review generation opportunity |
low_review_count | Review growth opportunity |
low_rating | Reputation improvement opportunity |
rating_missing | Profile trust-building opportunity |
under_reviewed_business | Local SEO and review growth opportunity |
Tag vocabulary
very_low_review_count, low_review_count, moderate_review_count, rating_missing, low_rating, average_rating, under_reviewed_business, review_generation_opportunity, review_growth_opportunity, reputation_opportunity, profile_trust_opportunity, local_seo_opportunity, has_phone, missing_phone, has_website, missing_website, complete_address, missing_address.
💰 Pricing
Pay-Per-Event. The actor charges a single review-opportunity-result event for each unique, filtered opportunity row that is successfully written to the dataset. The actor honors the user-configured per-run spending cap (Apify eventChargeLimitReached) and stops cleanly when reached.
Not charged:
- Duplicates (de-duplicated by
place_id, listing URL, or name+address). - Rows filtered out by
minOpportunityScore,maxRating,maxReviewCount,minRating,minReviewCount,websiteFilter,phoneRequired, orcategoryFilter. - Rows missing a
business_name. - Failed dataset pushes.
- Anything after the per-run spending cap is reached.
🚦 Proxy policy
Use Apify Datacenter proxy or no proxy for normal runs — both work reliably for Google Maps search at this actor's conservative concurrency (max 3).
Apify Residential proxy is not supported. The actor will fail at startup if apifyProxyGroups includes RESIDENTIAL. Reason: in pay-per-event actors, residential bandwidth ($8/GB) is billed to the developer, not the run user, so a single bandwidth-heavy run could exceed the per-result event revenue.
If you genuinely need residential routing (rare for Maps search), supply your own residential provider via the proxy editor's Custom proxy URLs field — that traffic goes through your provider, not Apify, and is unaffected:
http://user:pass@proxy.brightdata.com:22225http://user:pass@proxy.oxylabs.io:7777
📊 Run summary
After each run, a RUN_SUMMARY entry is written to the key-value store:
{"inputs_total": 3,"successful_inputs": 3,"failed_inputs": 0,"raw_results_found": 240,"results_saved": 100,"duplicates_removed": 20,"filtered_out": 120,"charged_events": 100,"blocked_requests": 0,"retry_count": 3,"runtime_seconds": 180,"scraped_at": "2026-05-06T00:00:00.000Z"}
charged_events always equals results_saved.
⚙️ Filters
| Filter | Effect |
|---|---|
minOpportunityScore | Drop rows whose review opportunity score is below this value (0 disables). |
maxRating | Drop rows with a rating above this. Missing rating is kept (opportunity). |
maxReviewCount | Drop rows with more reviews than this. Missing review count is kept (opportunity). |
minRating | Drop businesses below this star rating (0 disables; missing rating is dropped). |
minReviewCount | Drop businesses with fewer reviews (0 disables; missing review count treated as 0). |
websiteFilter | any / hasWebsite / missingWebsite. |
phoneRequired | If true, keep only businesses with a visible phone. |
categoryFilter | Case-insensitive contains match against the business category. |
deduplicateResults | Drop duplicates across queries (recommended ON). |
Filters are applied after extraction and scoring and before dataset push or event charge.
🚧 Limitations (V1)
- Cards-only extraction: V1 reads each business row directly from the search results panel and does not click into individual place detail panels. Phone, website, full opening hours, and
place_idonly appear when Google surfaces them on the card itself; otherwise these fields are empty/null. - No full review text scraping, reviewer profiles, owner responses, or review photos.
- No website crawling, email extraction, or social link extraction.
- No AI-generated outreach messages or AI reputation summaries.
- No login/cookie/session-based scraping.
- Address parsing into city/state/postcode is best-effort; the full
addressfield is the source of truth. - Per-query hard cap is 500 results; per-run hard cap is 5,000 results.
🛠️ Technical notes
- Stack: Node.js 22 · Apify SDK 3 · Crawlee · Puppeteer.
- Concurrency:
min=1,max=3(conservative to reduce blocking). - Memory: 1 GB min · 2 GB default · 4 GB max.
- Proxy: Apify Proxy enabled by default; custom configs accepted. Recommended for most real runs.
- Diagnostics: On the first failed render (no feed, or feed but zero cards), the actor saves the page HTML and URL to the key-value store as
debug-no-feed-html/debug-zero-cards-html.