# Fast Google Maps Scraper (`solutionssmart/fast-google-map-scraper`) Actor

HTTP-first Google Maps scraper for search listings, place details, reviews, lead scoring, and optional website enrichment.

- **URL**: https://apify.com/solutionssmart/fast-google-map-scraper.md
- **Developed by:** [Solutions Smart](https://apify.com/solutionssmart) (community)
- **Categories:** Lead generation, Automation, Travel
- **Stats:** 7 total users, 1 monthly users, 100.0% runs succeeded, 1 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

## Fast Google Maps Scraper

A lightweight Google Maps lead scraper built for low-cost prospecting. It uses a fast HTTP-first pipeline, optional deep details, and built-in opportunity scoring so you do not spend browser compute on every lead.

### What it does

- `list` mode searches Google Maps and saves lightweight listing rows only. This is the cheapest mode.
- `place` mode scrapes one known Google Maps `placeId`.
- `search` mode searches, fetches full place details, and optionally fetches reviews.
- `outputMode` controls whether the Dataset contains all records, only places and reviews, or places only.
- Supports concurrent place detail and review scraping in `search` mode.
- Pushes every result immediately to the Apify Dataset.
- Saves a run summary to Key-Value Store record `OUTPUT`.
- Supports Apify Proxy and a manual proxy URL fallback.
- Adds lead scoring for every full place record.
- Optionally enriches business websites with title, description, emails, and social links.
- Supports pay-per-event monetization with charged Dataset writes for `place-listed`, `place-detail`, and `review`.

### Input

The Actor uses `.actor/input_schema.json`, so configuration is available as a typed Apify Console form.

Important fields:

- `mode`: `list`, `place`, or `search`.
- `outputMode`: `allRecords`, `placesAndReviews`, or `placesOnly`.
- `query`: business/category query required for `list` and `search`, for example `coffee shops`.
- `searchLocation`: free-form location, for example `Berlin, Germany`.
- `geolocationParameters`: grouped country, state/region, county, city, and postal code fields used when `searchLocation` is empty.
- `customGeolocation`: grouped geometry type, coordinates, radius, latitude, longitude, and coordinates JSON fields for anchoring the map area.
- `leadFilters`: optional minimum rating, minimum review count, website, phone, and category filters.
- `websiteEnrichmentDepth`: `homepageOnly` or `contactPages`.
- `websiteTimeoutSeconds`: separate short timeout for website enrichment requests.
- `skipSocialWebsites`: skips enrichment of social profile URLs by default to reduce slow tails and 429 responses.
- `placeId`: required for `place`.
- `maxPlaces`: maximum places to list or scrape.
- `maxReviews`: reviews per place. Use `0` to skip reviews.
- `maxTotalReviews`: global review cap across the run. Use `0` for no global cap.
- `maxConcurrency`: number of places to scrape in parallel in `search` mode.
- `language`: Google `hl` parameter.
- `gl`: Google country parameter.
- `proxyConfiguration`: Apify Proxy settings.
- `delaySeconds`: randomized delay between requests.
- `enableSqliteCheckpoint`: optional internal SQLite copy for deduplication/checkpointing.
- `enrichWebsites`: optional website enrichment.
- `enableBillingEvents`: legacy testing flag. Production monetization is detected from Apify pay-per-event pricing.

### Output

Dataset records are streamed as they are found:

- `recordType: "listing"` for search results.
- `recordType: "place"` for full place detail records with lead scoring.
- `recordType: "review"` for individual reviews.

Output modes:

- `allRecords`: saves listings, places, and reviews.
- `placesAndReviews`: saves full places and reviews, but skips listing rows.
- `placesOnly`: saves only full place records and skips review fetching.

The `OUTPUT` key-value store record contains:

- mode and query
- start and finish timestamps
- places listed
- places scraped
- reviews scraped
- duplicates skipped
- failed places
- website enrichments
- skipped website enrichments

### Lead scoring

Each full place record includes:

```json
{
  "leadScore": {
    "score": 80,
    "tier": "hot",
    "reasons": ["Has phone", "Has website", "High rating"]
  }
}
```

Signals include phone, website presence or absence, rating, review volume, opening hours, photos, booking links, and commercial local categories.

### Example input

```json
{
  "mode": "search",
  "outputMode": "placesAndReviews",
  "query": "dentists",
  "searchLocation": "Austin, United States",
  "customGeolocation": {
    "latitude": 30.2672,
    "longitude": -97.7431
  },
  "maxPlaces": 25,
  "maxReviews": 20,
  "maxTotalReviews": 200,
  "maxConcurrency": 3,
  "language": "en",
  "gl": "us",
  "delaySeconds": 1.5,
  "enrichWebsites": true,
  "websiteEnrichmentDepth": "contactPages",
  "websiteTimeoutSeconds": 8,
  "skipSocialWebsites": true,
  "leadFilters": {
    "minRating": 4.0,
    "mustHaveWebsite": true
  },
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

### Cost notes

Use `list` mode when you only need names, ratings, categories, addresses, coordinates, and place IDs. It avoids detail and review endpoints.

Use `search` mode when you need complete lead records. Set `maxReviews` to `0` if reviews are not needed.

Use `placesOnly` when you want a lead list without review rows. It skips review fetching even if `maxReviews` is greater than `0`.

The default prefilled input is intentionally small: 5 places, `placesOnly`, and no reviews. This keeps Apify Store automated QA runs fast and gives new users a low-cost first test. Increase `maxPlaces`, switch output mode, and enable reviews for production runs.

`maxReviews` is a per-place limit. For example, `maxPlaces: 20` and `maxReviews: 50` can produce up to 1,000 reviews. Use `maxTotalReviews` when you want a global cap.

Increase `maxConcurrency` to process multiple places in parallel. Start with `2` or `3` when using proxies. Higher values can reduce runtime, but they also increase request pressure and blocking risk.

Website enrichment adds extra HTTP requests and should be enabled only when you need emails, social links, or website metadata.

`websiteEnrichmentDepth: "homepageOnly"` fetches only the listed website homepage. `contactPages` also follows likely contact, about, Kontakt, and Impressum links found on the homepage. This can find more emails, but it costs extra requests and some sites may rate-limit.

`websiteTimeoutSeconds` is independent from the main Google Maps request timeout. Keep it low, such as `6` to `8`, when you want predictable cost. `skipSocialWebsites` is enabled by default because social profile URLs rarely expose emails and often return 429 or slow responses through proxies.

Lead filters are applied after full place details are fetched:

```json
{
  "leadFilters": {
    "minRating": 4.2,
    "minReviewCount": 25,
    "mustHaveWebsite": true,
    "mustHavePhone": false,
    "categoryIncludes": "cafe"
  }
}
```

Filtered places are counted in the `OUTPUT.filteredPlaces` summary and skipped from Dataset output and review fetching.

### Location targeting

You can target by city and country:

```json
{
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany",
  "gl": "de"
}
```

Or use structured geolocation fields:

```json
{
  "query": "coffee shops",
  "geoCountry": "Germany",
  "geolocationParameters": {
    "country": "Germany",
    "city": "Berlin",
    "postalCode": "10117"
  },
  "gl": "de"
}
```

You can also add custom latitude and longitude to anchor the map area:

```json
{
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany",
  "customGeolocation": {
    "latitude": 52.520008,
    "longitude": 13.404954
  },
  "zoom": 13,
  "gl": "de"
}
```

For coordinate-heavy workflows, use `customCoordinates` as simple text:

```json
{
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany",
  "customGeolocation": {
    "coordinates": "52.520008, 13.404954",
    "radiusKm": 5
  }
}
```

Or use `coordinatesJson` with a GeoJSON point:

```json
{
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany",
  "customGeolocation": {
    "coordinatesJson": "{\"type\":\"Point\",\"coordinates\":[13.404954,52.520008]}"
  }
}
```

# Actor input Schema

## `mode` (type: `string`):

list searches only and is cheapest; place scrapes one known place ID; search lists places, fetches details, and optionally reviews.

## `outputMode` (type: `string`):

Choose which records are saved to the Dataset. list mode always returns listing records.

## `query` (type: `string`):

Business/category query, for example 'dentists' or 'coffee shops'. Required for list and search mode.

## `searchLocation` (type: `string`):

Free-form location such as Berlin, Germany. Used together with the search query.

## `geolocationParameters` (type: `object`):

Optional structured location fields. These are used when the free-form location is empty.

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

Optional geometry and coordinate fields for anchoring the Google Maps search area.

## `placeId` (type: `string`):

Known Google Maps place ID. Required for place mode.

## `maxPlaces` (type: `integer`):

Maximum number of search results to list or fully scrape.

## `maxReviews` (type: `integer`):

Maximum reviews to fetch for each place. Set to 0 to skip reviews.

## `maxTotalReviews` (type: `integer`):

Global review cap across the whole run. Set to 0 for no global cap.

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

Number of places to scrape in parallel in search mode. Higher values are faster but can increase blocking risk.

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

Google Maps zoom level. Higher values narrow the search area.

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

Google hl language parameter.

## `gl` (type: `string`):

Google gl country parameter.

## `delaySeconds` (type: `number`):

Minimum delay between HTTP requests. Actual delay is randomized up to 2x this value.

## `timeoutSeconds` (type: `integer`):

HTTP request timeout in seconds.

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

Use Apify Proxy or custom proxies.

## `proxyUrl` (type: `string`):

Optional direct proxy URL used when Apify Proxy is disabled.

## `enrichWebsites` (type: `boolean`):

Fetch listed websites to extract title, description, emails, and social links.

## `websiteEnrichmentDepth` (type: `string`):

Homepage only is fastest. Contact pages also checks contact/about/impressum pages for emails and social links.

## `websiteTimeoutSeconds` (type: `integer`):

Timeout for each website enrichment request. Keep this lower than the Google Maps timeout to avoid slow websites increasing run cost.

## `skipSocialWebsites` (type: `boolean`):

Skip website enrichment when Google Maps lists a social profile such as Instagram, Facebook, LinkedIn, X, or Twitter. This is faster and avoids many 429 responses.

## `leadFilters` (type: `object`):

Optional filters applied after full place details are fetched. Filtered places are skipped from Dataset output and reviews.

## `enableSqliteCheckpoint` (type: `boolean`):

Keep an internal SQLite copy for deduplication/checkpointing. Dataset remains the primary output.

## `sqlitePath` (type: `string`):

Internal SQLite path when checkpointing is enabled.

## `enableBillingEvents` (type: `boolean`):

Legacy testing flag. Production monetization is enabled automatically when pay-per-event pricing is configured in Apify Console. For local tests, use ACTOR\_TEST\_PAY\_PER\_EVENT=true.

## Actor input object example

```json
{
  "mode": "search",
  "outputMode": "placesOnly",
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany",
  "maxPlaces": 5,
  "maxReviews": 0,
  "maxTotalReviews": 0,
  "maxConcurrency": 3,
  "zoom": 13,
  "language": "en",
  "gl": "de",
  "delaySeconds": 0.5,
  "timeoutSeconds": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "enrichWebsites": false,
  "websiteEnrichmentDepth": "homepageOnly",
  "websiteTimeoutSeconds": 8,
  "skipSocialWebsites": true,
  "enableSqliteCheckpoint": false,
  "sqlitePath": "storage/key_value_stores/default/gmaps.db",
  "enableBillingEvents": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items generated by the Actor. Depending on outputMode, this can include listing, place, and review records.

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

Key-value store OUTPUT record with counters, timing, effective query, location, filters, and run status.

# 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 = {
    "query": "coffee shops",
    "searchLocation": "Berlin, Germany"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solutionssmart/fast-google-map-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 = {
    "query": "coffee shops",
    "searchLocation": "Berlin, Germany",
}

# Run the Actor and wait for it to finish
run = client.actor("solutionssmart/fast-google-map-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 '{
  "query": "coffee shops",
  "searchLocation": "Berlin, Germany"
}' |
apify call solutionssmart/fast-google-map-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solutionssmart/fast-google-map-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/fyyQzl7Sfh8Zmqdfx/builds/pSMqFNo3pbRiV4hj0/openapi.json
