# Google Maps Scraper (`acebuilds/google-maps-scraper`) Actor

Extract data from thousands of Google Maps places and businesses, including addresses, phone numbers, websites, ratings, review counts, emails, social profiles, opening hours, coordinates & more. Export data, run via API, schedule and monitor runs, or integrate with other tools.

- **URL**: https://apify.com/acebuilds/google-maps-scraper.md
- **Developed by:** [Ace](https://apify.com/acebuilds) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 scraped places

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Maps Scraper

### 📍 What is Google Maps Scraper?

Google Maps Scraper extracts data from Google Maps places and business listings: names, addresses, phone numbers, websites, ratings, review counts, opening hours, coordinates, place IDs, and emails and social profiles found on each business's website.

Use it to:

- 🎯 **Generate leads** — build lists of local businesses by category and city, with phone numbers and emails
- 🗂 **Build a Google Maps database** — export every dentist, plumber or restaurant in a city to CSV, Excel or JSON
- 🔍 **Find businesses without websites** — ideal prospects for web design, SEO and marketing agencies
- 📊 **Research markets and competitors** — compare ratings, review counts and coverage across areas
- 🤖 **Feed your apps and AI agents** — run it through the API, n8n, Make or Zapier

There is no Google Maps API key to set up and no browser extension to install. It runs in the cloud, and you pay only for the places you get.

#### What data does Google Maps Scraper extract?

| | | |
|---|---|---|
| 🏢 Business name | 🏷 Category and all categories | 📍 Full address, street, city, state, postcode, country |
| ☎️ Phone number (formatted + international) | 🌐 Website | ⭐ Rating (`totalScore`) |
| 💬 Review count | 🕒 Opening hours for every day | 🗺 Latitude and longitude |
| 🆔 Place ID, CID, FID, Knowledge Graph ID | 📝 Description | ♿ Amenities and accessibility (`additionalInfo`) |
| ✅ Claimed by owner + owner name | 🚫 Permanently / temporarily closed | 🖼 Main image URL |
| 📧 Emails *(add-on)* | 👥 Facebook, Instagram, LinkedIn, X, YouTube, TikTok *(add-on)* | 🔗 Google Maps and reviews links |

### ⬇️ Input

#### Search terms

Enter what you would type into Google Maps, one term per line: `dentist`, `coffee shop`, `roofing contractor`, `hotel`. Each term runs as its own search, and a place found by several terms is delivered and charged only once.

#### Location

Enter a city, region, postcode or country, such as `Austin, TX`, `Manchester, UK` or `10001`. Setting a location unlocks deep scraping (see [Using geolocation](#-using-geolocation-to-get-more-places)).

#### Search without a location

You can leave the location empty and put it in the search term instead, e.g. `pizza in Brooklyn`. Google returns at most ~120 places per plain search, so add a location when you need more.

#### Filters

| Filter | What it does |
|---|---|
| Minimum rating | Keep places rated 2+ … 4.5+ |
| Website | All places, only with a website, or only **without** a website |
| Skip closed places | Drop permanently or temporarily closed businesses |
| Category must contain | E.g. `dentist` keeps "Dentist" and "Cosmetic dentist" |
| Name must match | Keep places whose name contains or equals the search term |

Places removed by a filter are never charged.

#### Example input

```json
{
  "searchStringsArray": ["dentist"],
  "locationQuery": "Denver, CO",
  "maxCrawledPlacesPerSearch": 500,
  "scrapeContacts": true,
  "placeMinimumStars": "4"
}
```

### ⬆️ Output

#### Table view

The Overview table shows name, category, address, city, state, postcode, phone, website, rating, review count, emails and the Google Maps link. You can download it as CSV, Excel, JSON, XML or HTML.

#### JSON file

```json
{
  "title": "Epoch Coffee",
  "categoryName": "Coffee shop",
  "address": "221 W N Loop Blvd, Austin, TX 78751",
  "city": "Austin",
  "state": "Texas",
  "postalCode": "78751",
  "countryCode": "US",
  "location": { "lat": 30.3186037, "lng": -97.7245402 },
  "totalScore": 4.5,
  "reviewsCount": 2528,
  "phone": "(512) 454-3762",
  "phoneUnformatted": "+15124543762",
  "website": "http://www.epochcoffee.com/",
  "openingHours": [{ "day": "Monday", "hours": "12 AM–11:30 PM" }],
  "claimedByOwner": true,
  "permanentlyClosed": false,
  "placeId": "ChIJG-gJw2vKRIYROWi2uwOp8QE",
  "cid": "140078896924485689",
  "url": "https://www.google.com/maps/search/?api=1&query=Epoch%20Coffee&query_place_id=ChIJG-gJw2vKRIYROWi2uwOp8QE",
  "emails": ["madison@epochcoffee.com"],
  "facebooks": ["https://www.facebook.com/epochcoffee"],
  "instagrams": ["https://instagram.com/epochcoffee"]
}
```

Field names follow the most widely used Google Maps dataset format, so existing spreadsheets, CRM imports and Zapier/Make flows work without remapping.

### 📍📡 Using geolocation to get more places

A single Google Maps search stops at about 120 places. When you set a location, Google Maps Scraper:

1. Looks up the location's boundaries (city, county, state, country or postcode).
2. Splits the area into small map tiles, about 2.5 km across.
3. Searches every tile, starting from the centre, and removes duplicates.

This way you can scrape every business in a city, not just the first page. Set **Max places per search term** to `0` to scan the whole area, or to any number to stop earlier. Deep scraping turns on automatically above 120 places.

### 💰 How much does it cost to scrape Google Maps?

| Event | Price |
|---|---|
| Place scraped | **$0.004** per place ($4 per 1,000); cheaper on higher Apify plans |
| Filter applied | $0.001 per place, per active filter |
| Emails & social profiles | $0.002 per place — **charged only when at least one contact is found** |

Set a maximum cost per run in Apify, and the scraper stops cleanly when it reaches it.

### ❓FAQ

#### How does Google Maps Scraper work?

It reads the same data that the Google Maps website loads in your browser, about 20 places per request, without running a browser. That makes it fast and cheap. For emails, it visits each business's own website and its contact page.

#### What are the disadvantages of the Google Maps API?

The official Places API needs a Google Cloud billing account and charges per request. It returns at most 60 results per search, and it doesn't provide emails or social profiles. Google Maps Scraper has no search limit when you set a location, and it adds contacts from business websites.

#### Can I scrape places from multiple locations?

Yes. Run one location per run, or add several search terms that each include their place, e.g. `dentist in Austin` and `dentist in Dallas`. Places are de-duplicated across search terms.

#### How can I increase the speed of the scraper?

Raise **Parallel requests** (up to 10). Turning off the emails add-on also makes runs faster, because websites don't need to be visited.

#### Can I use Google Maps Scraper to extract Google reviews?

Each place includes its rating (`totalScore`), review count (`reviewsCount`) and a `reviewsUrl`. Full review text is not extracted yet.

#### Can I integrate Google Maps Scraper with other apps?

Yes. It works with Make, Zapier, n8n, Google Sheets, Airbyte, Slack, GitHub and any tool that accepts webhooks, through Apify integrations.

#### Can I use Google Maps Scraper as an API?

Yes. Start runs and fetch results with the [Apify API](https://docs.apify.com/api/v2). This makes it a Google Maps data API that you can call from any app.

#### Can I use this Google Maps Scraper API in Python?

Yes, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("acebuilds/google-maps-scraper").call(run_input={
    "searchStringsArray": ["plumber"],
    "locationQuery": "Chicago, IL",
    "maxCrawledPlacesPerSearch": 200,
})
for place in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(place["title"], place["phone"], place.get("website"))
```

#### Why did I get fewer places than my maximum?

The area may have fewer matching businesses, or your filters removed some. The run's `OUTPUT` record shows how many places each filter removed and whether Google blocked any request.

#### Is it legal to scrape Google Maps data?

Google Maps Scraper collects only publicly visible business information. If your results include personal data, such as owner names or personal emails, you must comply with GDPR, CCPA and similar laws, and use the data only for legitimate purposes. If you're unsure, ask a lawyer.

#### Your feedback

Found a bug or missing a field? Open an issue on the **Issues** tab, and it will be looked at quickly.

# Actor input Schema

## `searchStringsArray` (type: `array`):

What to search on Google Maps, one term per line — e.g. "dentist", "coffee shop", "plumber". Each term runs as its own search.

## `locationQuery` (type: `string`):

City, region, postcode or country — e.g. "Austin, TX" or "Berlin, Germany". Setting a location unlocks deep scraping beyond Google's ~120-results-per-search limit.

## `maxCrawledPlacesPerSearch` (type: `integer`):

Stop each search term after this many places. 0 = no limit (the whole location is scanned tile by tile).

## `deeperCityScrape` (type: `boolean`):

Split the location into small map tiles and search each one. Finds far more places than a single search. Turned on automatically when the max is 0 or above 120.

## `language` (type: `string`):

Language for place data, as a 2-letter code (en, de, es, fr…).

## `countryCode` (type: `string`):

Optional 2-letter country code (us, gb, de…) to bias results toward that country.

## `scrapeContacts` (type: `boolean`):

Visit each place's website and extract emails plus Facebook, Instagram, LinkedIn, X, YouTube and TikTok links. Billed only for places where at least one contact is actually found.

## `placeMinimumStars` (type: `string`):

Only keep places rated at least this high.

## `website` (type: `string`):

Keep all places, only places with a website, or only places without one (great for web-design lead lists).

## `skipClosedPlaces` (type: `boolean`):

Drop places marked permanently or temporarily closed.

## `categoryFilterWords` (type: `array`):

Only keep places whose Google category contains one of these words, e.g. "dentist" keeps "Cosmetic dentist" and "Dentist".

## `searchMatching` (type: `string`):

Keep only places whose name contains, or exactly equals, the search term.

## `maxConcurrency` (type: `integer`):

How many map tiles to search at once.

## `proxyConfiguration` (type: `object`):

Leave empty — the actor picks Apify Proxy automatically and switches to residential if Google blocks.

## Actor input object example

```json
{
  "searchStringsArray": [
    "restaurant"
  ],
  "locationQuery": "New York, USA",
  "maxCrawledPlacesPerSearch": 10,
  "deeperCityScrape": false,
  "language": "en",
  "countryCode": "",
  "scrapeContacts": false,
  "placeMinimumStars": "",
  "website": "allPlaces",
  "skipClosedPlaces": false,
  "categoryFilterWords": [],
  "searchMatching": "all",
  "maxConcurrency": 4
}
```

# Actor output Schema

## `places` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchStringsArray": [
        "restaurant"
    ],
    "locationQuery": "New York, USA",
    "maxCrawledPlacesPerSearch": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("acebuilds/google-maps-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchStringsArray": ["restaurant"],
    "locationQuery": "New York, USA",
    "maxCrawledPlacesPerSearch": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("acebuilds/google-maps-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchStringsArray": [
    "restaurant"
  ],
  "locationQuery": "New York, USA",
  "maxCrawledPlacesPerSearch": 10
}' |
apify call acebuilds/google-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,acebuilds/google-maps-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/U1jjfOU5qV1He1Ngj/builds/yHsv35W7LE3RFO3hD/openapi.json
