Google Maps Scraper avatar

Google Maps Scraper

Pricing

from $2.50 / 1,000 scraped places

Go to Apify Store
Google Maps Scraper

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

John Pratt

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Security

Limited permissions

Share

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?

DataFields
Businesstitle, category, descriptions, status, price_range
Contactphone, website, address, complete_address
Ratings and reviewsreview_rating, review_count, reviews_per_rating, user_reviews
Hours and trafficopen_hours, popular_times
Locationlatitude, longitude, plus_code, timezone
Google IDs and linksplace_id, cid, data_id, link, reviews_link, street_view_url
Extrasthumbnail, images, menu, reservations, order_online, owner, about, credit_cards_accepted

Every field is described in Output fields.

How to scrape Google Maps

  1. Open the Actor in Apify Console and go to the Input tab.
  2. Enter your searches in Search queries, one per line.
  3. Optionally raise Results depth to load more places for broad searches, or change the Language.
  4. Click Start. Searches run one after another.
  5. 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.

FieldTypeDefaultDescription
keywordsarray of stringsrequiredGoogle 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.
depthinteger, 1 or more10How 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.
languagestringenGoogle 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, CO rather than plumbers. 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, latitude and longitude are strings, so convert them before doing math.
  • Four fields are JSON text. menu, owner, reservations and order_online are JSON-encoded strings, for example "null" or "{\"link\":\"\",\"source\":\"\"}". Parse them with JSON.parse or json.loads.
  • Missing details are empty. Text fields are "" and object or array fields are null when Google has no data for them.
  • Two fields are always empty. emails is "" because the Actor doesn't visit business websites. user_reviews_extended is null because the Actor doesn't load extra review pages.
  • Reviews are a sample, taken from the place page, not the full review history.

Output fields

FieldTypeDescription
querystringThe search from keywords that returned this place.
input_idstringID of the search that found this place. Places from the same search share it.
titlestringBusiness name as shown on Google Maps.
categorystringMain category Google assigns to the place.
addressstringFull address on one line.
complete_addressobjectAddress parts: borough, street, city, postal_code, state, country.
phonestringPhone number as Google displays it.
websitestringBusiness website URL.
linkstringLink to the place on Google Maps.
review_ratingstringAverage star rating from 1 to 5, with six decimals.
review_countstringTotal number of Google reviews.
reviews_per_ratingobjectNumber of reviews for each star rating, keyed "1" to "5".
user_reviewsarraySample 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_extendednullAlways null in this Actor.
open_hoursobjectOpening hours per weekday. Each day maps to a list of time ranges.
popular_timesobjectHow 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.
statusstringStatus or summary line Google shows for the place.
descriptionsstringGoogle's description of the place.
price_rangestringPrice level or range, such as $$.
latitudestringLatitude in decimal degrees.
longitudestringLongitude in decimal degrees.
plus_codestringGoogle Plus Code for the location.
timezonestringIANA time zone, such as America/New_York.
place_idstringGoogle Place ID. Works with the Google Places API and as a stable key for the place.
cidstringGoogle's numeric ID for the place. https://maps.google.com/?cid=<cid> opens it.
data_idstringGoogle's internal place identifier.
reviews_linkstringLink to the place's reviews. Often empty.
thumbnailstringURL of the place's main photo.
imagesarrayPhotos from the place page, each with title and image (URL). Often empty.
street_view_urlstringStreet View link. Often empty.
reservationsstring (JSON)Reservation links, each with link and source. "null" when there are none.
order_onlinestring (JSON)Online ordering links, each with link and source. "null" when there are none.
menustring (JSON)Menu link with link and source. Both are empty when there is no menu.
ownerstring (JSON)Google account that manages the listing, with id, name and link.
credit_cards_acceptedstringComma-separated list of accepted cards.
aboutarrayAttributes from the About tab, grouped by section. Each section has id, name and options; each option has name and enabled.
emailsstringAlways 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:

  1. POST https://api.apify.com/v2/acts/qo6wnBx3a0y8TCEjZ/runs?token=YOUR_APIFY_TOKEN with the input as the JSON body. The response's data.id is the run ID and data.defaultDatasetId is the dataset ID.
  2. GET https://api.apify.com/v2/actor-runs/RUN_ID?token=YOUR_APIFY_TOKEN&waitForFinish=60 waits up to 60 seconds and returns the run. Repeat until data.status is SUCCEEDED, FAILED, TIMED-OUT or ABORTED.
  3. GET https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_APIFY_TOKEN&format=json returns the places. Use format=csv or format=xlsx for spreadsheets.

Python:

import requests
TOKEN = "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, TX that 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

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.

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.