Google Maps Scraper
Pricing
from $2.50 / 1,000 scraped places
Google Maps Scraper
Extract business listings from Google Maps — name, address, phone, website, rating, reviews, opening hours, category and coordinates. Search by keyword and location.
Pricing
from $2.50 / 1,000 scraped places
Rating
0.0
(0)
Developer
John Pratt
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Google Maps Scraper extracts business listings from Google Maps into a clean dataset: name, category, address, phone, website, star rating, review count, opening hours, coordinates and Google Place ID, plus a sample of reviews. That's 37 fields per place. Type a search the way you would in Google Maps, such as coffee shops in Austin, TX, or a business name with its address, and get one row per place back. Export the results as JSON, CSV or Excel, or read them from the API.
What can Google Maps Scraper do?
- Search the way you search Google Maps. A business type plus a location returns the places Google lists for it. A business name plus its address returns that one listing.
- Collect contact and listing details: phone, website, the full address and its parts, category, price range, opening hours, popular times and the attributes on the place's About tab.
- Collect ratings and reviews: average rating, total review count, the number of reviews for each star rating, and a sample of reviews.
- Collect location data: latitude, longitude, Plus Code, time zone, Google Place ID and CID.
- Get results in any Google interface language, so categories, opening hours and other text come back in the language you need.
- Use the Apify platform: run it from Apify Console or the API, schedule runs, get a webhook when a run finishes, and connect the results to Apify integrations.
What data can you extract from Google Maps?
| Data | Fields |
|---|---|
| Business | title, category, descriptions, status, price_range |
| Contact | phone, website, address, complete_address |
| Ratings and reviews | review_rating, review_count, reviews_per_rating, user_reviews |
| Hours and traffic | open_hours, popular_times |
| Location | latitude, longitude, plus_code, timezone |
| Google IDs and links | place_id, cid, data_id, link, reviews_link, street_view_url |
| Extras | thumbnail, images, menu, reservations, order_online, owner, about, credit_cards_accepted |
Every field is described in Output fields.
How to scrape Google Maps
- Open the Actor in Apify Console and go to the Input tab.
- Enter your searches in Search queries, one per line.
- Optionally raise Results depth to load more places for broad searches, or change the Language.
- Click Start. Searches run one after another.
- When the run finishes, open the Output tab. Switch between the Overview, Location and Reviews views, or export the dataset as JSON, CSV, Excel and other formats.
Input
The input is a JSON object with three fields. Only keywords is required.
| Field | Type | Default | Description |
|---|---|---|---|
keywords | array of strings | required | Google Maps searches, one per item, worded as you would type them into Google Maps. A business type plus a location (coffee shops in Austin, TX) returns the places Google lists for it. A business name plus its address returns that single listing. |
depth | integer, 1 or more | 10 | How many times to scroll each search's results list. Each scroll loads more places, so a higher value returns more businesses for broad searches but makes each search take longer. |
language | string | en | Google interface language code, such as en, es, de or fr. It sets the language of categories, opening hours and other text. |
{"keywords": ["coffee shops in Austin, TX", "Katz's Delicatessen, 205 E Houston St, New York"],"depth": 10,"language": "en"}
Tips for writing searches
- Put a location in every broad search, such as
plumbers in Denver, COrather thanplumbers. Without one, the results depend on where Google thinks the search comes from. - Split big areas into smaller searches. Google Maps lists only a limited number of places per search (around 120), so search one neighborhood or ZIP code at a time to cover a whole city.
- Add the street address when you want one business, so Google opens that exact listing.
Output
Each place is one item in the run's dataset. Every item has all 37 fields; this example is shortened:
{"query": "Katz's Delicatessen, East Houston Street, New York","title": "Katz's Delicatessen","category": "Deli","address": "205 E Houston St, New York, NY 10002","phone": "(212) 254-2246","website": "https://katzsdelicatessen.com/","review_rating": "4.500000","review_count": "56120","reviews_per_rating": { "1": 1846, "2": 1440, "3": 3392, "4": 8901, "5": 40541 },"open_hours": { "Monday": ["8 AM–11 PM"], "Saturday": ["Open 24 hours"] },"complete_address": {"borough": "Manhattan","street": "205 E Houston St","city": "New York","postal_code": "10002","state": "New York","country": "US"},"latitude": "40.722233","longitude": "-73.987429","plus_code": "P2C7+V2 New York","timezone": "America/New_York","place_id": "ChIJCar0f49ZwokR6ozLV-dHNTE","cid": "3545819340560108778","menu": "{\"link\":\"\",\"source\":\"\"}","emails": ""}
Good to know about the output
- Numbers come as text.
review_rating(for example"4.500000"),review_count,latitudeandlongitudeare strings, so convert them before doing math. - Four fields are JSON text.
menu,owner,reservationsandorder_onlineare JSON-encoded strings, for example"null"or"{\"link\":\"\",\"source\":\"\"}". Parse them withJSON.parseorjson.loads. - Missing details are empty. Text fields are
""and object or array fields arenullwhen Google has no data for them. - Two fields are always empty.
emailsis""because the Actor doesn't visit business websites.user_reviews_extendedisnullbecause the Actor doesn't load extra review pages. - Reviews are a sample, taken from the place page, not the full review history.
Output fields
| Field | Type | Description |
|---|---|---|
query | string | The search from keywords that returned this place. |
input_id | string | ID of the search that found this place. Places from the same search share it. |
title | string | Business name as shown on Google Maps. |
category | string | Main category Google assigns to the place. |
address | string | Full address on one line. |
complete_address | object | Address parts: borough, street, city, postal_code, state, country. |
phone | string | Phone number as Google displays it. |
website | string | Business website URL. |
link | string | Link to the place on Google Maps. |
review_rating | string | Average star rating from 1 to 5, with six decimals. |
review_count | string | Total number of Google reviews. |
reviews_per_rating | object | Number of reviews for each star rating, keyed "1" to "5". |
user_reviews | array | Sample reviews. Each has Name, ProfilePicture, Rating, When, Description, Images, review_id, author_url, published_at, language, text_original, text_translated and related fields. |
user_reviews_extended | null | Always null in this Actor. |
open_hours | object | Opening hours per weekday. Each day maps to a list of time ranges. |
popular_times | object | How busy the place usually is: weekday, then hour of the day (0–23), then a relative busyness value. Empty when Google doesn't show it. |
status | string | Status or summary line Google shows for the place. |
descriptions | string | Google's description of the place. |
price_range | string | Price level or range, such as $$. |
latitude | string | Latitude in decimal degrees. |
longitude | string | Longitude in decimal degrees. |
plus_code | string | Google Plus Code for the location. |
timezone | string | IANA time zone, such as America/New_York. |
place_id | string | Google Place ID. Works with the Google Places API and as a stable key for the place. |
cid | string | Google's numeric ID for the place. https://maps.google.com/?cid=<cid> opens it. |
data_id | string | Google's internal place identifier. |
reviews_link | string | Link to the place's reviews. Often empty. |
thumbnail | string | URL of the place's main photo. |
images | array | Photos from the place page, each with title and image (URL). Often empty. |
street_view_url | string | Street View link. Often empty. |
reservations | string (JSON) | Reservation links, each with link and source. "null" when there are none. |
order_online | string (JSON) | Online ordering links, each with link and source. "null" when there are none. |
menu | string (JSON) | Menu link with link and source. Both are empty when there is no menu. |
owner | string (JSON) | Google account that manages the listing, with id, name and link. |
credit_cards_accepted | string | Comma-separated list of accepted cards. |
about | array | Attributes from the About tab, grouped by section. Each section has id, name and options; each option has name and enabled. |
emails | string | Always empty in this Actor. |
The same field descriptions, with examples, are in the Actor's dataset schema (.actor/dataset_schema.json), which Apify shows to API clients and AI agents.
How to use the Google Maps Scraper API
Run the Actor and read its results with the Apify API. Get your API token from Apify Console → Settings → API & Integrations. The examples use the Actor ID qo6wnBx3a0y8TCEjZ. The API tab on the Actor's page in Console has ready-made snippets for more languages.
Run and get results in one request
The run-sync-get-dataset-items endpoint starts a run and returns its dataset items in the same response. Apify ends the request with HTTP 408 if the run takes longer than 300 seconds, so use this endpoint only for a few targeted lookups:
curl -X POST "https://api.apify.com/v2/acts/qo6wnBx3a0y8TCEjZ/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d "{\"keywords\": [\"Katz's Delicatessen, 205 E Houston St, New York\"]}"
Start a run and fetch the results when it finishes
For broad searches or many keywords, start the run, wait for it to finish, then read the dataset:
POST https://api.apify.com/v2/acts/qo6wnBx3a0y8TCEjZ/runs?token=YOUR_APIFY_TOKENwith the input as the JSON body. The response'sdata.idis the run ID anddata.defaultDatasetIdis the dataset ID.GET https://api.apify.com/v2/actor-runs/RUN_ID?token=YOUR_APIFY_TOKEN&waitForFinish=60waits up to 60 seconds and returns the run. Repeat untildata.statusisSUCCEEDED,FAILED,TIMED-OUTorABORTED.GET https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_APIFY_TOKEN&format=jsonreturns the places. Useformat=csvorformat=xlsxfor spreadsheets.
Python:
import requestsTOKEN = "YOUR_APIFY_TOKEN"API = "https://api.apify.com/v2"run = requests.post(f"{API}/acts/qo6wnBx3a0y8TCEjZ/runs",params={"token": TOKEN},json={"keywords": ["coffee shops in Austin, TX"], "depth": 10, "language": "en"},).json()["data"]while run["status"] in ("READY", "RUNNING", "TIMING-OUT", "ABORTING"):run = requests.get(f"{API}/actor-runs/{run['id']}",params={"token": TOKEN, "waitForFinish": 60},).json()["data"]places = requests.get(f"{API}/datasets/{run['defaultDatasetId']}/items",params={"token": TOKEN, "format": "json"},).json()for place in places:print(place["title"], "|", place["phone"], "|", place["website"])
Node.js, with the apify-client package. call() waits for the run to finish:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('qo6wnBx3a0y8TCEjZ').call({keywords: ['coffee shops in Austin, TX'],depth: 10,language: 'en',});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const place of items) {console.log(place.title, '|', place.phone, '|', place.website);}
How much does it cost to scrape Google Maps?
It costs $2.50 per 1,000 places ($0.0025 per place). Each place saved to the dataset is one charge, and the price already includes the details (opening hours, popular times, About attributes, review sample and photos). There's no separate charge for compute; the Actor covers its own platform usage. Each run also has a start fee of $0.00005, Apify's standard Actor start charge.
Examples:
- A broad search like
coffee shops in Austin, TXthat returns 76 places costs about $0.19. - A single business lookup costs $0.0025.
- 10,000 places cost $25.
To cap what a run can cost, set Maximum cost per run in the run options (or maxTotalChargeUsd in the API). The lowest cap you can set is $0.25. When a run reaches its cap, it stops saving places and ends.
FAQ
How many places can I get per search?
Google Maps lists around 120 places per search at most, so a higher depth stops helping past that point. To get more, split the area into several smaller searches.
How long does a run take?
Searches run one after another. A single business lookup takes about 20–35 seconds. Broad searches take longer, because the scraper opens every place on the list. Each search is capped at 10 minutes: places not reached by then are left out, and the run still succeeds.
Why was my first run in a while slow to start?
If nobody has run the Actor for a few weeks, its backend needs to wake up first. For a few minutes the log shows Lambda is waking up (...); retrying in 15s., then the run continues normally. Runs after that start right away.
What happens if a search fails?
The run stops at the failed search and is marked as failed. Places from the searches that finished before it stay in the dataset.
Do I pay for searches that return nothing?
No. You pay only for places saved to the dataset, plus the $0.00005 start fee per run.
Why are some fields empty?
Google doesn't show every detail for every place. Landmarks and areas, such as a market or a park, come back with few fields because Google Maps doesn't treat them as businesses. emails and user_reviews_extended are always empty in this Actor.
Can I connect the results to other tools?
Yes. Every run's dataset can be downloaded as JSON, CSV, Excel, XML, HTML or RSS, or read through the API. You can also schedule runs, get webhooks when a run finishes, and send the results to the integrations Apify supports.
Is it legal to scrape Google Maps?
The Actor extracts only data that Google Maps shows publicly. Reviews can contain personal data, such as reviewer names and profile photos, which laws like the GDPR protect. Collect and store personal data only if you have a legitimate reason, and check with a lawyer if you're unsure.