Google Maps Scraper - Businesses and Leads
Pricing
from $0.80 / 1,000 places
Google Maps Scraper - Businesses and Leads
Find public Google Maps businesses by keyword and area. Phone, website, hours, categories, ratings and star distribution included at one flat price. Adaptive map splitting expands coverage. Export JSON or CSV, then enrich websites into verified leads.
Pricing
from $0.80 / 1,000 places
Rating
0.0
(0)
Developer
Sumitr Mardy
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
Google Maps Scraper — Businesses and Leads
Find public business listings by keyword and location. Phone numbers, websites, opening hours, categories, ratings and star distribution are included at one flat price. Export JSON, CSV or Excel. No Google API key, login, cookies or browser required.
Quick start
{"searchQueries":["coffee"],"locations":["Lisbon, Portugal"],"maxPlaces":10}
Queries run in every location. With no locations, write the location inside the query:
{"searchQueries":["dentist in Austin TX"],"maxPlaces":50,"requireWebsite":true,"requirePhone":true}
Input
| Field | Default | Meaning |
|---|---|---|
| searchQueries | [] | Business keywords, not URLs. |
| locations | [] | Place names geocoded through public Maps. Empty means use the query as written. |
| maxPlaces | 100 | Returned unique places per query/location, 1–5,000. Prefill is 10. |
| splitArea | true | Split busy viewports into four smaller areas, down to a 500 m viewport. |
| language | en | Maps UI language (hl). |
| country | us | Two-letter country code (gl). |
| minRating | 0 | Local minimum-rating filter. Missing rating counts as 0. |
| requireWebsite | false | Return only listings with a website. |
| requirePhone | false | Return only listings with a phone. |
At most 100 query/location combinations. Duplicate combinations are merged. Deduplication by placeId applies across all pages/tiles for each combination. The same place may appear under different queries or locations. Filtering happens before saving and charging; filtered-out listings are free.
Coverage and automatic map splitting
A single Maps search often stops near 140–180 places. The Actor paginates each viewport; a short page before offset 120 marks it complete. A capped area is split into four quadrants. This continues until the result limit, 500 m minimum viewport, inventory exhaustion, spending limit or free-work guard.
Measured from Apify on 2026-10-30: the Maps-returned viewport for Manhattan produced 174 unique restaurants from one wide search; adaptive splitting reached 1,000 unique restaurants across 7 viewports, then stopped at the requested limit with 18 areas still pending. This is a measured coverage improvement, not an exhaustive census.
The location sets a Maps viewport/bias, not an administrative polygon. Nearby districts or cities may appear. A Maps geocoded viewport can be much wider than the named area; we do not claim exact city-boundary filtering. Smaller viewports and Maps ranking can still hide places. maxPlaces is a ceiling, not a guarantee.
Output
One row per unique successful place per query/location. All 26 keys are always present, never null. Missing strings are "", counts 0, categories [], openingHours {}, and starDistribution always has keys "1" through "5".
| Field | Meaning |
|---|---|
| inputIndex, query, location | Original combination index and search context. |
| placeId, cid, mapsUrl | Public place ID, decimal CID converted from its feature ID, and Maps link. |
| name, category, categories | Public business name, primary category and category array. |
| address, city | Displayed address and available locality label; not verified administrative membership. |
| phone, phoneE164, website | Listed display phone, E.164 phone and website. Empty if absent. |
| rating, reviewsCount | Displayed average rating and number of reviews. |
| starDistribution | Object with counts for 1-, 2-, 3-, 4- and 5-star ratings; absent values 0. |
| latitude, longitude | Public listing coordinates; 0 if absent. |
| openingHours, timezone | Displayed weekday/hour text and available timezone. Hours can reflect special/holiday dates. |
| position | One-based returned position within this combination. |
| status, subStatus, error, scrapedAt | Stable result, machine-readable reason, explanation and ISO timestamp. |
| status | subStatus | Place charge |
|---|---|---|
| ok | place | Yes |
| no_results | no_results | No |
| failed | invalid_input, location_not_found, http_CODE, blocked, parse_error, network_error, free_work_limit, cost_limit_reached | No |
A partially completed search can return successful places plus a final free error or limit row. A free failure does not remove charges for places already saved.
Measured field availability
Direct Apify spike, 2026-10-30. Availability varies by business and changes over time; fields are not fabricated.
| Sample | Places | Phone | Website | Rating | Hours |
|---|---|---|---|---|---|
| Lisbon coffee viewport | 160 | 108 (67.5%) | 106 (66.3%) | 153 (95.6%) | 147 (91.9%) |
| Manhattan restaurant viewport with splitting | 1,000 | 985 (98.5%) | 878 (87.8%) | 988 (98.8%) | 970 (97.0%) |
| dentist in Austin TX | 60 | 60 (100%) | 60 (100%) | 60 (100%) | 60 (100%) |
Phone and website are included only when the business lists them. Use requirePhone/requireWebsite to filter, with no extra fee.
Pricing
| Apify tier | Per place | Per 1,000 places |
|---|---|---|
| FREE | $0.002 | $2.00 |
| BRONZE | $0.0015 | $1.50 |
| SILVER | $0.0012 | $1.20 |
| GOLD+ | $0.0008 | $0.80 |
Everything listed above is included. No phone, website, details or filter surcharge. Default Actor start fee: $0.00005 per start event (per GB, minimum one). Failed, empty and locally filtered places have no place charge; start still applies. Dataset-item billing is disabled. The Actor pays platform usage under PPE. User spending limits may stop runs early.
Lead pipeline: Maps → contacts → email verification
- Collect business listings here and take non-empty website values.
- Pass those URLs as domains to Website Contact Finder, which returns its emails array alongside contacts and source information.
- Pass collected email strings as emails to Email Verifier.
Contact Finder input example (its field name was checked):
{"domains":["https://example-business.com"],"maxPagesPerDomain":5}
Email Verifier input:
{"emails":["contact@example-business.com"]}
Each Actor has its own pricing and spending limit. This Actor does not automatically run or charge the other two. Keep verification status and catch-all/unknown results when assessing contacts.
API examples
curl -X POST "https://api.apify.com/v2/acts/sumitr_mardy~google-maps-scraper/run-sync-get-dataset-items?format=json" \-H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \-d '{"searchQueries":["coffee"],"locations":["Lisbon, Portugal"],"maxPlaces":10}'
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("sumitr_mardy/google-maps-scraper").call(run_input={"searchQueries":["dentist"], "locations":["Austin, TX"],"maxPlaces":50, "requireWebsite":True, "requirePhone":True})places = list(client.dataset(run["defaultDatasetId"]).iterate_items())websites = sorted({row["website"] for row in placesif row["status"] == "ok" and row["website"]})# Optional next step; this runs a separately priced Actor:# contacts_run = client.actor("sumitr_mardy/website-contact-finder").call(# run_input={"domains": websites}# )
Use asynchronous runs for larger exports; download the dataset after completion.
Use it from AI agents (MCP)
Hosted OAuth:
{"mcpServers":{"maps":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/google-maps-scraper"}}}
Hosted Bearer alternative:
{"mcpServers":{"maps":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/google-maps-scraper","headers":{"Authorization":"Bearer YOUR_APIFY_TOKEN"}}}}
Stdio:
{"mcpServers":{"maps":{"command":"npx","args":["-y","@apify/actors-mcp-server","--tools","sumitr_mardy/google-maps-scraper"],"env":{"APIFY_TOKEN":"YOUR_APIFY_TOKEN"}}}}
Set an explicit maxPlaces, specify the area, and inspect status/subStatus. Ask for phone/website filters only when needed. Do not treat a missing field or 0 coordinate as verified data.
Scope and limits
Not affiliated with Google. Public listing JSON only; no place detail page, review texts, photos, login or private data. Results reflect Google Maps for the requested language/country. Field positions can change; missing fields stay empty. Opening hours and star distributions may be unavailable or stale.
At most two query/location workers; pages sequential, with a 300 ms pause after each request before that worker's next request. Hard network deadlines and a free-work loss guard bound slow or unproductive work. The default prefill makes two requests: geocode plus one results page.
A CAPTCHA, /sorry/ or consent challenge stops that request and future requests in the run. No captcha solving, cookie/session reuse, residential proxy or IP rotation around a challenge. Non-challenge HTTP failures may be retried once directly, then once through Apify's default datacenter proxy. A guard or spending limit can end coverage before all tiles are visited.