# Google Maps Business Search & Reviews MCP Server (`vexaloom-labs/google-maps-business-search-and-reviews-mcp-server`) Actor

Search Google Maps businesses or pull reviews for a specific place through one actor, usable as a normal run or as an MCP tool for AI agents. Returns ratings, contact info, hours and flattened reviews.

- **URL**: https://apify.com/vexaloom-labs/google-maps-business-search-and-reviews-mcp-server.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (community)
- **Categories:** AI, Lead generation, MCP servers
- **Features:** Limited permissions, Single-tenant, Server interface
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Business Search & Reviews MCP Server

A single Google Maps actor that works two ways: as a normal Apify batch run, and as a native MCP (Model Context Protocol) server for AI agents. It reads Google Maps' public pages directly — no login, cookie, or API key.

- **Search mode** — find businesses by keyword and location with ratings, reviews, contact details, hours and coordinates. Sponsored placements are excluded.
- **Details mode** — pull the full record for one place by Google Maps URL or canonical Place ID.
- **Reviews mode** — flatten a place's reviews to one row per review, with place metadata repeated on every row.
- **MCP server** — the same three capabilities are exposed as typed tools in Apify Standby mode at `/mcp`.
- **Empty fields are omitted** — nothing is fabricated to fill a gap.

### MCP server (Standby mode)

When the actor runs in Standby, it serves Streamable HTTP MCP at:

```
https://<actor-standby-url>/mcp
```

| Tool | What it returns |
|---|---|
| `search_businesses` | Businesses for a keyword + location: name, category, rating, review count, address, phone, website, hours, coordinates and Google Maps URL. |
| `get_business_details` | The full detail record for one place, addressed by `place_url` or `place_id` (ChIJ...). |
| `get_place_reviews` | One flattened review per item plus the place summary; accepts `place_url` or `place_id`. |

Every tool accepts a `language` code (`en`, `es`, `fr`, `de`, `it`, `pt`, `ja`, `ko`, `zh`, `ar`, `ru`). Tool results are plain JSON objects with `count`, `items`/`reviews` and the resolved `place`/`placeId` where relevant. Errors return an `error` message instead of failing the session. Per-call tool caps are 100 businesses and 1,000 reviews; the batch modes keep the wider caps listed below.

### Batch modes

| Mode | Reads | Emits |
|---|---|---|
| `search` | Keyword + location result feed, then each place page | One `recordType: "business"` row per business |
| `details` | One place page addressed by `placeUrl` or `placeId` | One `recordType: "business"` row |
| `reviews` | A place's public reviews panel | One `recordType: "review"` row per review |

`reviews` mode needs either `placeUrl` or `placeId`; `details` accepts the same two alternatives. `search` needs `searchQuery`, with `location` strongly recommended.

### Output per business

```json
{
  "recordType": "business",
  "index": 0,
  "name": "Joe's Pizza",
  "categoryName": "Pizza restaurant",
  "categories": ["Pizza restaurant"],
  "totalScore": 4.5,
  "reviewsCount": 1234,
  "ratingHistogram": {"5_star": 900, "4_star": 200, "3_star": 80, "2_star": 30, "1_star": 24},
  "address": "7 Carmine St, New York, NY 10014",
  "plusCode": "Q256+VX New York, USA",
  "phone": "+1 212-366-1182",
  "phoneUnformatted": "+12123661182",
  "website": "https://www.joespizzanyc.com",
  "priceLevel": "$$",
  "hours": [{"day": "Monday", "hours": "11 AM–10 PM"}],
  "additionalInfo": {"Service options": [{"Dine-in": true}]},
  "photosSample": ["https://lh3.googleusercontent.com/..."],
  "menuUrl": "https://www.joespizzanyc.com/menu",
  "permanentlyClosed": false,
  "temporarilyClosed": false,
  "placeId": "ChIJ...",
  "featureId": "0x...:0x...",
  "location": {"lat": 40.7308314, "lng": -73.9973325},
  "googleMapsUrl": "https://www.google.com/maps/place/...",
  "sourceUrl": "https://www.google.com/maps/place/...",
  "scrapedAt": "2026-11-07T12:00:00+00:00"
}
```

Other fields appear when Google publishes them: `description`, `menuUrl`, `reserveTableUrl`, `reservationsUrl`, `orderOnlineUrl`. Action links are emitted only when they resolve to a real destination — not a Google ad redirect or another Maps page.

### Output per review

```json
{
  "recordType": "review",
  "order": 1,
  "placeId": "ChIJ...",
  "featureId": "0x...:0x...",
  "businessName": "Joe's Pizza",
  "businessRating": 4.5,
  "businessReviewCount": 1234,
  "businessCategory": "Pizza restaurant",
  "businessAddress": "7 Carmine St, New York, NY 10014",
  "placeMetadata": {
    "placeUrl": "https://www.google.com/maps/place/...",
    "placeId": "ChIJ...",
    "businessName": "Joe's Pizza",
    "businessRating": 4.5,
    "businessReviewCount": 1234
  },
  "reviewId": "ChZDSUhNMG9nS0VJQ0FnSUQ...",
  "reviewerName": "John Smith",
  "reviewerAvatarUrl": "https://lh3.googleusercontent.com/...",
  "reviewerProfileUrl": "https://www.google.com/maps/contrib/...",
  "reviewerTotalReviews": 87,
  "isLocalGuide": true,
  "rating": 5.0,
  "reviewText": "Best pizza in NYC...",
  "reviewDateOriginal": "2 months ago",
  "likesCount": 12,
  "reviewLanguage": "en",
  "photosInReview": ["https://lh3.googleusercontent.com/..."],
  "ownerResponseText": "Thank you!",
  "ownerResponseDate": "1 month ago",
  "placeUrl": "https://www.google.com/maps/place/...",
  "sourceUrl": "https://www.google.com/maps/place/...",
  "scrapedAt": "2026-11-07T12:00:00+00:00"
}
```

`order` is the 1-based position in this run's output. `reviewDateOriginal` preserves Google's own date text, which is often relative. Fields Google does not publish for a review are omitted.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search`, `details` or `reviews`. |
| `searchQuery` | string | – | What to search for, e.g. `coffee shop` (mode=search). |
| `location` | string | – | City, region or address scope, e.g. `New York, NY` (mode=search). |
| `maxResults` | integer | `20` | Maximum businesses, 1–500 (mode=search). Prefill uses 3. |
| `language` | string | `en` | Google Maps interface language (11 supported codes). |
| `placeUrl` | string | – | Google Maps place URL (mode=details or reviews). |
| `placeId` | string | – | Canonical Place ID beginning with `ChIJ` (mode=details or reviews). |
| `maxReviews` | integer | `50` | Maximum reviews, 1–200000 (mode=reviews). |
| `proxyConfiguration` | object | – | Optional proxy. Runs start direct and use the automatic Apify proxy pool only after a real block. |

`details` and `reviews` accept either `placeUrl` or `placeId`, never both.

#### Examples

Search:

```json
{
  "mode": "search",
  "searchQuery": "pizza restaurant",
  "location": "New York, NY",
  "maxResults": 20
}
```

Details:

```json
{
  "mode": "details",
  "placeId": "ChIJabtoT7hlwokRLECK0SW3_8I"
}
```

Reviews:

```json
{
  "mode": "reviews",
  "placeUrl": "https://www.google.com/maps/place/Joe's+Pizza/@40.7308314,-73.9973325,17z",
  "maxReviews": 100
}
```

Search in another language:

```json
{
  "mode": "search",
  "searchQuery": "寿司",
  "location": "東京 日本",
  "maxResults": 20,
  "language": "ja"
}
```

### Use cases

- Market research: compare competitor ratings, pricing tier and location in one dataset.
- Site selection: scan an area's existing businesses before choosing a location.
- Review analysis: pull a place's reviews for sentiment or recurring complaint analysis.
- AI agent tooling: call search, details and reviews from an MCP-compatible agent.
- RAG pipelines: feed structured business and review records into a downstream model.

### FAQ

**Does this need Google login, cookies or an API key?** No. All modes read public Google Maps pages.

**Can it run as an MCP server?** Yes. In Standby mode the actor serves `/mcp` with the three tools listed above, alongside normal batch runs.

**Which mode should I use for one specific place?** Use `details` for one full business row, or `reviews` when you need the review rows. Both accept a Maps URL or a `ChIJ` Place ID.

**Why might a run return fewer records than requested?** Google's own public result set and review surface set the ceiling. The actor returns everything it can observe and never pads the count.

**Is a proxy required?** No. Batch runs go direct first; if Google serves a challenge, the actor retries through the automatic Apify proxy pool. MCP tool calls are direct-only and return a retryable `error` object if Google serves a challenge. You can leave `proxyConfiguration` empty.

**Why is a field missing from one record?** Only fields Google publishes for that record are included. Empty values are removed rather than emitted as `null`.

**Is this affiliated with Google?** No. This is an independent actor reading public Google Maps pages.

### Limits

- Google caps the public review panel's first window. The actor retries a bounded number of fresh renders and returns only reviews it actually observed; a very large `maxReviews` can therefore return fewer rows than requested.
- Search results are the organic ranked window Google serves for the query, not an exhaustive crawl of every matching business. Sponsored placements are excluded.
- Google may occasionally serve a limited or challenge page. The actor reports that state instead of fabricating rows.
- Each run needs at least the default 2 GB of memory; smaller allocations can crash Chromium during multi-place searches.

# Actor input Schema

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

Choose the scraping mode: search for businesses, get full details for one place, or scrape reviews from a specific place.

## `searchQuery` (type: `string`):

What to search for (e.g., 'restaurant', 'hotel', 'coffee shop'). Required for 'search' mode.

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

Location to search in (e.g., 'New York, NY', 'London, UK'). Required for 'search' mode.

## `maxResults` (type: `integer`):

Maximum number of business results to scrape. Only used in 'search' mode.

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

Language code for results (e.g., 'en', 'de', 'fr').

## `placeUrl` (type: `string`):

Google Maps place URL. Required for 'details' and 'reviews' modes unless placeId is provided.

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

Canonical Google Place ID beginning with ChIJ. Use instead of placeUrl in 'details' and 'reviews' modes.

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

Maximum number of reviews to scrape. Only used in 'reviews' mode.

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

Optional Apify proxy. Runs start direct and fall back to the automatic Apify proxy pool only after a real block.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "pizza restaurant",
  "location": "New York, NY",
  "maxResults": 3,
  "language": "en",
  "placeUrl": "https://www.google.com/maps/place/Joe's+Pizza/@40.7308314,-73.9973325,17z",
  "placeId": "ChIJabtoT7hlwokRLECK0SW3_8I",
  "maxReviews": 50
}
```

# Actor output Schema

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

Search and details records use the suite's canonical camelCase business fields; review mode emits one flattened canonical review per item.

# 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 = {
    "mode": "search",
    "searchQuery": "coffee shop in New York",
    "maxResults": 3,
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/google-maps-business-search-and-reviews-mcp-server").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 = {
    "mode": "search",
    "searchQuery": "coffee shop in New York",
    "maxResults": 3,
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/google-maps-business-search-and-reviews-mcp-server").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 '{
  "mode": "search",
  "searchQuery": "coffee shop in New York",
  "maxResults": 3,
  "language": "en"
}' |
apify call vexaloom-labs/google-maps-business-search-and-reviews-mcp-server --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/google-maps-business-search-and-reviews-mcp-server"
        }
    }
}
```

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/sC80YE19nutFBUPx8/builds/Czdvhnc5ASnO9t9rN/openapi.json
