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

Extract data from thousands of locations: get reviews, pricing, photos, and B2B contact info (names, emails, titles). Automate your workflow by scheduling recurring runs, monitoring performance, and integrating directly via our API.

- **URL**: https://apify.com/pimperp/google-maps-scraper.md
- **Developed by:** [F](https://apify.com/pimperp) (community)
- **Categories:** Automation, Lead generation, Real estate
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 4.83 out of 5 stars

## Pricing

from $1.95 / 1,000 record scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Custom Target Schema Scraper

A production-ready Apify Actor designed to scrape Google Maps business profiles. This scraper extracts deep, comprehensive data and formats its JSON output in a clean, structured schema.

### 💰 Pricing & Monetization

This Actor is billed under a highly transparent **Pay per event + usage** model:
*   **Actor Start**: **$0.05 per 1,000 runs** ($0.00005 flat rate per run).
*   **Record Scraped**: **$1.95 per 1,000 places** ($0.00195 per successfully scraped record).

---

### 🚀 Features

- **Structured Outputs**: Output objects are organized in a clean, consistent, industry-standard schema format.
- **Dynamic Content Support**: Fully renders modern interactive pages to extract dynamic lists and profiles seamlessly.
- **Advanced Anti-Detection Measures**:
  - **Ghost-Cursor**: Emulates human-like bezier-curve mouse movements prior to clicks to bypass Google's advanced bot detection.
  - Automatically avoids rate limits and IP bans to ensure stable scraping.
  - Automatically dismisses cookie consent banners.
- **Deep Extraction Strategy**:
  - **Fuzzy Match Fallback**: Utilizes Dice's Coefficient string similarity to accurately resolve and click the correct business when Google returns an ambiguous list view.
  - Extracts core data (Title, Rating, Coordinates, Address, Plus Codes).
  - Decomposes addresses into logical segments (Street, Neighborhood, City, State, Country).
  - Captures reviews distribution, booking links, and restaurant reservation providers.
  - Grabs "People Also Search For", similar nearby hotels, and hotel ads.
  - Extracts photo gallery metadata (including author, URL, and upload dates).
  - Gathers extended review metadata (including translation status, reviewer photos, detailed sub-ratings).
- **Data Sanitization Pipeline**: Built-in middleware aggressively scrubs zero-width spaces, invisible byte-order marks, and soft hyphens to guarantee pristine string formatting.
- **Fast & Efficient**: Optimized to scrape data quickly while minimizing execution time and cost.

### Prerequisites

- [Node.js](https://nodejs.org/en/) (v18 or higher recommended)
- [Apify CLI](https://docs.apify.com/cli) (if running or deploying to the Apify Platform)

### Installation

```bash
## Clone or download the repository
cd apify_scrapper

## Install dependencies
npm install
````

### Running Locally

To run the scraper locally, you must provide valid input data matching the expected schema.

1. Create a directory named `apify_storage/key_value_stores/default`.
2. Inside that directory, create a file named `INPUT.json` with the following format:

```json
{
  "searchStrings": ["Best coffee shops in Seattle", "Pizza in NYC"],
  "maxResultsPerSearch": 20,
  "language": "en",
  "maxReviews": 5,
  "maxImages": 5
}
```

3. **Important**: Because this scraper requires Residential Proxies to bypass Google's blocks, you must run the scraper with your Apify API token exported to your environment:

```bash
## Export your Apify API Token
export APIFY_TOKEN="your_apify_api_token_here"

## Start the scraper
npm start
```

Extracted data will be saved to `apify_storage/datasets/default/`.

### 🐍 Programmatic Integration (Python)

You can run this Actor programmatically from your Python applications using the official `apify-client` library.

#### 1. Install Apify Client

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

#### 2. Python Code Example

```python
from apify_client import ApifyClient

## Initialize the Apify Client with your Apify API Token
client = ApifyClient("your_apify_api_token_here")

## Define the scraper inputs
run_input = {
    "searchStrings": ["Pizza Hut, Boston"],
    "maxResultsPerSearch": 10,
    "language": "en",
    "maxSearchRadius": 5,
    "searchRadiusUnit": "km"
}

## Run the Actor and wait for its completion
run = client.actor("google-maps-custom-target-schema-scraper").call(run_input=run_input)

## Fetch and print the scraped results from the default dataset
dataset = client.dataset(run["defaultDatasetId"])
for item in dataset.iterate_items():
    print(f"Name: {item.get('title')}")
    print(f"Phone: {item.get('phone')}")
    print(f"Address: {item.get('address')}")
    print(f"Distance: {item.get('distanceFromSearchCenter')} {item.get('distanceUnit')}")
    print("-" * 40)
```

### Detailed Input Parameters

The Actor accepts the following JSON input parameters. These fields control what is searched and how deeply each profile is scraped.

#### Ways to Search

You can target places using different search patterns based on your needs. Below are examples of how to configure your inputs:

##### 1. Search by Business Name or Keyword (`searchStrings`)

Perfect for scraping matching businesses across a city or general keywords.

- **Plain Search**: `["Pizza in Boston", "Dentists near Central Park"]`
- **Specific Business Name**: `["Union Oyster House Boston", "Giacomo's Restaurant Boston"]`

Example Input:

```json
{
  "searchStrings": ["Seafood in Boston", "Union Oyster House Boston"]
}
```

##### 2. Search by Latitude and Longitude (Geographic Viewport)

To search within a specific geographic coordinate area, use a Google Maps search URL with `@latitude,longitude,zoomz` coordinate parameters inside `startUrls`. The scraper will search only within that specific map viewport.

- **Format**: `https://www.google.com/maps/search/<query>/@<lat>,<lng>,<zoom>z`
- **Example (Restaurants near Boston Common)**: `https://www.google.com/maps/search/restaurants/@42.3554,-71.0640,16z`

Example Input:

```json
{
  "startUrls": [
    "https://www.google.com/maps/search/restaurants/@42.3554,-71.0640,16z"
  ]
}
```

##### 3. Search by Polygons / Custom Areas (Grid Viewport Split)

Since Google Maps doesn't support drawing arbitrary polygons directly, you can scrape custom-shaped regions by splitting your polygon into a grid of overlapping coordinate viewports, and adding their search URLs to `startUrls`.

- **Example (Scraping two adjacent grid viewports covering a custom shape in the North End)**:
  1. Viewport 1 (North End West): `https://www.google.com/maps/search/cafes/@42.3642,-71.0545,17z`
  2. Viewport 2 (North End East): `https://www.google.com/maps/search/cafes/@42.3655,-71.0510,17z`

Example Input:

```json
{
  "startUrls": [
    "https://www.google.com/maps/search/cafes/@42.3642,-71.0545,17z",
    "https://www.google.com/maps/search/cafes/@42.3655,-71.0510,17z"
  ]
}
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchStrings` | `Array` | `[]` | A list of Google Maps search queries. (Accepts strings or arrays, parsed safely with default fallback.) |
| `startUrls` | `Array` | `[]` | Direct Google Maps place URLs to scrape. (Accepts strings or arrays, parsed safely with default fallback.) |
| `maxResultsPerSearch` | `Integer` | `20` | The maximum number of place profiles to scrape per search query. Defaults to `20` if missing, invalid, or malformed. |
| `language` | `String` | `"en"` | The language code appended to the Google Maps URLs (e.g., `"en"`, `"ar"`, `"es"`). |
| `maxReviews` | `Integer` | `0` | The maximum number of individual reviews to extract per place. Defaults to `0` if invalid. |
| `maxImages` | `Integer` | `0` | The maximum number of image URLs to collect per place. Defaults to `0` if invalid. |
| `maxSearchRadius` | `Number` | `null` | The maximum distance from the search center coordinates. Skipped if null, empty string, or invalid. |
| `searchRadiusUnit` | `String` | `"km"` | Unit of measurement for the maximum search radius: `"km"` (Kilometers) or `"mi"` (Miles). |
| `searchCenterLat` | `Number` | `null` | Optional manual override for the search center latitude. Parse-safe float. |
| `searchCenterLng` | `Number` | `null` | Optional manual override for the search center longitude. Parse-safe float. |

***

#### 🌍 Internationalization & Arabic Localization Support

The scraper features robust built-in support for localized Middle-Eastern addresses and Arabic text parsing to prevent parsing errors and data loss:

- **Arabic Commas (`،` - U+060C)**: Google Maps profiles in Arabic regions use standard commas `,` and Arabic commas `،`. The parser splits on both `/[,،]/` to cleanly segment street, neighborhood, and city.
- **Arabic Country Mappings**: Mappings are configured for Arabic country names (e.g. `"السعودية"` or `"المملكة العربية السعودية"` for Saudi Arabia, `"الامارات"`/`"الإمارات"` for United Arab Emirates, etc.) to successfully resolve ISO-2 country codes (like `SA`, `AE`, `QA`, `BH`, `KW`, `OM`, `EG`, `JO`, `LB`).
- **Asynchronous Search Resolving**: Handles client-side JS redirects on single place searches dynamically before trying to extract feeds, preventing timeouts or empty results on direct business matches.

***

### Exhaustive Output Data Structure

The output dataset is formatted as a structured JSON object. Below is a complete breakdown of every single key you will find in the output JSON objects.

#### Core Metadata & Search Context

- **`searchString`** *(String)*: The original query used to find this place.
- **`rank`** *(Integer)*: The position of this place in the search results (1-indexed).
- **`searchPageUrl`** *(String)*: The URL of the search results page.
- **`searchPageLoadedUrl`** *(String)*: The final URL after redirects.
- **`isAdvertisement`** *(Boolean)*: `true` if this place was a sponsored ad in the search results.

#### Place Identity & Basics

- **`title`** *(String)*: The business name.
- **`subTitle`** *(String)*: The subtitle shown below the business name on Google Maps.
- **`description`** *(String)*: The editorial summary/description written by Google.
- **`categoryName`** *(String)*: The primary category of the business (e.g., "Pizza restaurant").
- **`categories`** *(Array)*: A list of all categories assigned to the business.
- **`price`** *(String)*: The price tier (e.g., `"$"` or `"$$$"`).
- **`totalScore`** *(Float)*: The overall star rating out of 5.0.
- **`reviewsCount`** *(Integer)*: The total number of reviews.

#### Location & Contact

- **`address`** *(String)*: The full, unparsed address string.
- **`street`** *(String)*: Parsed street address.
- **`neighborhood`** *(String)*: The specific neighborhood or district.
- **`city`** *(String)*: Parsed city name.
- **`state`** *(String)*: The full state or province name (e.g., "New York", not "NY").
- **`postalCode`** *(String)*: Parsed ZIP or postal code.
- **`countryCode`** *(String)*: The two-letter country code (e.g., "US", "GB").
- **`location`** *(Object)*: Contains the exact `lat` and `lng` coordinates.
- **`locatedIn`** *(String)*: If the business is located inside another building/mall.
- **`plusCode`** *(String)*: The Google Plus Code for the location.
- **`phone`** *(String)*: The formatted phone number.
- **`phoneUnformatted`** *(String)*: The raw phone number string with non-numeric characters removed.
- **`website`** *(String)*: The business's primary website URL.
- **`distanceFromSearchCenter`** *(Float)*: Calculated distance between the place and the resolved search center (in `distanceUnit`), or `null` if coordinates couldn't be resolved.
- **`distanceUnit`** *(String)*: The unit used for distance calculations (`"km"` or `"mi"`), or `null`.

#### Identifiers

- **`placeId`** *(String)*: The Google Maps Place ID.
- **`cid`** *(String)*: The unique Customer ID (decimal BigInt format).
- **`fid`** *(String)*: The Google Feature ID.
- **`kgmid`** *(String)*: The Knowledge Graph Machine ID.
- **`url`** *(String)*: The canonical Google Maps URL for this profile.

#### Business Status & Features

- **`claimThisBusiness`** *(Boolean)*: `true` if the business profile is unverified/unclaimed.
- **`permanentlyClosed`** *(Boolean)*: `true` if marked permanently closed.
- **`temporarilyClosed`** *(Boolean)*: `true` if marked temporarily closed.
- **`operationalStatusText`** *(String)*: Text indicator of current operational status (e.g., `"Open"`, `"Closed"`).
- **`openingHours`** *(Array)*: An array of objects `[{ day, hours }]`.
- **`additionalInfo`** *(Object)*: Contains nested arrays of strings for various amenities and features.

#### Media & Engagement

- **`imageUrl`** *(String)*: The primary hero image URL for the business.
- **`imagesCount`** *(Integer)*: Total number of photos uploaded to the profile.
- **`imageCategories`** *(Array)*: The tab labels for photos (e.g., "All", "Menu", "Food").
- **`images`** *(Array)*: Detailed metadata for scraped images. Each object contains `imageUrl`, `authorName`, `authorUrl`, and `uploadedAt`.
- **`imageUrls`** *(Array)*: A flat list of the raw image URLs.

#### Reviews Data

- **`reviewsDistribution`** *(Object)*: Counts of reviews by star rating: `{ oneStar, twoStar, threeStar, fourStar, fiveStar }`.
- **`reviewsTags`** *(Array)*: Popular keywords mentioned in reviews, e.g., `[{ title: "pizza", count: 45 }]`.
- **`topRelevantReviews`** *(Array)*: Snippets of the top 5 'Relevant' reviews extracted directly from the main overview tab.
- **`reviews`** *(Array)*: Detailed individual reviews. Each object contains:
  - `name`, `reviewerId`, `reviewerUrl`, `reviewerPhotoUrl`, `reviewerNumberOfReviews`, `isLocalGuide`
  - `publishAt`, `publishedAtDate`
  - `text`, `textTranslated`, `rating`, `stars`
  - `likesCount`, `reviewId`, `reviewUrl`, `reviewOrigin`, `reviewImageUrls`
  - `reviewContext`, `reviewDetailedRating` (e.g., `{"Food": 5, "Service": 4}`)
  - `responseFromOwnerDate`, `responseFromOwnerText`

#### Specialized Entities

- **`restaurantData`** *(Object)*: Contains booking provider info: `{ tableReservationProvider: { name, reserveTableUrl } }`.
- **`menu`** *(String)*: Direct link to the menu.
- **`reserveTableUrl`** *(String)*: Direct link to book a table.
- **`googleFoodUrl`** *(String)*: Direct link to order food via Google.
- **`hotelStars`** *(String)*: Descriptive hotel rating (e.g., "4-star hotel").
- **`hotelDescription`** *(String)*: Editorial hotel description.
- **`hotelAds`** *(Array)*: Booking ads `{ title, googleUrl, isOfficialSite, price, url }`.
- **`similarHotelsNearby`** *(Array)*: Competitors `{ name, rating, reviews, description, price }`.
- **`peopleAlsoSearch`** *(Array)*: Related businesses `{ category, title, reviewsCount, totalScore }`.

***

### 📊 Sample Output JSON

Below is a complete, realistic sample of a successfully scraped Google Maps place record, showing all the fields populated by the Actor:

```json
{
  "searchString": "Pizza Hut, Boston",
  "rank": 1,
  "searchPageUrl": "https://www.google.com/maps/search/Pizza%20Hut%2C%20Boston?hl=en",
  "searchPageLoadedUrl": "https://www.google.com/maps/search/Pizza%20Hut%2C%20Boston?hl=en",
  "isAdvertisement": false,
  "title": "Pizza Hut",
  "subTitle": null,
  "description": "Popular delivery, carry-out & dine-in chain known for pizza, wings & pasta, plus sides & desserts.",
  "price": "$",
  "categoryName": "Pizza delivery",
  "address": "7 Sycamore St, Everett, MA 02149, United States",
  "neighborhood": "Everett",
  "street": "7 Sycamore St",
  "city": "Everett",
  "postalCode": "02149",
  "state": "Massachusetts",
  "countryCode": "US",
  "website": "https://locations.pizzahut.com/ma/everett/7-sycamore-st",
  "phone": "+1 781-321-3335",
  "phoneUnformatted": "+17813213335",
  "claimThisBusiness": false,
  "location": {
    "lat": 42.4144303,
    "lng": -71.0467333
  },
  "locatedIn": "Glendale Square",
  "plusCode": "CX73+Q8 Everett, Massachusetts, USA",
  "menu": "https://www.pizzahut.com/c/content/menu",
  "servicesLink": null,
  "totalScore": 3.6,
  "permanentlyClosed": false,
  "temporarilyClosed": false,
  "operationalStatusText": "Open",
  "placeId": "ChIJkeNmq51x44kRyEDnYBTWnsk",
  "categories": [
    "Pizza delivery",
    "Pizza restaurant"
  ],
  "fid": "0x89e3719dab66e391:0xc99ed61460e740c8",
  "cid": "14528284830957256904",
  "reviewsCount": 843,
  "reviewsDistribution": {
    "oneStar": 190,
    "twoStar": 36,
    "threeStar": 19,
    "fourStar": 115,
    "fiveStar": 365
  },
  "imagesCount": 42,
  "imageCategories": [
    "All",
    "Interior",
    "Food & drink"
  ],
  "scrapedAt": "2026-06-15T18:25:34.710Z",
  "reserveTableUrl": null,
  "googleFoodUrl": null,
  "hotelStars": null,
  "hotelDescription": null,
  "checkInDate": null,
  "checkOutDate": null,
  "similarHotelsNearby": [],
  "hotelReviewSummary": null,
  "hotelAds": [],
  "openingHours": [
    {
      "day": "Monday",
      "hours": "10:30 AM - 12:00 AM"
    },
    {
      "day": "Tuesday",
      "hours": "10:30 AM - 12:00 AM"
    },
    {
      "day": "Wednesday",
      "hours": "10:30 AM - 12:00 AM"
    },
    {
      "day": "Thursday",
      "hours": "10:30 AM - 12:00 AM"
    },
    {
      "day": "Friday",
      "hours": "10:30 AM - 1:00 AM"
    },
    {
      "day": "Saturday",
      "hours": "10:30 AM - 1:00 AM"
    },
    {
      "day": "Sunday",
      "hours": "10:30 AM - 12:00 AM"
    }
  ],
  "additionalOpeningHours": null,
  "openingHoursBusinessConfirmationText": null,
  "popularTimesLiveText": null,
  "popularTimesLivePercent": null,
  "popularTimesHistogram": null,
  "peopleAlsoSearch": [],
  "placesTags": [],
  "reviewsTags": [
    {
      "title": "classic hand tossed pizza",
      "count": 2
    },
    {
      "title": "friendly cashier",
      "count": 5
    }
  ],
  "additionalInfo": {
    "Service options": [
      {
        "Curbside pickup": true
      },
      {
        "No-contact delivery": true
      },
      {
        "Takeout": true
      }
    ]
  },
  "gasPrices": [],
  "questionsAndAnswers": [],
  "updatesFromCustomers": [],
  "ownerUpdates": [],
  "url": "https://www.google.com/maps/place/Pizza+Hut/data=!4m7!3m6!1s0x89e3719dab66e391:0xc99ed61460e740c8!8m2!3d42.4144303!4d-71.0467333!16s%2Fg%2F1thx0fxl!19sChIJkeNmq51x44kRyEDnYBTWnsk",
  "imageUrl": "https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no",
  "kgmid": "/g/1thx0fxl",
  "floor": null,
  "isExternalServicePlace": false,
  "externalServiceProvider": null,
  "externalId": null,
  "webResults": [],
  "parentPlaceUrl": null,
  "tableReservationLinks": [],
  "bookingLinks": [],
  "images": [
    {
      "imageUrl": "https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no",
      "authorName": "Pizza Hut",
      "authorUrl": "",
      "uploadedAt": "3 years ago"
    }
  ],
  "imageUrls": [
    "https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no"
  ],
  "reviews": [
    {
      "name": "Jane Doe",
      "text": "Great service and the pizza was hot and fresh!",
      "publishAt": "2 weeks ago",
      "likesCount": 3,
      "reviewId": "ChZDSUhNMG9uQkNNR09Y...",
      "reviewerId": "2394829384",
      "reviewerUrl": "https://www.google.com/maps/contrib/2394829384",
      "reviewerPhotoUrl": "https://lh3.googleusercontent.com/a-/ALV-...",
      "reviewerNumberOfReviews": 15,
      "isLocalGuide": false,
      "reviewOrigin": "Google",
      "stars": 4,
      "responseFromOwnerDate": null,
      "responseFromOwnerText": null
    }
  ],
  "userPlaceNote": null,
  "restaurantData": {},
  "topRelevantReviews": [
    {
      "text": "Great service and the pizza was hot and fresh!",
      "rating": 5
    }
  ],
  "distanceFromSearchCenter": 5.48,
  "distanceUnit": "km"
}
```

# Actor input Schema

## `searchStrings` (type: `array`):

Type what you'd normally search for in the Google Maps search bar, like English breakfast or Pizza Hut, Boston. Aim for unique terms for faster processing. Using similar terms (e.g., bar vs. restaurant vs. cafe) may slightly increase your capture rate but is less efficient.

⚠️ Searching for a specific place? If you're looking for a particular business or location (e.g., M\&M Indian Thai Halal Restaurant), make sure to also specify the city or country to get more accurate and reliable results. Without location context, Google Maps may return results from unexpected areas.

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

Direct Google Maps place URLs or search URLs to scrape. Valid format for URLs contains google.com/maps/. Bypasses the search step.

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

Number of results you expect to get per each Search term or URL. The higher the number, the longer it will take.

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

Results details will show in this language.

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

Set the number of reviews you expect to get per place. Set to 0 to skip review extraction entirely.

## `maxImages` (type: `integer`):

Set the number of images per place you expect to scrape. Set to 0 to skip.

## `maxSearchRadius` (type: `number`):

Maximum distance from the search center coordinates (determined from search page or custom overrides). Places outside this radius are skipped.

## `searchRadiusUnit` (type: `string`):

Unit of measurement for the maximum search radius (kilometers or miles).

## `searchCenterLat` (type: `number`):

Optional latitude override to calculate distances from a specific point instead of the search page center.

## `searchCenterLng` (type: `number`):

Optional longitude override to calculate distances from a specific point instead of the search page center.

## Actor input object example

```json
{
  "searchStrings": [
    "Pizza Hut, Boston"
  ],
  "maxResultsPerSearch": 50,
  "language": "en",
  "maxReviews": 5,
  "maxImages": 5,
  "maxSearchRadius": 10,
  "searchRadiusUnit": "km",
  "searchCenterLat": 42.4144,
  "searchCenterLng": -71.0467
}
```

# Actor output Schema

## `dataset` (type: `string`):

The dataset containing all scraped Google Maps places and their details.

# 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 = {
    "searchStrings": [
        "Pizza Hut, Boston"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pimperp/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 = { "searchStrings": ["Pizza Hut, Boston"] }

# Run the Actor and wait for it to finish
run = client.actor("pimperp/google-maps-scraper").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 '{
  "searchStrings": [
    "Pizza Hut, Boston"
  ]
}' |
apify call pimperp/google-maps-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Scraper",
        "description": "Extract data from thousands of locations: get reviews, pricing, photos, and B2B contact info (names, emails, titles). Automate your workflow by scheduling recurring runs, monitoring performance, and integrating directly via our API.",
        "version": "0.0",
        "x-build-id": "u68bH4XzRxWDVz613"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/pimperp~google-maps-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-pimperp-google-maps-scraper",
                "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/pimperp~google-maps-scraper/runs": {
            "post": {
                "operationId": "runs-sync-pimperp-google-maps-scraper",
                "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/pimperp~google-maps-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-pimperp-google-maps-scraper",
                "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",
                "properties": {
                    "searchStrings": {
                        "title": "🔍 Search term(s)",
                        "type": "array",
                        "description": "Type what you'd normally search for in the Google Maps search bar, like English breakfast or Pizza Hut, Boston. Aim for unique terms for faster processing. Using similar terms (e.g., bar vs. restaurant vs. cafe) may slightly increase your capture rate but is less efficient.\n\n⚠️ Searching for a specific place? If you're looking for a particular business or location (e.g., M&M Indian Thai Halal Restaurant), make sure to also specify the city or country to get more accurate and reliable results. Without location context, Google Maps may return results from unexpected areas.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "🔗 Google Maps URLs",
                        "type": "array",
                        "description": "Direct Google Maps place URLs or search URLs to scrape. Valid format for URLs contains google.com/maps/. Bypasses the search step.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxResultsPerSearch": {
                        "title": "💯 Number of places to extract (per each search term or URL)",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Number of results you expect to get per each Search term or URL. The higher the number, the longer it will take.",
                        "default": 20
                    },
                    "language": {
                        "title": "🌍 Language",
                        "type": "string",
                        "description": "Results details will show in this language.",
                        "default": "en"
                    },
                    "maxReviews": {
                        "title": "💬 Number of reviews to extract",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Set the number of reviews you expect to get per place. Set to 0 to skip review extraction entirely.",
                        "default": 0
                    },
                    "maxImages": {
                        "title": "🖼 Number of additional images to extract",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Set the number of images per place you expect to scrape. Set to 0 to skip.",
                        "default": 0
                    },
                    "maxSearchRadius": {
                        "title": "📏 Maximum Search Radius",
                        "minimum": 0,
                        "type": "number",
                        "description": "Maximum distance from the search center coordinates (determined from search page or custom overrides). Places outside this radius are skipped."
                    },
                    "searchRadiusUnit": {
                        "title": "⚙️ Search Radius Unit",
                        "enum": [
                            "km",
                            "mi"
                        ],
                        "type": "string",
                        "description": "Unit of measurement for the maximum search radius (kilometers or miles).",
                        "default": "km"
                    },
                    "searchCenterLat": {
                        "title": "↕ Search Center Latitude Override",
                        "type": "number",
                        "description": "Optional latitude override to calculate distances from a specific point instead of the search page center."
                    },
                    "searchCenterLng": {
                        "title": "↔ Search Center Longitude Override",
                        "type": "number",
                        "description": "Optional longitude override to calculate distances from a specific point instead of the search page center."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
