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

Collect public Google Maps place reviews, ratings, reviewer details, and place metadata from place URLs or place IDs.

- **URL**: https://apify.com/mlg14/google-maps-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Travel, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.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/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

Scrape public Google Maps place reviews, ratings, reviewer profile details, and place information from place URLs or place IDs. Export Google Maps review data to JSON, CSV, or Excel from the run dataset, or use the actor as a structured Google Maps API alternative for small review snapshots.

Each input place is resolved to its public place record, and each available preview review becomes one dataset row. A row includes the review and its place context so results from several locations can be combined without a separate join. The current public place response supplies up to five preview reviews per place; see Limits before planning a larger collection.

### What data can you extract from Google Maps?

The dataset has one row per review. Fields stay present even when the public response does not provide a value. Empty arrays indicate no exposed entries; null indicates a value was not supplied. The table describes every output field.

| Field | Description | Example |
|---|---|---|
| searchString | Input place URL or URL constructed from the input place ID. | varies |
| reviewId | Identifier of the public review. | Ci9DQU... |
| reviewUrl | Direct public review URL when present. | null |
| reviewOrigin | Origin shown for the review, such as Google or a hotel partner. | Google |
| stars | Review rating from 1 to 5 stars. | 4 |
| text | Displayed review text. | Early morning, nice to have a trail walk |
| textTranslated | Translated review text when included in the preview. | null |
| publishAt | Relative publication time shown by Maps. | null |
| publishedAtDate | Publication time in UTC when supplied. | 2026-06-29T01:44:48.216Z |
| likesCount | Like count when supplied; unavailable in the current preview. | null |
| reviewerId | Public reviewer profile ID when supplied. | null |
| reviewerUrl | Public reviewer profile URL. | null |
| name | Displayed reviewer name. | null |
| reviewerNumberOfReviews | Number of reviews shown on the reviewer profile. | null |
| isLocalGuide | Whether the reviewer is labeled a Local Guide. | varies |
| reviewerPhotoUrl | Public reviewer avatar URL. | null |
| responseFromOwnerDate | Owner response date when exposed; unavailable in the current preview. | null |
| responseFromOwnerText | Owner response text when exposed; unavailable in the current preview. | null |
| reviewImageUrls | Image URLs attached to the review. | \[] |
| reviewContext | Structured visit context when exposed; empty in the current preview. | {} |
| reviewDetailedRating | Structured aspect ratings when exposed; empty in the current preview. | {} |
| visitedIn | Visit period when exposed; unavailable in the current preview. | null |
| originalLanguage | Language code shown for the original text. | null |
| translatedLanguage | Translated language code when present. | null |
| placeId | Google Maps place ID. | ChIJbzg82hLUT1MRxpsdaatcUu8 |
| location | Place latitude and longitude. | {"lat": 44.97, "lng": -110.7} |
| address | Displayed place address when provided. | null |
| countryCode | Two-letter country code. | US |
| categoryName | Primary place category. | Tourist attraction |
| categories | All place categories in the preview. | \["Tourist attraction"] |
| title | Place name. | Liberty Cap |
| totalScore | Average place rating. | 4.7 |
| reviewsCount | Total review count displayed for the place. | 834 |
| url | Public Maps place URL. | null |
| cid | Decimal place CID. | null |
| fid | Maps feature identifier. | null |
| imageUrl | Place image URL when supplied. | null |
| scrapedAt | UTC extraction timestamp. | 2026-09-26T18:04:26.000Z |
| language | Requested language code. | en |

The place identifier and review identifier can be used to remove duplicates across repeated runs. The decimal CID and feature identifier are included because links sometimes use those identifiers instead of the place ID. The place score and review count describe the place as a whole at collection time; the stars value belongs to the individual review. The dataset does not infer a missing owner reply or like count from nearby interface elements.

The current place response can mix reviews from the map's own review system with reviews attributed to another public origin, especially for lodging. Use the reviewOrigin field or the Google-only input option when that distinction matters. A missing reviewer profile on an attributed review is normal.

### How to scrape Google Maps reviews

1. Open the actor and add one or more public Maps place URLs in startUrls, or enter place IDs in placeIds.
2. Set the total review cap and optional filters for origin, stars, and a keyword. The preview limit is five per place.
3. Start the run. The actor resolves each place and writes available reviews to the default dataset.
4. Open the dataset to inspect the table or download JSON, CSV, or Excel.

A full place URL is more reliable than a name-only search URL. Name-only searches may resolve to a different location or to no single place at all. When collecting a group of locations, provide one explicit place URL or place ID for each location. This also makes subsequent runs easier to compare.

### Input

| Parameter | Type | Default | Description |
|---|---|---:|---|
| startUrls | URL list | Empty | Public Maps place URLs. Supply a distinct URL for each location. |
| placeIds | String list | Empty | Optional place IDs for locations without a saved URL. |
| maxReviews | Integer | 5 | Maximum reviews emitted per place, from 1 to 5. |
| maxItems | Integer | 0 | Maximum reviews across the entire run; zero leaves this total uncapped. |
| language | String | en | Language code used for place pages and displayed review text. |
| reviewsOrigin | Selection | all | Keep all origins or only reviews labeled Google. |
| reviewsFilterString | String | Empty | Keep preview reviews containing the keyword, ignoring case. |
| stars | Integer list | Empty | Keep only the selected star ratings from 1 through 5. |
| proxyConfiguration | Object | Enabled | Network configuration for the place requests. |

Example input for two related places:

```json
{
  "startUrls": [
    {"url": "https://www.google.com/maps/place/Yellowstone+National+Park/@44.5857951,-110.5140571,9z/data=!3m1!4b1!4m5!3m4!1s0x5351e55555555555:0xaca8f930348fe1bb!8m2!3d44.427963!4d-110.588455"},
    {"url": "https://www.google.com/maps/place/Old+Faithful/data=!4m2!3m1!1s0x5351ed1b81592e5f:0x83b7c275a6822a1"}
  ],
  "maxReviews": 5,
  "maxItems": 10,
  "language": "en",
  "reviewsOrigin": "all",
  "stars": []
}
```

You may combine startUrls and placeIds. Duplicate review IDs are emitted once within a run. The total cap is checked while reviews are written, so a run can stop before it reaches the end of the input list. Filters operate on the five reviews available in each public preview; a filter can reduce the output to zero even when the place has many reviews in total.

### Output example

This shortened item comes from a live run. Long media URLs and optional null fields are omitted here; the dataset retains the full output shape.

```json
{
  "reviewId": "Ci9DQUlRQUNvZENodHljRjlvT2taamFraGFhM0ZIYjFOU2FrMWtZamcwUkdWbVVrRRAB",
  "stars": 4,
  "text": "Early morning, nice to have a trail walk🚶",
  "publishedAtDate": "2026-06-29T01:44:48.216Z",
  "reviewOrigin": "Google",
  "placeId": "ChIJbzg82hLUT1MRxpsdaatcUu8",
  "title": "Liberty Cap",
  "totalScore": 4.7,
  "reviewsCount": 834,
  "categoryName": "Tourist attraction",
  "countryCode": "US",
  "fid": "0x534fd412da3c386f:0xef525cab691d9bc6",
  "cid": "17244947814427761606"
}
```

The timestamp is derived from the publication time in the public response. The relative publishAt value can change between runs while publishedAtDate stays suitable for sorting. The scrapedAt timestamp marks when this actor collected the row, not when the reviewer wrote it. Some reviews include many images, so the reviewImageUrls array can be substantially longer than the compact example.

### Use cases

- A local business team can inspect a small current sample of public comments and ratings across several branches. Keeping placeId on each row makes branch-level grouping straightforward.
- A travel researcher can compare recent public experiences at nearby attractions and identify recurring visitor themes before a trip.
- A destination operator can monitor whether a public place score or review count changes between scheduled snapshots.
- A retail team can collect public feedback about opening hours, stock, accessibility, or service at a handful of locations, then follow up in the original review.
- A data analyst can test a review processing workflow with stable review and place IDs before obtaining a larger licensed source.
- A quality team can check whether photo-bearing reviews, reviewer counts, and attributed review origins are present for a set of locations.

These uses fit the preview scope. For an exhaustive history of a popular place, this actor's five-review source is insufficient. The displayed place review count is context, not a promise that every counted review was collected.

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

The configured result charge is $1.00 per 1,000 emitted dataset rows, or $0.001 per review. A run with five emitted reviews is $0.005 in result charges. A 30-review run is $0.03. At 1,000 emitted reviews across enough places, result charges are $1.00. Only rows written to the dataset count toward that result charge; a place returning zero preview reviews does not create a result row.

For a worked small batch, six places returning five reviews each produce 30 rows and $0.03 in result charges. For a larger batch, 200 places returning five each produce 1,000 rows and $1.00. If filters remove half of a 200-place batch, 500 emitted rows would be $0.50. Actual row counts depend on what each place response exposes at run time, and the public preview often returns fewer than five. Platform usage and network use are subject to the account's run settings; check the run cost display for the complete bill.

To control spend, set maxItems to the number of rows needed and start with a small place list. A low maxItems value stops writing as soon as the cap is reached. The actor also honors an account event charge limit when the platform reports that the limit has been reached.

### Tips for best results

Use explicit place pages containing a place feature identifier, or use a place ID. A Maps search for a business name does not always identify one place, particularly when several locations have the same name. Verify the title and placeId in the first output before launching a wider batch. If the output title is unexpected, replace the search URL with the correct place page.

Try reviewsOrigin set to google if you want only reviews from the map's own review system. Lodging pages may also show attributed partner reviews, which can have a different profile format and rating representation. The actor maps the available rating to a 1–5 stars field and preserves the origin label. Review image arrays and profile fields may differ by origin.

Leave stars and reviewsFilterString empty when completeness within the small preview matters. These filters act after the public response is received. They cannot ask the site for more matching reviews. A keyword such as "parking" can return nothing even if the full place page contains older parking reviews outside the preview.

Use maxItems for a predictable output ceiling when many places are supplied. Put the most important locations first: once the total cap is reached, later places are not fetched. Repeated input URLs that resolve to the same reviews will not inflate the dataset because review IDs are deduplicated within the run. Keep reviewId and placeId when exporting to spreadsheets so later snapshots can be compared without matching on text.

The language setting affects the public page request and displayed text. A reviewer may have written in another language; originalLanguage and textTranslated are populated only when the response exposes them. Do not assume all text is translated or all dates appear in a particular local time zone. publishedAtDate and scrapedAt use UTC formatting.

### Limits

The currently reachable structured place response supplies up to five preview reviews per place. It may return zero for a place that visibly has many reviews, and the set can change across runs. maxReviews therefore has a maximum of five. The actor does not paginate through all reviews. The displayed reviewsCount can be much larger than the number of dataset rows.

A public review-list route returned no usable response during development, while the alternate public reviews link redirected to a search surface with an access interstitial. The actor relies on the structured place response because it remained reachable without login. Changes to that response can alter fields or reduce availability. A status message in the run log records how many reviews were present for each resolved place.

Owner replies, likes, detailed aspect ratings, visit periods, and translated language codes were not present in the confirmed preview records. Their columns are retained as null or empty values so datasets have a stable shape, but users should not treat them as collected facts. Addresses, images, reviewer profile data, and categories may also be absent for some places or review origins.

The actor does not accept login-gated pages, private reviews, arbitrary domains, or general web search URLs. It only follows public Maps place pages. It does not create reviews, modify a place, or contact reviewers. Regional presentation, locale, and public visibility can affect the output. Review counts and ratings are point-in-time values.

### Automation examples

- "Collect the visible public reviews for these ten place URLs, keep only four- and five-star rows, and return the dataset grouped by place ID."
- "Run this place list each week, compare review IDs and place scores with the previous dataset, and report new public reviews."

For reliable recurring comparisons, retain the prior dataset. Use reviewId to find new or removed preview entries, and use placeId to group locations. A review leaving the five-item preview does not prove that it was deleted; it may simply have moved outside the visible preview.

### FAQ

#### Is it legal to collect these reviews?

The actor reads publicly accessible place and review data. Applicable site terms and privacy rules still matter. Use reviewer identifiers and profile links only for a legitimate purpose, respect applicable data protection requirements, and avoid misuse of personal data. For a regulated use case, get advice specific to your jurisdiction.

#### Do I need to provide a proxy?

The default network configuration handles requests during a normal run. The actor starts with the lower-cost network path and can escalate when access is blocked. You can supply your own configuration in the input when the default does not suit your account.

#### How fast is a run?

Each place normally needs a page request and a structured place request. In the confirmed 30-row run, the actor visited multiple places within a short run, but speed changes with the number of places, network conditions, and blocked or empty responses. Start with a few places to estimate your own batch time.

#### Can I schedule and monitor it?

Yes. Schedule the actor with saved input and review the run log and dataset after each execution. Record the run timestamp and compare placeId plus reviewId against prior datasets. A drop in output should be investigated alongside the per-place log counts.

#### Can I export to a spreadsheet?

Yes. Download the default dataset as CSV or Excel, or use its JSON endpoint in a connected workflow. Keep nested arrays, such as reviewImageUrls and categories, in JSON when you need every element. A CSV export may represent those arrays as serialized values.

#### Why is a field empty?

The public preview does not include every field for every place or review. Owner responses and like counts were absent from the verified source. A reviewer profile can also be unavailable for a review attributed to another public origin. Null means the actor had no confirmed value.

#### Why did I receive fewer than five reviews for a place?

Some place responses contain fewer than five preview records or none at all. Filters can remove rows after collection, and the global maxItems cap can stop before later places are processed. Check the place-specific line in the run log to distinguish source availability from filtering.

### Integrations

Use the default dataset endpoint to feed reports and internal workflows. Scheduled runs, webhooks, and spreadsheet imports can move newly collected rows into another system. Store reviewId, placeId, publishedAtDate, and scrapedAt together so later updates can be compared. A webhook should use the completed run's dataset ID rather than assuming every run has the same number of reviews.

### Support

Open an issue on the Issues tab with a public place URL, expected field, and run ID. We reply within 24 hours and add fields on request when the public response contains them.

# Actor input Schema

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

Public Google Maps place or place-ID URLs. Each place currently yields up to five preview reviews.

## `placeIds` (type: `array`):

Optional Google Maps place IDs.

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

Maximum preview reviews to emit per place. The current public response exposes up to five.

## `maxItems` (type: `integer`):

Maximum reviews across all places. Zero means no total cap.

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

Language code used for the Maps page and returned review display.

## `reviewsOrigin` (type: `string`):

Keep all public reviews or only reviews shown as Google reviews.

## `reviewsFilterString` (type: `string`):

Optional case-insensitive keyword matched against preview review text.

## `stars` (type: `array`):

Optional star ratings from 1 to 5. Empty means every rating in the preview.

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

Proxy configuration for place requests.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.google.com/maps/place/Yellowstone+National+Park/@44.5857951,-110.5140571,9z/data=!3m1!4b1!4m5!3m4!1s0x5351e55555555555:0xaca8f930348fe1bb!8m2!3d44.427963!4d-110.588455"
    }
  ],
  "placeIds": [],
  "maxReviews": 5,
  "maxItems": 0,
  "language": "en",
  "reviewsOrigin": "all",
  "reviewsFilterString": "",
  "stars": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

Public reviews in the default dataset.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.google.com/maps/place/Yellowstone+National+Park/@44.5857951,-110.5140571,9z/data=!3m1!4b1!4m5!3m4!1s0x5351e55555555555:0xaca8f930348fe1bb!8m2!3d44.427963!4d-110.588455"
        }
    ],
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/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 = {
    "startUrls": [{ "url": "https://www.google.com/maps/place/Yellowstone+National+Park/@44.5857951,-110.5140571,9z/data=!3m1!4b1!4m5!3m4!1s0x5351e55555555555:0xaca8f930348fe1bb!8m2!3d44.427963!4d-110.588455" }],
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/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 '{
  "startUrls": [
    {
      "url": "https://www.google.com/maps/place/Yellowstone+National+Park/@44.5857951,-110.5140571,9z/data=!3m1!4b1!4m5!3m4!1s0x5351e55555555555:0xaca8f930348fe1bb!8m2!3d44.427963!4d-110.588455"
    }
  ],
  "language": "en"
}' |
apify call mlg14/google-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mlg14/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/LOLnC9aF1QuNvmNXU/builds/o9qlc7YuqnaQCFBYO/openapi.json
