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

Fast Google Maps scraper: business details, emails, social profiles, deep reviews, hours and geo. Grid/area coverage breaks Google's ~120-results-per-area limit.

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

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Google Maps Scraper

Extract structured business data from Google Maps at scale — fast, with a low, predictable cost.

Built on the [`gosom/google-maps-scraper`](https://github.com/gosom/google-maps-scraper) Go engine, wrapped with grid/area coverage, contact enrichment, proxy rotation and per-search result caps.

### Why this Actor

- **Breaks the 120-per-area limit.** Google Maps only shows ~120 results per view. Turn on **Area coverage** and the Actor sweeps a bounding box as a grid of cells, de-duplicating by place ID, so you get the full set.
- **Fast + cheap.** The Go engine is significantly lighter than a full browser crawler, so large jobs finish quicker and cost less.
- **Contact enrichment built in.** Optionally crawls each business website for emails, extra phone numbers and social-media profiles (Facebook, Instagram, LinkedIn, X/Twitter, YouTube, TikTok), with optional MX verification.
- **Real per-search caps.** `maxCrawledPlacesPerSearch` is enforced **per search term / URL**, not across the whole run.
- **Deep reviews.** Review pagination is on by default, so high-review places return their full review history, not just the first page.

### Input

| Field | Type | Notes |
|---|---|---|
| `searchStringsArray` | string\[] | Search terms / categories. Each runs as its own search with its own cap. |
| `startUrls` | url\[] | Google Maps place or search URLs to scrape directly. Location fields are not applied to these. |
| `locationQuery`, `city`, `state`, `county`, `postalCode` | string | Location parts, combined into one suffix appended to every search term. |
| `countryCode` | enum | ISO 3166-1 alpha-2. |
| `language` | enum | Google Maps interface language. Default `en`. |
| `maxCrawledPlacesPerSearch` | int | Cap per term/URL after filtering + dedupe. Default 100. |
| `areaSearch` | bool | Geocode the location to a bbox and grid-scrape it. |
| `customGeolocation` | object | Explicit area: GeoJSON Polygon/MultiPolygon, or `{southWest:{lat,lng}, northEast:{lat,lng}}`. Overrides `areaSearch`. |
| `gridCellKm`, `zoom` | int | Grid cell size and per-cell zoom. |
| `scrapePlaceDetailPage` | bool | Full detail page vs fast mode. Default true. |
| `extraReviews` | bool | Deep review pagination. Default true. |
| `scrapeContacts` | bool | Website crawl for email + phone + social. |
| `scrapeSocialMediaProfiles` | object | Which networks to keep. Enabling any turns enrichment on. |
| `verifyLeadsEnrichmentEmails` | bool | MX-record check per extracted email. |
| `placeMinimumStars` | enum | Minimum average rating. |
| `categoryFilterWords` | string\[] | Keep only places whose Google category contains one of these words. |
| `searchMatching` | enum | `all` / `only_includes` / `only_exact` on the place title. |
| `website` | enum | `allPlaces` / `withWebsite` / `withoutWebsite`. |
| `skipClosedPlaces` | bool | Drop closed places. |
| `maxConcurrency` | int | Parallel workers per search. Default 4. |
| `proxyConfiguration` | proxy | Apify Proxy. Residential recommended for large runs. |

At least one of `searchStringsArray` or `startUrls` is required.

### Output

One dataset item per place. Core fields from the engine include `title`, `address`, `phone`, `web_site`,
`review_rating`, `review_count`, `reviews_per_rating`, `categories`, `open_hours`, `popular_times`,
`price_range`, `latitude`, `longitude`, `place_id`, `cid`, `plus_code`, `images`, `thumbnail`,
`timezone`, plus review detail when `extraReviews` is on.

Added by this Actor:

| Field | When |
|---|---|
| `search_term`, `search_query` | always |
| `emails` | `scrapeContacts` and an email was found on the website |
| `emails_verified` | `verifyLeadsEnrichmentEmails` |
| `contact_phones` | contact enrichment found `tel:` links |
| `social_media` | contact enrichment found profile links |
| `enrichment_source` | set to `website_crawl` when any signal was added |

### Example

```json
{
  "searchStringsArray": ["coffee shop"],
  "locationQuery": "Ashburn, Virginia",
  "maxCrawledPlacesPerSearch": 50,
  "areaSearch": true,
  "gridCellKm": 3,
  "scrapeContacts": true,
  "verifyLeadsEnrichmentEmails": true,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Notes & limits

- Base image is pinned by digest for a stable CLI contract.
- Area/grid runs are much slower and produce more items than a single search — tune `gridCellKm` and `maxCrawledPlacesPerSearch`.
- Contact enrichment fetches third-party websites; results depend on how each site exposes its contact details.
- Email verification is an MX-record check only (no SMTP probe), so it confirms the domain can receive mail, not that a specific mailbox exists.

# Actor input Schema

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

Keywords or categories to search on Google Maps. Each term runs as its own search and gets its own result cap.

## `startUrls` (type: `array`):

Google Maps place or search URLs to scrape directly, instead of (or in addition to) search terms. Location fields are not applied to these.

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

Free-text location appended to every search term (e.g. 'Casablanca', 'Austin, Texas'). Use one location per run.

## `city` (type: `string`):

Structured location part (optional).

## `state` (type: `string`):

Structured location part (optional).

## `county` (type: `string`):

Structured location part (optional).

## `postalCode` (type: `string`):

Structured location part (optional).

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

ISO 3166-1 alpha-2 country code. Used to complete the location text.

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

Language of the Google Maps interface.

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

Upper bound of places kept for EACH search term / URL (after filtering and de-duplication).

## `areaSearch` (type: `boolean`):

Geocode the location to a bounding box and sweep it as a grid of cells. Breaks Google's ~120-results-per-area limit. Slower but far more complete.

## `customGeolocation` (type: `object`):

Explicit area to grid-scrape. A GeoJSON Polygon/MultiPolygon object, or {"southWest":{"lat":..,"lng":..},"northEast":{"lat":..,"lng":..}}. Overrides 'Area coverage'.

## `gridCellKm` (type: `integer`):

Side length of each grid cell when area coverage is on. Smaller = more complete + slower + more expensive.

## `zoom` (type: `integer`):

Google Maps zoom used per grid cell (1-21). 15 suits dense urban areas; lower for rural.

## `scrapePlaceDetailPage` (type: `boolean`):

Open each place page for full data (hours, images, attributes, price). Off = fast mode with reduced fields.

## `extraReviews` (type: `boolean`):

Scroll and paginate reviews instead of only the first page Google shows. Needed to get all review texts for high-review places.

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

Visit each place's website and extract email addresses, extra phone numbers and social-media profile links.

## `scrapeSocialMediaProfiles` (type: `object`):

Which social networks to keep when contact enrichment runs. Enabling any of these also turns enrichment on.

## `verifyLeadsEnrichmentEmails` (type: `boolean`):

For each extracted email, check that the domain has a valid mail server (MX record). Adds an emails\_verified field.

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

Keep only places with at least this average rating.

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

Keep only places whose Google category contains one of these words (case-insensitive). Empty = no category filter.

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

How strictly a place title must match the search term.

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

Filter results by website availability.

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

Drop places marked temporarily or permanently closed.

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

Parallel scraper workers inside a single search. Higher = faster but more memory and higher block risk.

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

Proxy used for scraping. Residential proxy is strongly recommended for anything beyond small runs.

## Actor input object example

```json
{
  "searchStringsArray": [
    "restaurant"
  ],
  "locationQuery": "New York",
  "countryCode": "",
  "language": "en",
  "maxCrawledPlacesPerSearch": 20,
  "areaSearch": false,
  "customGeolocation": null,
  "gridCellKm": 1,
  "zoom": 15,
  "scrapePlaceDetailPage": true,
  "extraReviews": true,
  "scrapeContacts": false,
  "scrapeSocialMediaProfiles": {
    "facebook": true,
    "instagram": true,
    "linkedin": true,
    "twitter": true,
    "youtube": true,
    "tiktok": true
  },
  "verifyLeadsEnrichmentEmails": false,
  "placeMinimumStars": "",
  "searchMatching": "all",
  "website": "allPlaces",
  "skipClosedPlaces": false,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every place scraped in this run (JSON).

## `overview` (type: `string`):

Key columns only.

## `contacts` (type: `string`):

Emails, phones and social profiles (requires scrapeContacts).

# 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",
    "maxCrawledPlacesPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("inablemassi/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",
    "maxCrawledPlacesPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("inablemassi/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",
  "maxCrawledPlacesPerSearch": 20
}' |
apify call inablemassi/google-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inablemassi/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/qVsjpUwj2fPHP67CO/builds/W4cgz4bGcEWl3aGhs/openapi.json
