Google Maps Local SEO Prospect Finder avatar

Google Maps Local SEO Prospect Finder

Pricing

from $2.40 / 1,000 pospect results

Go to Apify Store
Google Maps Local SEO Prospect Finder

Google Maps Local SEO Prospect Finder

Find local businesses from Google Maps and identify simple Local SEO prospect opportunities using clean business data and transparent non-AI scoring.

Pricing

from $2.40 / 1,000 pospect results

Rating

0.0

(0)

Developer

Delowar Munna

Delowar Munna

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

9 hours ago

Last modified

Share

Google Maps Local SEO Prospect Finder

Find local businesses on Google Maps and rank them as Local SEO prospects using transparent non-AI scoring. Returns clean, flat, CSV-friendly lead data — built for SEO agencies, web designers, lead-generation teams, and local sales prospecting.

V1 deliberately avoids website crawling, email extraction, full review scraping, photos, and AI enrichment so the run stays fast and cheap. You only pay for unique prospect rows that pass your filters and are successfully written to the dataset.

✨ Why this scraper

  • SEO-prospect focused — 25 flat fields tuned for outreach, plus a transparent local_seo_score and reason_tags per row.
  • Pay-Per-Event$ per saved unique prospect row. Duplicates, filtered rows, and failed pushes are not charged.
  • No login, no cookies, no sessions — keyword + location, or any Google Maps search URL.
  • CSV-friendly output — flat structure, no nested objects, drops cleanly into Sheets/Excel/CRMs.
  • Transparent scoring — rule-based, explained below. No AI black box.

🚀 Quick start — sample inputs

Example 1 — discover prospects in a city

{
"searches": [
{ "key": "dentists", "value": "Canberra ACT" }
],
"startUrls": [],
"maxResults": 100,
"maxResultsPerSearch": 100,
"language": "en",
"countryCode": "AU",
"businessStatus": "any",
"websiteFilter": "any",
"phoneFilter": "any",
"minRating": 0,
"maxRating": 5,
"minReviews": 0,
"maxReviews": 0,
"includeScore": true,
"deduplicate": true,
"proxyConfiguration": { "useApifyProxy": true }
}

Example 2 — find no-website / low-review prospects across multiple cities

{
"searches": [
{ "key": "electricians", "value": "Sydney NSW" },
{ "key": "plumbers", "value": "Melbourne VIC" },
{ "key": "cafes", "value": "Brisbane QLD" }
],
"startUrls": [],
"maxResults": 200,
"maxResultsPerSearch": 80,
"language": "en",
"countryCode": "AU",
"businessStatus": "open",
"websiteFilter": "noWebsite",
"phoneFilter": "any",
"minRating": 0,
"maxRating": 5,
"minReviews": 0,
"maxReviews": 30,
"includeScore": true,
"deduplicate": true,
"proxyConfiguration": { "useApifyProxy": true }
}

The searches field uses Apify's Key/Value form editor — the Key column is the business keyword (e.g. dentists), the Value column is the location (e.g. Canberra ACT). Add one row per search.


📦 Output

The dataset has one view: Local SEO prospects — a 25-column flat table.

Local SEO prospects table view

Sample record — Local SEO prospects

{
"business_id": "0x6b164f2bc100c4e7:0xd21f9af5314ab950",
"place_url": "https://www.google.com/maps/place/Weber+Plumbing/data=!4m7!3m6!1s0x6b164f2bc100c4e7:0xd21f9af5314ab950!8m2!3d-35.3764967!4d149.2467654!16s%2Fg%2F11bc95wrz3!19sChIJ58QAwStPFmsRULlKMfWaH9I",
"business_name": "Weber Plumbing",
"category": "Plumber",
"address": "32 Doeberl Pl",
"city": null,
"state_region": null,
"country_code": "AU",
"phone": "0423 682 816",
"website": null,
"domain": null,
"rating": 5,
"review_count": 20,
"business_status": "open",
"opening_hours_summary": null,
"latitude": -35.3764967,
"longitude": 149.2467654,
"local_seo_score": 42,
"local_seo_label": "medium_opportunity",
"reason_tags": "no_website|low_review_count",
"input_query": "plumbers",
"input_location": "Queanbeyan NSW",
"input_url": null,
"input_index": 1,
"scraped_at": "2026-05-06T06:56:24.113Z"
}

Output fields (25)

business_id, place_url, business_name, category, address, city, state_region, country_code, phone, website, domain, rating, review_count, business_status, opening_hours_summary, latitude, longitude, local_seo_score, local_seo_label, reason_tags, input_query, input_location, input_url, input_index, scraped_at.


🎯 Local SEO opportunity score

Transparent rule-based score (0–100) — higher means stronger prospect opportunity. Computed only from visible Google Maps fields. No AI, no enrichment, nothing hidden.

SignalPoints
No website+30
Reviews 0–10+20
Reviews 11–30+12
Rating < 4.0+15
Missing phone+10
Missing category+10
Unknown business status+5

Labels: high_opportunity (70–100) · medium_opportunity (40–69) · low_opportunity (0–39). reason_tags is a pipe-separated string (CSV-friendly), e.g. no_website|low_review_count|missing_phone.


💰 Pricing

Pay-Per-Event. The actor charges a single prospect-result event for each unique, filtered prospect 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 business_id, place_url, domain + name, name + address, etc.).
  • Rows filtered out by businessStatus, websiteFilter, phoneFilter, minRating, maxRating, minReviews, or maxReviews.
  • Rows missing a business_name or all of place_url / address / phone / website.
  • Failed dataset pushes.
  • Anything after the per-run spending cap is reached.

📊 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,
"invalid_inputs": 0,
"raw_results_found": 240,
"results_saved": 187,
"duplicates_removed": 21,
"filtered_out": 32,
"charged_events": 187,
"blocked_requests": 0,
"retry_count": 4,
"runtime_seconds": 142,
"scraped_at": "2026-05-06T00:00:00.000Z"
}

charged_events always equals results_saved.


🚦 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 (~/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, 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.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777

⚙️ Filters

FilterEffect
businessStatusany / open / closed.
websiteFilterany / hasWebsite / noWebsite.
phoneFilterany / hasPhone / noPhone.
minRatingDrop businesses below this star rating (0 disables).
maxRatingDrop businesses above this star rating (5 disables).
minReviewsDrop businesses with fewer reviews (0 disables).
maxReviewsDrop businesses with more reviews (0 / unset disables).
deduplicateDrop duplicates across overlapping searches (recommended ON).

Filters are applied after extraction and before dataset push or event charge.


🚧 Limitations (V1)

  • Cards-only extraction: V1 reads each business directly from the search results panel and does not click into individual place detail panels. Phone, website, full opening hours, and business_id only appear when Google surfaces them on the card itself.
  • No website crawling, email extraction, or social link extraction.
  • No full review text or sentiment.
  • No photos, menus, prices, or popular times.
  • No login/cookie/session-based scraping.
  • Address parsing into city / state_region is best-effort; the full address field is the source of truth.
  • Per-search hard cap is 1,000 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.
  • Diagnostics: On the first failed render, the actor saves the page HTML and URL to the key-value store as debug-no-feed-html / debug-zero-cards-html.