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

Extract business data from Google Maps at scale. Get names, addresses, phone numbers, websites, ratings, reviews, opening hours, popular times, photos, and 40+ data points per listing.

- **URL**: https://apify.com/abotapi/google-maps-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Lead generation, Social media, Real estate
- **Features:** Limited permissions
- **Stats:** 95 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.70 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Google Maps Scraper: Business Listings, Reviews & Location Data

Google Maps Scraper turns Google Maps into structured business data. Search by keyword, paste Google Maps links, or draw a custom area, then pull names, addresses, phone numbers, websites, ratings, opening hours, popular times and reviews for every matching place. Export to JSON, CSV or Excel, or read the results straight through the API.

### Why This Scraper?

- **Two ways to find places.** Free text search terms, or direct Google Maps place-page and search-result links, no manual URL building.
- **Full business profiles.** Contact details, location, category, price level, opening hours, popular times, photos and "people also search for" in one record.
- **Reviews on demand.** Turn on review extraction per run, with sort order, or skip it entirely for faster runs.
- **Area coverage.** Draw a custom polygon and the actor builds a grid of searches across it, so you are not limited to Google's per-search result cap.
- **Built for schedules.** Incremental mode returns only new and changed businesses on recurring runs, and a resumed run never re-scrapes a place it already collected.

### Use Cases

- **Lead generation:** build prospect lists with names, phone numbers, websites and categories for a market or neighborhood.
- **Local SEO and reputation tracking:** monitor ratings, review counts and review text for your business and competitors over time.
- **Market and site research:** map competitor density, categories, price levels and ratings for real estate, retail or franchise planning.
- **Data enrichment:** attach verified addresses, coordinates and opening hours to an existing list of businesses.
- **Delivery and menu research:** collect menu links and order/delivery platform links for restaurants in an area.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `placeId` | `"ChIJN1t_tDeuEmsRUsoyG83frY4"` |
| `title` | `"Example Coffee Roasters"` |
| `categoryName` | `"Coffee shop"` |
| `address` | `"100 Example St, San Francisco, CA 94102, USA"` |
| `street` / `city` / `state` / `postalCode` / `countryCode` | Address components parsed from `address`, when Google's format allows it |
| `location` | `{ "lat": 37.7763, "lng": -122.4158 }` |
| `plusCode` | `"QHFJ+8R Hayes Valley, San Francisco, CA"` |
| `phone` | `"+1 555 010 0100"` |
| `website` | `"https://www.example.com"` |
| `totalScore` | `4.5` |
| `reviewsCount` | `1842` |
| `priceLevel` | `"$$"` |
| `openingHours` | `[{ "day": "Monday", "hours": "7 am to 6 pm" }, ...]` |
| `popularTimes` | Hourly occupancy percent per day, when Google shows it for that place |
| `imageUrls` | Photo URLs, up to the configured limit |
| `peopleAlsoSearch` | Related places Google shows on the same listing |
| `menuUrl` / `orderLinks` | Menu link, and delivery platform links (Uber Eats, DoorDash, ...) when present |
| `locatedIn` | Parent place, for a business inside a mall or airport |
| `temporarilyClosed` / `permanentlyClosed` | Closure status flags |
| `searchString` / `rank` / `isAdvertisement` | Which search found this place, its position, and whether it was a sponsored slot |
| `scrapedAt` | `"2025-12-06T10:30:00.000Z"` |
| `reviews` | Reviewer name, rating, text, date and owner response, when Max Reviews Per Business is above 0 |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | Present only when Incremental mode is on: how this business changed since the last tracked run |

### How to Use

1. Pick how to find places: free text search terms, or direct Google Maps links.
2. Optionally narrow the area with a location string, coordinates, country/state/city/postal code, or a custom polygon, and set the map zoom.
3. Set how many results, reviews and photos to collect per search, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Basic keyword search:**

```json
{
  "searchStringsArray": ["coffee shops"],
  "location": "Seattle, WA",
  "maxResultsPerSearch": 50
}
```

**Coordinate search with reviews:**

```json
{
  "searchStringsArray": ["dentists"],
  "lat": 41.8781,
  "lng": -87.6298,
  "zoom": 15,
  "maxReviews": 20,
  "reviewsSort": "newest"
}
```

**Custom area grid search:**

```json
{
  "searchStringsArray": ["hotels"],
  "customGeolocation": {
    "type": "Polygon",
    "coordinates": [[[-122.5, 37.7], [-122.3, 37.7], [-122.3, 37.85], [-122.5, 37.85], [-122.5, 37.7]]]
  },
  "zoom": 16,
  "maxResultsPerSearch": 200
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/google-maps-scraper").call(run_input={"searchStringsArray": ["coffee shops"], "location": "Seattle, WA"})
for business in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(business["title"], business.get("totalScore"))
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/google-maps-scraper').call({ searchStringsArray: ['coffee shops'], location: 'Seattle, WA' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Grid search for large areas

Google Maps caps how many results a single search returns. Set `customGeolocation` to a GeoJSON Polygon or MultiPolygon and the actor generates a grid of search points across it based on `zoom`, so a large area is covered as many smaller searches instead of one capped one. A `Point` geometry is also accepted, but is treated as a single search location.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run ID and the actor skips every Place ID it already collected there, so you don't pay twice. The deprecated `resumeRunId` field still works the same way; if both are set, `resumeFromRunId` wins.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same search. Each business is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED` (only after a run that fully re-walked the search, and only with `emitExpired`). `stateKey` names or shares the tracked baseline; leave it empty and the actor derives one from your search settings. With Incremental mode off, output is exactly as before.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape, the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each business, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `searchStringsArray` | array | `["restaurants"]` | Free text search terms. |
| `startUrls` | array | (none) | Direct Google Maps place-page or search-result links to scrape. |
| `location` | string | `"New York, NY"` | Location text appended to each search term. |
| `lat` | number | (none) | Latitude for a coordinate-based search (-90 to 90). Must be set together with `lng`. |
| `lng` | number | (none) | Longitude for a coordinate-based search (-180 to 180). Must be set together with `lat`. |
| `country` | string | (none) | Country used to build the search query when `location` is not set. |
| `state` | string | (none) | State or region used to build the search query when `location` is not set. |
| `city` | string | (none) | City used to build the search query when `location` is not set. |
| `postalCode` | string | (none) | Postal or ZIP code filter. |
| `customGeolocation` | object | (none) | GeoJSON Polygon or MultiPolygon boundary; the actor builds a grid of searches across it. A Point is accepted as a single search location. |
| `zoom` | integer | `14` | Map zoom level (1 to 21). Higher values mean a smaller area per grid cell and more precise results. |
| `maxResultsPerSearch` | integer | `2` | Maximum results to extract per search term or grid point (up to 10,000). |
| `maxReviews` | integer | `0` | Maximum reviews to extract per business. `0` skips review extraction. |
| `maxImages` | integer | `10` | Maximum photo URLs to extract per business. |
| `reviewsSort` | string | `relevant` | Review sort order: `relevant`, `newest`, `highest`, or `lowest`. |
| `oneReviewPerRow` | boolean | `false` | Output one dataset row per review instead of one row per business, useful for CSV export. |
| `skipClosedPlaces` | boolean | `false` | Skip temporarily or permanently closed businesses. |
| `language` | string | `en` | Language code for search results and extracted text. |
| `maxConcurrency` | integer | `5` | Maximum number of pages processed in parallel (1 to 20). |
| `proxyConfiguration` | object | Apify Proxy off | Connection settings for all requests. |
| `resumeFromRunId` | string | (none) | Run ID of a previous run to continue; already-scraped Place IDs are skipped. |
| `resumeRunId` | string | (none) | Deprecated, use `resumeFromRunId` instead. Still honored for existing saved tasks; `resumeFromRunId` wins if both are set. |
| `incrementalMode` | boolean | `false` | Turn on recurring monitoring of the same search, classifying each business as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED across scheduled runs. |
| `stateKey` | string | (none) | Manually name the Incremental mode baseline. Leave empty to derive it automatically from your search settings. |
| `emitUnchanged` | boolean | `false` | Also output businesses with no changes since the last run (bills and returns an extra row for each). |
| `emitExpired` | boolean | `false` | Also output a synthetic row for a previously tracked business no longer found, only after a run proves it fully re-scanned the search. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each business to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "placeId": "ChIJ49sQuK-AhYARM6U646SA12Y",
  "title": "Example Coffee Roasters",
  "url": "https://www.google.com/maps/place/Example-Coffee-Roasters/ChIJ49sQuK-AhYARM6U646SA12Y",
  "categoryName": "Coffee shop",
  "address": "100 Example St, San Francisco, CA 94102, USA",
  "street": "100 Example St",
  "city": "San Francisco",
  "state": "CA",
  "postalCode": "94102",
  "countryCode": "US",
  "location": { "lat": 37.7763, "lng": -122.4158 },
  "plusCode": "QHFJ+8R Hayes Valley, San Francisco, CA",
  "phone": "+1 555 010 0100",
  "website": "https://www.example.com",
  "totalScore": 4.5,
  "reviewsCount": 1842,
  "priceLevel": "$$",
  "openingHours": [
    { "day": "Monday", "hours": "7 am to 6 pm" },
    { "day": "Tuesday", "hours": "7 am to 6 pm" }
  ],
  "imageUrls": ["https://lh3.googleusercontent.com/example=w800-h600"],
  "menuUrl": "https://www.example.com/menu",
  "temporarilyClosed": false,
  "permanentlyClosed": false,
  "searchString": "coffee shops",
  "rank": 3,
  "isAdvertisement": false,
  "scrapedAt": "2025-12-06T10:30:00.000Z",
  "reviews": [
    {
      "reviewId": "review_0123456789abcdef",
      "reviewerName": "Sample Reviewer",
      "rating": 5,
      "text": "Great coffee and atmosphere.",
      "publishedAtDate": "2025-11-22T09:00:00.000Z"
    }
  ]
}
```

### Plan Requirement

The default connection works for most searches out of the box. For large grid searches across many polygon cells, or for high volumes of detail pages, switch **Proxy Configuration** to a residential group under Connection for steadier throughput. The **Pricing** tab shows the current rates.

### FAQ

#### How much does it cost?

You pay per dataset row returned. Reviews are included inside each business row; if you turn on **One Review Per Row**, every review becomes its own row. The **Pricing** tab shows the current rates. Use **Max Results Per Search** to cap the cost of any run.

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

This actor collects only publicly available business listing data. You are responsible for how you use it: follow Google's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Reviews and photos may carry their authors' own rights.

#### Can I get only new or changed businesses on a schedule?

Yes. Schedule the actor from the **Schedules** tab against the same search and turn on **Incremental mode**. Each run then returns only new, updated, reappeared and expired businesses, and unchanged ones are not billed unless you turn on **Emit unchanged businesses**.

#### Why do I only get 2 results for a search term?

`maxResultsPerSearch` defaults to `2`. Raise it, up to `10,000`, to collect more results per search term or grid point. For very large areas, a `customGeolocation` grid search covers more ground than a single search term ever can.

#### Why did my run finish with an empty or partial dataset instead of failing?

The actor only stops the whole run for a configuration problem: no `searchStringsArray` or `startUrls` provided, `lat` set without `lng` (or the reverse), coordinates out of range, or turning on Incremental mode with `resumeFromRunId` against a search that already has tracked state. If Google Maps blocks or fails to load an individual search or business page, that one page is skipped and logged, and the run still finishes and returns whatever it did collect, which can be an empty dataset if every page was blocked. Run it again, or lower `maxConcurrency`, if you see this often.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more leads data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>📇 <a href="https://apify.com/abotapi/2gis-places-scraper"><b>2GIS</b></a><br>From $1/1K. Extract business and place data from 2GIS.com at scale. Get names, addresses...</td><td>🧩 <a href="https://apify.com/abotapi/yandex-maps-scraper"><b>Yandex Maps Scraper</b></a><br>Scrape businesses and places from Yandex Maps by search term or URL for research, leads...</td></tr>
<tr><td>✈️ <a href="https://apify.com/abotapi/naver-map-scraper"><b>Naver Map Scraper</b></a><br>From $1/1K. Scrape Naver Map places by keyword or URL: names, categories, ratings...</td><td>📇 <a href="https://apify.com/abotapi/herold-at-scraper"><b>Herold.at Scraper</b></a><br>From $0.80/1K. Scrape Herold.at business listings across Austria into clean JSON. Extract...</td></tr>
<tr><td>📇 <a href="https://apify.com/abotapi/pagesjaunes-fr-scraper"><b>PagesJaunes FR</b></a><br>From $0.8/1K. Scrapes business listings from PagesJaunes.fr (French Yellow Pages)...</td><td>📇 <a href="https://apify.com/abotapi/bizbuysell-scraper"><b>BizBuySell Scraper</b></a><br>From $1.5/1K. Extract business-for-sale and franchise listings from bizbuysell.com with...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/google-maps-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

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

List of search queries (e.g., 'restaurants', 'coffee shops')

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

Direct Google Maps URLs to scrape

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

Location text (e.g., 'New York, NY', 'Tokyo, Japan')

## `lat` (type: `number`):

Latitude for coordinate-based search

## `lng` (type: `number`):

Longitude for coordinate-based search

## `country` (type: `string`):

Country for geolocation filtering

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

State or region for geolocation filtering

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

City for geolocation filtering

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

Postal/ZIP code for geolocation filtering

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

GeoJSON geometry (Polygon, MultiPolygon, or Point with radius)

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

Map zoom level (1=world, 21=building). Higher = more precise, fewer results

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

Maximum number of results to extract per search query

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

Maximum reviews to extract per business. Set to 0 to disable review extraction (faster)

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

Maximum number of image URLs to extract per business

## `reviewsSort` (type: `string`):

How to sort reviews when extracting

## `oneReviewPerRow` (type: `boolean`):

Output each review as a separate Dataset row (useful for CSV export)

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

Skip temporarily or permanently closed businesses

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

Language code for search results (e.g., 'en', 'es', 'ja')

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

Number of parallel browser contexts (higher = faster but more memory)

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

Apify Proxy settings. Residential proxies recommended for high volume

## `resumeFromRunId` (type: `string`):

Run ID of a previous run to continue. Loads its already-scraped Place IDs and skips them, so this run only appends new businesses. See also Incremental mode below for recurring monitoring instead of a one-off resume.

## `resumeRunId` (type: `string`):

Deprecated — use "Resume From Run ID" above instead. Kept working so existing saved tasks that pass this field name are unaffected. If both are set, "Resume From Run ID" wins.

## `incrementalMode` (type: `boolean`):

Remember this search's results across scheduled runs and classify every business as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED, instead of re-scraping from scratch. State is kept by the Actor itself, keyed on "State key" below (or a hash of your search settings). Default off — no existing user is affected until they opt in.

## `stateKey` (type: `string`):

Optional. Manually name the Incremental-mode baseline so you can control exactly which runs share state (e.g. two different scheduled tasks on the same search). Leave empty to derive it automatically from your search settings — two differently-configured searches then never share a baseline.

## `emitUnchanged` (type: `boolean`):

When Incremental mode is on, also output businesses whose data has not changed since the last run (changeType="UNCHANGED"). Off by default so a recurring run only bills and returns what's new. Turning this on bills and returns an extra row for every unchanged business, every run.

## `emitExpired` (type: `boolean`):

When Incremental mode is on, also output a synthetic row (changeType="EXPIRED") for a previously-tracked business that no longer appears in the search. Only fires after a run proves it fully re-scanned the search (no result cap hit, no CAPTCHA/block, not a resume) — a partial run never marks anything expired. Off by default. Turning this on bills and returns an extra row for every business that disappears.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "searchStringsArray": [
    "restaurants"
  ],
  "location": "New York, NY",
  "zoom": 14,
  "maxResultsPerSearch": 2,
  "maxReviews": 0,
  "maxImages": 10,
  "reviewsSort": "relevant",
  "oneReviewPerRow": false,
  "skipClosedPlaces": false,
  "language": "en",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `businesses` (type: `string`):

Dataset containing all scraped business listings with full 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 = {
    "searchStringsArray": [
        "restaurants"
    ],
    "location": "New York, NY",
    "maxResultsPerSearch": 2,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

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

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "searchStringsArray": ["restaurants"],
    "location": "New York, NY",
    "maxResultsPerSearch": 2,
    "proxyConfiguration": { "useApifyProxy": False },
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchStringsArray": [
    "restaurants"
  ],
  "location": "New York, NY",
  "maxResultsPerSearch": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call abotapi/google-maps-scraper --silent --output-dataset

```

## MCP server setup

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

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

## OpenAPI specification

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