Google Maps Business Scraper — $0.50/1K, No API Key
Pricing
$0.50 / 1,000 business delivereds
Google Maps Business Scraper — $0.50/1K, No API Key
Search Google Maps businesses with phone, website, split address, weekly hours, accessibility, ratings, ranking, and coordinates. $0.50 per 1,000 delivered. No Google API key; duplicates, failures, and empty searches are free.
Pricing
$0.50 / 1,000 business delivereds
Rating
0.0
(0)
Developer
Meka.im
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
Google Maps businesses with complete details for $0.50 per 1,000 delivered businesses.
- Contact, address, hours, accessibility, ranking and location in the base price
- Core business fields aligned with the leading Google Maps Actor
- No charge for duplicates, failures, or empty searches
- No Google API key required
Type what you would type into Google Maps. Get a flat table of businesses with phone, website, address split into parts, coordinates, rating, review count, weekly opening hours, accessibility attributes and identifiers, ready for CSV, Excel, JSON or a warehouse.
Quick start
- Put your search terms in the Search terms field, one per line.
- Click Start.
- Export the Dataset, or read it with the API calls below.
{"searchStringsArray": ["dentist in Austin TX", "florist in Boston"],"maxCrawledPlacesPerSearch": 20,"language": "en"}
Input
| Field | Type | Default | Notes |
|---|---|---|---|
searchStringsArray | array of strings | required | One search term per line. Terms that name a place work best. Searched separately, results keep your order |
locationQuery | string | A single place to search in. Combined with each term | |
city / county / state / postalCode | string | Optional, added to the location | |
countryCode | string | Biases results toward this country | |
language | string | en | Language of names, categories and hours |
maxCrawledPlacesPerSearch | integer | 20 | 1 to 20. See Limits |
customGeolocation | object | GeoJSON geometry; its centre becomes the map centre | |
categoryFilterWords | array | Keep only these categories | |
searchMatching | string | all | only_includes or only_exact to match on the name |
placeMinimumStars | string | Drop businesses below this rating | |
website | string | allPlaces | withWebsite or withoutWebsite |
Duplicate search terms are searched once. A business that appears under two terms is written once.
All four filters run on results that were already fetched. They never add requests, and anything they remove is not charged.
Inputs from the reference Actor
This Actor also accepts the other inputs of the leading Google Maps Actor so an existing input file runs unchanged, even though they are not shown in the editor:
- Accepted, no effect: review, image, contact, lead, social-profile and competitor-analysis options,
scrapePlaceDetailPage,skipClosedPlacesand the other add-on switches. Setting any of them to a non-default value is reported in the run log and in the run summary, so it is never silent. - Rejected:
startUrls,placeIdsandallPlacesNoSearchAction. These change the input mode entirely, and quietly ignoring them would return results you did not ask for. A run that sets one stops with an explanation instead.
Output
One row per business, in the order of your search terms.
| Field | Type | Notes |
|---|---|---|
fid | string | Google's feature ID. The stable key for joining and de-duplication |
placeId | string | Google Place ID, ChIJ… |
cid | string | Decimal customer ID used by maps?cid= links |
kgmid | string | Knowledge Graph machine ID |
businessProfileId | string | Google Business Profile ID |
url | string | Google Maps link |
title | string | Business name |
categoryName | string | Primary category |
categories | array | All categories, primary first |
description | string or null | Editorial summary |
tagline | string or null | Short tagline. Additional field |
address | string | Street address without the business name |
street / city / state / postalCode / countryCode / neighborhood | string or null | Address split into parts |
location | object | { lat, lng }, each null when Google has no coordinates |
phone | string or null | As Google displays it |
phoneUnformatted | string or null | Digits only |
website | string or null | |
totalScore | number or null | Average rating |
reviewsCount | number or null | See Limits |
openingHours | array | { day, hours }, Monday first |
openingHoursComplete | boolean | Whether all seven days are present |
openState | string or null | Open/closed text at the moment of the scrape. Not a permanent-closure flag |
timezone | string | IANA timezone |
additionalInfo | object | Accessibility attributes |
thumbnail | string or null | Preview image |
searchString / language / rank / scrapedAt | Where this row came from |
Example row, trimmed:
{"fid": "0x8644b4eb0b01986f:0x6b241d4769ed491e","placeId": "ChIJbxgBC-u0RIYRHknsaUcdJGs","title": "ATX Family Dental","categoryName": "Dentist","address": "1700 S 1st St, Austin, TX 78704","city": "Austin", "state": "TX", "postalCode": "78704", "countryCode": "US","location": { "lat": 30.2482229, "lng": -97.7559705 },"phone": "(512) 717-3147", "phoneUnformatted": "+15127173147","website": "https://www.atxfamilydental.com/","totalScore": 4.9, "reviewsCount": 902,"openingHours": [{ "day": "Monday", "hours": "8 AM–5 PM" }],"openingHoursComplete": true,"additionalInfo": { "Accessibility": [{ "Wheelchair accessible entrance": true }] },"searchString": "dentist in Austin TX", "rank": 1}
Pricing
$0.50 per 1,000 delivered businesses.
- A search term that returns nothing is not charged. Unlike some alternatives, this Actor does not fill an empty search with unrelated businesses.
- Duplicate search terms and businesses that appear under more than one term are charged once.
- Filtered-out businesses are not written and not charged.
- Failed searches are not charged.
- A resumed run does not refetch or recharge a business already in the Dataset.
The run summary records delivered alongside charged, so you can reconcile the bill against the Dataset.
Limits
Stated here rather than discovered later.
20 businesses per search term. Google returns one page of 20 for a search, and this version does not page further. To cover a city, use more search terms or a tighter location, which is how large Google Maps datasets are built anyway.
Review count and weekly hours come and go. Google answers this endpoint with either a full payload or a lite one, and the choice is per response: either all 20 businesses carry the review count and seven-day hours, or none of them do. The run detects a lite payload and retries, waiting between attempts because that is what actually helps. Most businesses end up complete; some do not, and openingHoursComplete tells you which. reviewsCount is null when the payload omitted it.
openState is not a closure flag. It is the open or closed text at the moment of the scrape, so a business that is simply shut for the night reads as closed. This version does not extract a permanent-closure flag.
additionalInfo covers accessibility only. Other attribute groups are not part of the search response.
Not included in this version: review text, rating distribution, image counts and full image sets, claim status, emails and website contacts, and more than 20 businesses per search term.
Compatibility
Designed to match the core search semantics of the leading Google Maps Actor, not its full input contract. Field names, types and null rules for the core business fields follow that Actor, verified field by field against 100 rows of a live run on 2026-09-20: 99.94% semantic match across 24 core fields and 1,632 comparisons.
Result sets are not identical. Google returns a somewhat different set of businesses for the same search from one call to the next, and this version reads one page per term.
API and automation
Read the Dataset directly:
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=csv&clean=true" \-H "Authorization: Bearer APIFY_TOKEN"
Start a run and wait for its Dataset in one call:
curl -X POST "https://api.apify.com/v2/acts/ACTOR_ID/run-sync-get-dataset-items" \-H "Authorization: Bearer APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchStringsArray":["dentist in Austin TX"]}'
Each run also writes an OUTPUT record to the key-value store with how many search terms were requested and deduplicated, and how many businesses were delivered, charged, de-duplicated, filtered out, skipped on resume, and how many searches returned nothing or failed.
FAQ
Why did I get fewer than 20 businesses for a term? Google returned fewer, or a filter removed some. Filtered-out businesses are not charged.
A business has no phone or website. Was I charged? Yes. That is a real answer: the business does not publish one. A row is only skipped when it has no stable identifier.
openingHoursComplete is false. Why? Google answered with its lite payload for that request and the retries did not land a full one. The hours you do get are correct, just not the whole week.
My run stopped early. If stoppedOnBudget is true in the run summary, the run hit the maximum charge you allowed. Raise the limit and start it again. Businesses already delivered are not refetched or recharged.
Can I search by Place ID or a Google Maps URL? Not in this version. A run that sets placeIds or startUrls stops with an explanation rather than returning something else.
Can I get reviews? Not from this Actor. See Limits.
Legal
This Actor is independently developed and is not affiliated with, endorsed by, or sponsored by Google.
It reads a public endpoint. It does not sign in, does not use cookies or credentials, and does not reach anything behind a login. You are responsible for how you use the data, including any applicable terms and data-protection rules.