Google Maps Scraper - Leads, Phones, Websites
Pricing
Pay per event
Google Maps Scraper - Leads, Phones, Websites
Extract businesses from Google Maps by keyword and location: name, category, address, phone, website, rating, review count, opening hours, coordinates, place ID. Filter by rating, website, phone. No API key. $2.50 per 1,000 places.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Andres Garcia-Baquero Leon
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
20 days ago
Last modified
Categories
Security
Limited permissionsShare
Turn a Google Maps search into structured business records: business name, category, address, phone (local and E.164), website, rating, review count, available opening hours, coordinates, place ID and Maps URL. Type what you would search in Google Maps ("dentists in Chicago"), set a limit and export to CSV, Excel, JSON or your CRM. No Google API key or browser is required by this Actor. Source fields may be missing and exhaustive coverage is not guaranteed.
Source rights: Public access does not establish permission to resell data. Google Maps additional terms (last modified January 27, 2026), section 2, restrict redistribution/sale and mass downloading/bulk feeds, with specified exceptions for some copying. Google's general terms and Geo permissions also apply as relevant. We have not established a permission or applicable exception authorizing this commercial extraction. Resolve the applicable terms and rights before scaling. This is a contractual uncertainty, not a general claim that scraping is unlawful. This Actor reads Maps search responses; it is not an authenticated Places API license or a Google-affiliated service.
Price: $2.50 per 1,000 places ($0.0025 per place). Places removed by your filters (min rating, website, phone) are not charged.
Why use it
| Capability | This Actor |
|---|---|
| Pricing | $2.50 per 1,000 returned places, plus start fee |
| Contacts | Phone, website and available hours in the same row |
| Collection limit | Configurable 1-400; availability depends on Google |
Output example
{"name": "Beyond Wow Plumbing & Drains","category": "Plumber","categories": ["Plumber", "Drainage service", "Gas installation service"],"address": "3432 Greystone Dr, Austin, TX 78731, United States","street": "3432 Greystone Dr","neighborhood": "Northwest Hills","city": "Austin, TX, United States","phone": "+1 512-601-6173","phoneE164": "+15126016173","website": "https://beyondwow.com/","rating": 4.9,"reviewsCount": 2592,"latitude": 30.3578911,"longitude": -97.7482485,"timezone": "America/Chicago","openingHours": {"Monday": "7 am–6 pm", "Saturday": "Closed"},"placeId": "ChIJpxUGhC_LRIYR2g941oH50ow","cid": "10147447246463438810","googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJpxUGhC_LRIYR2g941oH50ow","searchQuery": "plumbers in Austin TX","rank": 1}
How to use
- Review source rights and your applicable permissions.
- Enter queries, an optional location and a result limit.
- Set a maximum charged amount, run, and inspect OUTPUT.queryStatus.
- Export CSV, JSON or Excel, or consume the dataset through the Apify API.
Omitting searchQueries, including {}, uses dentists in Chicago, up to 100 places. The published form prefill also includes plumbers in Austin TX; it is a different test from {}. Explicit invalid targets never become demo queries.
{"searchQueries": ["dentists in Chicago"], "maxPlacesPerQuery": 20, "skipPlacesWithoutWebsite": true}
{"searchQueries": ["dentists", "orthodontists"], "location": "Madrid, Spain", "maxPlacesPerQuery": 40, "minRating": 4, "skipPlacesWithoutPhone": true, "language": "es"}
Input
| Field | Description |
|---|---|
| searchQueries | Search terms like "dentists in Chicago". Omitting searchQueries (e.g. {}) runs a demo. Explicit empty, blank or invalid targets fail with an OUTPUT diagnostic; they never become demo data. |
| location | Optional; appended as "in |
| maxPlacesPerQuery | 1-400, default 100. |
| minRating | Skip lower-rated places (not charged). |
| skipPlacesWithoutWebsite / skipPlacesWithoutPhone | Keep only contactable leads (not charged). |
| language | en, es, de... |
Dataset fields
The build includes a JSON Schema for row validation. Optional source values may be null; null is unknown, not false or zero.
| Fields | Type | Meaning |
|---|---|---|
| name, category, categories | string / nullable string / array | Source listing name and categories |
| address, street, neighborhood, city | nullable string | Source address fields |
| phone, phoneE164, website | nullable string | Listed phone, international normalization and website |
| rating, reviewsCount, reviewsCountAvailable | nullable number / integer / boolean | Rating/count with valid zeros preserved and count availability |
| openingHours, openingHoursDays, openingHoursCoverage | nullable object / integer / string | Available days and full_week, partial or unavailable coverage |
| latitude, longitude, timezone | nullable number / string | Source location and timezone |
| priceLevel, permanentlyClosed | nullable string / boolean | Optional source indications |
| placeId, cid, featureId, googleMapsUrl | nullable string / string | Stable identifiers and source link; featureId required |
| searchQuery, rank, searchMatchType, scrapedAt | string / integer / string / string | First delivered query, sequence position, google_interpreted and UTC extraction time |
Use cases
- Lead generation for agencies and B2B sales: local businesses with phone and website by niche and city.
- Market research: count and rate competitors in an area.
- Local SEO: see who ranks for "plumber in Austin" and their ratings.
rankis the position in this returned source sequence, not a universal personalized Maps/SEO rank. - Data enrichment: place IDs and coordinates for mapping and CRM matching.
Tips for more results
This Actor inspects at most 400 source positions per query as an operational safety limit, not a guaranteed Google source limit or result count. For a whole city, split it: "dentists in Chicago 60601", "dentists in Lincoln Park Chicago", etc. Duplicates across searches in one run are removed automatically and not charged.
Pricing
Pay per event, unchanged:
| Event | Price |
|---|---|
| place | $0.0025 per delivered place |
| apify-actor-start | $0.00005 per GB of run memory, minimum one event |
Set maxTotalChargeUsd in run options. Charged delivery is atomic and can return only a prefix of the requested rows. The start event may apply with zero results. QA events are not evidence of seller revenue.
Read the dataset API from n8n, Make, Zapier, Google Sheets or your own CRM pipeline. These are standard dataset integrations, not additional deployed workflows. Scheduling does not add cross-run deduplication or change detection.
FAQ
Do I need a Google API key? No.
Do you extract emails? Not in this version; the website field lets you enrich emails with any contact-scraper.
Do you extract reviews text? No, only rating and review count.
Why is reviewsCount sometimes empty? Google omits the count in some regional result formats. reviewsCountAvailable reports whether the count was provided, including a valid zero.
Are opening hours a complete week? Not always. openingHoursCoverage is full_week, partial or unavailable; openingHoursDays counts non-null days. Missing days are unknown, not closed.
Are queries matched exactly? Google may correct or approximate your query. Each row includes searchMatchType: google_interpreted; no exact-name or keyword-match guarantee is made. The original query is retained in searchQuery.
How are partial runs reported? OUTPUT contains queryStatus per query with status and stopReason: source_exhausted, result_limit, scan_limit, charge_limit, upstream_failure or billing_failure. complete means this returned sequence ended, not that every business was found. A scan limit or upstream failure is partial; all queries failing upstream with zero delivered places causes FAILED. Earlier records survive a later upstream failure.
Does HTTP 200 with no parsed records prove no matches? No. Only a recognized explicit empty-result layout is accepted as source exhaustion. Unknown JSON is retried and then reported as upstream_failure, never a proven empty search. A changed valid empty layout can therefore require maintenance rather than silently reporting absence.
What if billing fails? Missing, malformed or inconsistent SDK charge results fail the run with an OUTPUT diagnostic. OUTPUT.scraped and chargedCount only count confirmed delivery. Previously confirmed records remain; a failed run does not imply their charges were refunded. Billing failures are not swallowed or converted to source exhaustion.
How does deduplication work? Place IDs (or feature IDs) are deduplicated before billing within one run, not across runs. Only delivered identities are globally excluded from later queries; unreturned page tails remain eligible. First delivered query owns the row. Repeated source pages can consume the scan cap without proving exhaustive coverage.
Does public access authorize resale? No. See the source-rights notice. Competitor listings and working HTTP responses do not establish authorization.
Troubleshooting
| Problem | Solution |
|---|---|
Search in failed | HTTP rejection or unrecognized layout. Inspect queryStatus.error; do not interpret as no businesses. |
| billing_failure / billingError | Inspect the Apify log and pricing; the run failed closed, not as a successful paid delivery. |
| Fewer places than requested | Inspect OUTPUT.queryStatus: source exhausted, filters, scan limit or upstream failure; broaden or split the search as appropriate. |
| Run stopped early | Max cost per run reached. |
Only publicly listed business data is collected. Applicable source terms, privacy and outreach rules still require review; this Actor does not certify reuse rights, contact consent, GDPR or CAN-SPAM compliance.