# 📍📞 🆔 ⭐ 🌐 Google Maps Places Spider (`badruddeen/google-maps-places-spider`) Actor

A powerful Google Maps scraper that extracts listings from any location with intelligent deduplication & KV-backed delta tracking. Extract structured business data including: Business Name, Address, Phone number, Website, Google Maps short URL, Rating and Review Count. No hidden extra charges

- **URL**: https://apify.com/badruddeen/google-maps-places-spider.md
- **Developed by:** [Badruddeen Naseem](https://apify.com/badruddeen) (community)
- **Categories:** Developer tools, Automation, Lead generation
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 Places Spider

A powerful and lightweight Google Maps spider that extracts **real-world business data from Google Maps at global scale**.

Designed for **multi-keyword + multi-location scraping,** this actor is ideal for:

- lead generation
- market research
- large-scale business intelligence systems

---

### 🚀 What this scraper does

This actor runs multiple Google Maps searches in a single run, using:

- 🔑 Multiple keywords
- 🌍 Multiple locations
- 🔁 Combined search permutations (keyword × location)

Each combination is scraped independently and merged into a unified dataset.

---

### 📦 Extracted Data

Each place includes:

- 🏢 Business name
- 📍 Full address
- 📞 Phone number
- 🌐 Website (cleaned, tracking-free)
- ⭐ Review count (total number of reviews only)
- 🗺️ Google Maps URL
- 🆔 Place ID (unique identifier)

---

### 🌍 Key Features
- 🔎 Multi-keyword + multi-location scraping (core feature)
- 🌍 Global Google Maps coverage
- ⚡ Fast Playwright-based scraping engine
- 🧠 Smart deduplication (placeId-based)
- 🧾 Persistent Key-Value Store (KV) for incremental updates
- 🔁 Delta-based dataset rebuild system
- 🧹 Clean normalized output data
- 📦 Dataset export ready for CSV / JSON / CRM pipelines

---

### 💡 Multi-Search System (Important)

This actor builds search queries like:

- **{keyword} in {location}**

**Example**:

- dentist in Japan
- cafe in Ca SanFrancisco
- clinic in Berlin

- **Each combination is processed independently, enabling**:

- wide geographic coverage
- multi-niche data extraction
- scalable batch scraping

### 💡 Use Cases

This scraper is built for real-world business workflows:

- 📈 Lead generation for sales teams & agencies  
- 🏢 Local business intelligence  
- 🔍 Competitor research  
- 🧭 Market mapping by location  
- 📊 CRM data enrichment  
- 🌍 Travel, tourism, and hospitality analysis  

---

### ⚙️ Input Configuration

Example input:

```json
{
  "keywords": [
    "hotels",
    "restaurants",
    "cafes"
  ],
  "location": [
    "Berlin",
    "California",
    "Thailand"
  ],
  "maxResultsPerSearch": 20,
  "timeout": 60000,
  "forceRescrape": false
}
````

***

### 📤 Output Example

```json
{
  "name": "Hard Rock Hotel Maldives",
  "address": "Akasdhoo, Maldives",
  "phone": "+960 000 0000",
  "website": "https://example.com",
  "reviewsCount": 1243,
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:xxxx",
  "placeId": "ChIJxxxx"
}
```

***

### 🔁 Smart Deduplication System

This scraper uses a Key-Value Store caching system to:

- Avoid re-scraping the same place
- Skip unchanged entries
- Speed up repeated runs
- Reduce unnecessary API load

If you increase maxResultsPerSearch, the scraper will continue discovering new places globally.

***

### 🔁 Data Architecture (IMPORTANT)

This actor uses a dual-layer storage system:

#### 🗂 Key-Value Store (Source of Truth)

- Stores every scraped place individually

Used for:

- deduplication
- incremental updates
- long-term persistence

#### 📦 Dataset (Export Layer)

- Built only after successful run completion
- Contains clean, merged snapshot of KV data
- Used for download / API / integrations

⚠️ Important behavior:

- If the **run is aborted, KV data is preserved**
- But dataset is not updated for that run
- Re-running the actor rebuilds dataset from KV for new records - The aborted results remains in KV Store - You need to do a "Force Rescrape" if you want those place ID results in Dataset.

### 🌐 Global Search Capability

This actor is not limited by region.
You can search:

- Countries 🌍
- Cities 🏙️
- Niches (hotels, cafes, gyms, etc.)
- Mixed queries (e.g. “luxury resorts Maldives”)

**If it exists on Google Maps → it can be scraped.**

***

### 📊 Output Storage

Results are stored in:

📦 - Dataset (clean export-ready data)
🗂️ - Key-Value Store (deduplication + caching)

***

### 🧠 Important Notes

- Only publicly available Google Maps data is extracted
- No login required
- No API key needed
- No reviews text or ratings scraping (only review count)

***

### 🧾 Why use this scraper?

Because Google Maps is one of the richest sources of:

- Business leads
- Local company data
- Location intelligence
  This tool turns it into structured, usable data instantly.

***

### 📌 Perfect for

- Lead generation agencies
- SaaS founders
- Data analysts
- Growth hackers
- Marketing teams

***

### How to scrape Google Maps

It's easy to scrape Google Maps with Google Maps Places Spider. Just follow these few steps and you'll get your data in a few minutes.

1. Click on **Try for free** on the [actor page](https://apify.com/badrddeen/google-maps-places-spider).
2. Enter the location, search terms, or keywords you want to scrape.
3. Click on **Start**.
4. When Google Maps Places Spider has finished, preview or download your data from the **Dataset** tab.

***

### How much will it cost to scrape Google Maps?

**Apify gives you $5 in free usage credits every month** on the [Apify Free plan](https://apify.com/pricing). With those credits, you can scrape a substantial number of Google Maps listings completely free.

If you need to scrape Google Maps listings regularly, we recommend our [$29/month Starter plan](https://apify.com/pricing), which gives you significantly more computing power and data extraction capacity.

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

Our Google Maps actor costs $0.004 per scraped result (per place).

This means you only pay for successful extractions — not failed attempts or empty runs.

#### 📊 Example pricing

- 1,000 places → $4.00
- 5,000 places → $20.00
- 10,000 places → $40.00

So even large-scale datasets remain very affordable.

### 🆓 Free usage

Apify provides $5 in free monthly credits on the Apify Free plan.

With that, you can scrape:

\~1,250 places for free (at $0.004 per result)

### 🚀 Scaling up

For regular or high-volume scraping, the $29/month Starter plan is recommended. It gives you:[$29/month Starter plan](https://apify.com/pricing).

- higher compute limits
- more stable long-running runs
- better concurrency for large datasets

### ⚡ Summary

- 💲 Cost: $0.004 per place
- 🆓 Free tier: ~1,250 results/month
- 📈 Predictable scaling with usage

***

### ⚙️ Billing Behavior

Billing is based on per-place processing
Each successfully processed place triggers one charge event
Event name: google\_maps\_place

***

### Results

Google Maps Places Spider returns structured JSON data for each business listing:

```json
{
   "name": "Apify",
   "address": "123 Tech Street, San Francisco, CA 94105",
   "phoneNumber": "+1 (555) 123-4567",
   "website": "https://apify.com",
   "mapsUrl": "https://maps.app.goo.gl/abc123",
   "rating": 4.8,
   "reviewCount": 156
 }
```

### 🚀 Tips for scraping Google Maps?

Run the scraper, increase your search queries, and build massive global business datasets in minutes.

- Use specific location searches combined with category keywords for more targeted results
- Leverage the intelligent deduplication feature to avoid duplicate entries across multiple runs
- Use KV-backed delta tracking to only extract new or updated listings since your last run
- Break large geographic areas into smaller regions for more efficient scraping
- Allow sufficient time for the actor to process results, especially for high-volume searches

### Is it legal to scrape Google Maps?

Note that personal data is protected by GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

We also recommend that you read our blog post: [is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

# Actor input Schema

## `testMode` (type: `boolean`):

When enabled, skips real scraping and pushes 2 dummy sample results. Used by Apify automated tests to verify the Actor succeeds quickly. Leave OFF for normal use.

## `keywords` (type: `string`):

Comma-separated business keywords (e.g. Law Firm, Attorney, Personal Injury Lawyer, Immigration Lawyer, Legal Services)

## `location` (type: `string`):

Comma-separated locations (e.g. USA, UK, Singapore)

## `maxResultsPerSearch` (type: `integer`):

Maximum number of places to scrape per keyword search

## `forceRescrape` (type: `boolean`):

If enabled, ignores cached KV data and fully rescrapes all places

## `timeout` (type: `integer`):

Page timeout in milliseconds

## Actor input object example

```json
{
  "testMode": true,
  "keywords": "Law Firm, Attorney, Personal Injury Lawyer, Immigration Lawyer, Legal Services",
  "location": "DC, Washington",
  "maxResultsPerSearch": 50,
  "forceRescrape": false,
  "timeout": 120000
}
```

# Actor output Schema

## `runSummary` (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 = {
    "testMode": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("badruddeen/google-maps-places-spider").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 = { "testMode": True }

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

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

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

```

## CLI example

```bash
echo '{
  "testMode": true
}' |
apify call badruddeen/google-maps-places-spider --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=badruddeen/google-maps-places-spider",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "📍📞 🆔 ⭐ 🌐 Google Maps Places Spider",
        "description": "A powerful Google Maps scraper that extracts listings from any location with intelligent deduplication & KV-backed delta tracking. Extract structured business data including: Business Name, Address, Phone number, Website, Google Maps short URL, Rating and Review Count. No hidden extra charges",
        "version": "0.0",
        "x-build-id": "JioZLbsPbquzOYcdh"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/badruddeen~google-maps-places-spider/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-badruddeen-google-maps-places-spider",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/badruddeen~google-maps-places-spider/runs": {
            "post": {
                "operationId": "runs-sync-badruddeen-google-maps-places-spider",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/badruddeen~google-maps-places-spider/run-sync": {
            "post": {
                "operationId": "run-sync-badruddeen-google-maps-places-spider",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "keywords",
                    "location"
                ],
                "properties": {
                    "testMode": {
                        "title": "Test Mode",
                        "type": "boolean",
                        "description": "When enabled, skips real scraping and pushes 2 dummy sample results. Used by Apify automated tests to verify the Actor succeeds quickly. Leave OFF for normal use.",
                        "default": false
                    },
                    "keywords": {
                        "title": "Business Keywords",
                        "type": "string",
                        "description": "Comma-separated business keywords (e.g. Law Firm, Attorney, Personal Injury Lawyer, Immigration Lawyer, Legal Services)",
                        "default": "Law Firm, Attorney, Personal Injury Lawyer, Immigration Lawyer, Legal Services"
                    },
                    "location": {
                        "title": "Location / Area",
                        "type": "string",
                        "description": "Comma-separated locations (e.g. USA, UK, Singapore)",
                        "default": "DC, Washington"
                    },
                    "maxResultsPerSearch": {
                        "title": "Max Results Per Keyword",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of places to scrape per keyword search",
                        "default": 50
                    },
                    "forceRescrape": {
                        "title": "Force Full Rescrape",
                        "type": "boolean",
                        "description": "If enabled, ignores cached KV data and fully rescrapes all places",
                        "default": false
                    },
                    "timeout": {
                        "title": "Timeout",
                        "type": "integer",
                        "description": "Page timeout in milliseconds",
                        "default": 120000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
