# Google Maps Reviews Scraper | 💰 $0.25 per 1,000 results (`solidcode/google-maps-reviews-scraper`) Actor

\[💰 $0.25 / 1K] Scrape Google Maps reviews at scale. Extract review text, ratings, reviewer details, owner responses, photos, and more for any place on Google Maps.

- **URL**: https://apify.com/solidcode/google-maps-reviews-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Automation, Other, Developer tools
- **Stats:** 57 total users, 10 monthly users, 99.6% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.25 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Reviews Scraper

Export the review history of any place on Google Maps as clean spreadsheet rows: star ratings, full review text, reviewer profiles, owner replies, and review photos. Built for reputation managers, market researchers, and analysts who need a place's complete review record, not the handful of reviews a page happens to show before it stops loading.

### Why This Scraper?

- **Date-range exports that are actually complete.** Google's "newest" feed is not in date order. Across a 2,757-review sample, every place tested served reviews out of position, some by years. This scraper reads straight past those instead of stopping at the first old one, so "everything since January" really means everything since January.
- **Up to 50,000 reviews from a single listing.** Set the per-place limit to `0` and take the whole history in one run.
- **20 fields per review**, including each reviewer's lifetime review count, their photo count, and their Local Guide badge, so a 5-star rave from a 900-review Local Guide can be weighted differently from a first-timer's.
- **Owner replies on the same row as the review they answer**, with the date the business posted them.
- **Review photos as full-size image links**, listed per review.
- **4 sort orders** (Most Relevant, Newest First, Highest Rating, Lowest Rating). Lowest Rating with a limit of 100 buys you a complaint sample for cents instead of an entire history.
- **33 review languages and 184 countries.** Reviews come back in whatever language they were written in, each row tagged with its own language code, and you pick which country's view of Maps to collect.
- **Three ways to name a place, mixable in one run:** a Maps URL, a `ChIJ…` place ID, or plain text like "Katz's Delicatessen New York".
- **Runs report honestly.** If reviews cannot be retrieved, the run fails and names the reason instead of handing you an empty file marked "succeeded". Partial runs say how many places came back short.

### Use Cases

#### Reputation Monitoring

- Track new reviews across every one of your locations in one dataset
- Pull only reviews posted since your last export and route them to Slack or email
- Catch owner replies that were never written, by filtering rows where the response field is empty

#### Competitive Intelligence

- Compare rating distributions across every competitor in a trade area
- Read a rival's 1-star and 2-star reviews in bulk to find the failure they keep repeating
- Track how a competitor's rating moves month by month after a refurbishment or menu change

#### Lead Generation

- Build prospect lists of businesses whose ratings slipped below a threshold
- Find high-review-volume locations worth a partnership approach
- Identify businesses that never respond to reviews, an easy opening for reputation services

#### Customer Experience Research

- Mine thousands of reviews for the phrases customers repeat about wait times, staff, or parking
- Separate tourist feedback from local feedback using reviewer review counts and Local Guide status
- Compare what customers praise in one city against another for the same brand

#### Academic and Data Science

- Assemble large labelled review corpora for sentiment and NLP work
- Study rating behaviour, reviewer tenure, and photo-contribution patterns
- Analyse temporal and geographic trends in consumer feedback

### Getting Started

#### Paste place URLs

The fastest start. Paste one or more Google Maps place links:

```json
{
    "placeUrls": [
        "https://www.google.com/maps/place/Eiffel+Tower/@48.8583701,2.2944813"
    ],
    "maxReviewsPerPlace": 100
}
```

#### Search by name

No URL? Give the name and the city:

```json
{
    "searchQueries": ["Katz's Delicatessen New York", "Sagrada Familia Barcelona"],
    "maxReviewsPerPlace": 200
}
```

#### Only reviews since a date

Everything published on or after your cutoff. Reviews outside the range are dropped before they reach your dataset, so they cost you nothing:

```json
{
    "placeUrls": ["https://www.google.com/maps/place/..."],
    "reviewsStartDate": "2024-01-01",
    "maxReviewsPerPlace": 0
}
```

#### Complaints only, in a local market

Lowest ratings first, in the language and country you care about:

```json
{
    "searchQueries": ["Tokyo Tower"],
    "maxReviewsPerPlace": 100,
    "sortBy": "lowest",
    "language": "ja",
    "countryCode": "JP"
}
```

### Input

#### Places

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `placeUrls` | string\[] | `[]` | Google Maps place URLs or place IDs (`ChIJ…`). One per line. |
| `searchQueries` | string\[] | `[]` | Place names to look up, for example "Eiffel Tower Paris". One per line. |

You can supply both in the same run.

#### Collection options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxReviewsPerPlace` | integer | `100` | Reviews to collect per place. `0` means everything, up to 50,000. |
| `sortBy` | string | `relevant` | Most Relevant, Newest First, Highest Rating, or Lowest Rating. Forced to Newest First whenever a start date is set. |
| `reviewsStartDate` | string | empty | Collect only reviews published on or after this date (`YYYY-MM-DD`). Also switches the sort to Newest First. |

#### Language and region

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `language` | string | `en` | One of 33 languages for the Google Maps interface. Review text itself always comes back in the language the reviewer wrote it in. |
| `countryCode` | string | Auto-detect | One of 184 countries. The run is made from that country, so results match what a visitor there would see. Leave empty to let Google choose. |

### Output

Every review is one row, with up to 20 fields:

```json
{
    "reviewId": "Ci9DQUlRQUNvZENodHljRjlvT2xWbExYUlBlRTFrWjB0...",
    "rating": 5,
    "reviewText": "Incredible family-style Italian food. The portions are massive and perfect for sharing, and service was attentive even on a busy Saturday night.",
    "language": "en",
    "publishedAt": "2026-06-20T17:16:06Z",
    "publishedAtTimestamp": 1781975766,
    "reviewPhotoUrls": ["https://lh3.googleusercontent.com/..."],
    "responseFromOwnerText": "Thank you for the wonderful review! We hope to see you again soon.",
    "responseFromOwnerDate": "2026-06-22",
    "reviewUrl": "https://www.google.com/maps/reviews/data=Ci9DQUlRQUNvZENodHlj...",
    "source": "Google",
    "reviewerName": "Sarah M.",
    "reviewerUrl": "https://www.google.com/maps/contrib/1234567890123456789",
    "reviewerPhotoUrl": "https://lh3.googleusercontent.com/a-/ALV-UjU...",
    "reviewerNumberOfReviews": 852,
    "reviewerNumberOfPhotos": 8391,
    "isLocalGuide": true,
    "placeName": "Carmine's - Times Square",
    "placeUrl": "https://www.google.com/maps/place/...",
    "placeFeatureId": "0x89c259af3367d0f5:0x3bdb6f7c1c5b8b5d"
}
```

#### Review fields

| Field | Type | Description |
|-------|------|-------------|
| `reviewId` | string | Unique identifier for the review, stable across runs |
| `rating` | number | Star rating, 1 to 5 |
| `reviewText` | string | Full review text. Empty when the reviewer left a rating only |
| `language` | string | Language the review was written in |
| `publishedAt` | string | Publication date and time, ISO 8601 (`2026-06-20T17:16:06Z`) |
| `publishedAtTimestamp` | number | The same moment as a Unix timestamp, ready to sort or filter on |
| `reviewPhotoUrls` | string\[] | Full-size links to photos attached to the review |
| `responseFromOwnerText` | string | The business owner's public reply, when there is one |
| `responseFromOwnerDate` | string | Date the owner replied |
| `reviewUrl` | string | Direct link to the review on Google Maps |
| `source` | string | Platform the review came from |

#### Reviewer fields

| Field | Type | Description |
|-------|------|-------------|
| `reviewerName` | string | Reviewer's display name |
| `reviewerUrl` | string | Link to the reviewer's public Google Maps profile |
| `reviewerPhotoUrl` | string | Reviewer's profile photo |
| `reviewerNumberOfReviews` | number | How many reviews this person has written in total |
| `reviewerNumberOfPhotos` | number | How many photos this person has contributed in total |
| `isLocalGuide` | boolean | Whether Google marks them as a Local Guide |

#### Place fields

| Field | Type | Description |
|-------|------|-------------|
| `placeName` | string | Name of the reviewed place |
| `placeUrl` | string | Google Maps link to the place |
| `placeFeatureId` | string | Google's own identifier for the place, useful for joining runs together |

### Tips for Best Results

- **Name the city in every search query.** "Katz's Delicatessen New York" resolves to one listing; "Katz's" can land on a different branch in a different country.
- **A start date overrides your sort order.** Setting `reviewsStartDate` switches collection to Newest First, because that is the only order a date range can be read in. If a specific order matters more than the date window, use one or the other, not both.
- **Raise the per-place limit when you use a date range.** The limit counts reviews delivered to your dataset, so a busy place can hit `100` long before it reaches your cutoff. The run log names which of the two ended collection.
- **Filter ratings after export, not before.** Google offers no rating filter, so pull the reviews you want and filter on the `rating` column in your spreadsheet or database.
- **Use `publishedAtTimestamp` for repeat exports.** Keep the highest timestamp from your last run and use it as the next run's start date to pick up only what is new.
- **Pair `language` with `countryCode`.** A Japanese-language run from Japan surfaces a noticeably different review mix than the same place requested from the US.
- **Split places with 10,000+ reviews across runs.** Two runs with different sort orders reach further into a huge review history than one long run with a single order.

### Pricing

**From $0.22 per 1,000 reviews.** One flat rate per review, whichever place it came from. You pay for reviews delivered to your dataset, plus a small fixed start fee each time a run begins. Reviews filtered out by your date range never reach the dataset and are never charged. Bronze, Silver, and Gold subscribers pay progressively less, and the table shows the total at each discount tier.

| Reviews | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.025 | $0.024 | $0.023 | $0.022 |
| 1,000 | $0.25 | $0.24 | $0.23 | $0.22 |
| 10,000 | $2.50 | $2.40 | $2.30 | $2.20 |
| 100,000 | $25.00 | $24.00 | $23.00 | $22.00 |

Standard Apify platform fees apply on top.

### Integrations

Export as JSON, CSV, Excel, XML, or RSS, and connect to 1,500+ apps:

- **Zapier** / **Make** / **n8n** — workflow automation
- **Google Sheets** — direct spreadsheet export
- **Slack** / **Email** — alerts when a run finishes
- **Webhooks** — push new reviews into your own systems
- **Apify API** — full programmatic access for scheduling, monitoring, and data retrieval

### Legal and Ethical Use

This actor is built for legitimate reputation monitoring, market research, and competitive intelligence. You are responsible for complying with applicable laws and Google's Terms of Service. Do not use collected data for spam, harassment, or any unlawful purpose.

# Actor input Schema

## `placeUrls` (type: `array`):

Paste Google Maps place URLs here. You can also paste the place identifier from the URL.

## `searchQueries` (type: `array`):

Search terms for places you want to scrape, such as 'Eiffel Tower Paris' or 'Central Park New York'.

## `maxReviewsPerPlace` (type: `integer`):

Maximum number of reviews to scrape per place. Set to 0 for all reviews. Recommended: 100-1000 to keep costs reasonable.

## `sortBy` (type: `string`):

Choose the order in which reviews should be collected. Note: if you also set a Reviews Start Date below, this is automatically changed to 'Newest First' — that is the only order a date range can be collected in.

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

Language used for Google Maps and the review text returned when available.

## `countryCode` (type: `string`):

Country to collect from. Google Maps is asked for places and reviews as a visitor in this country would see them, and the run is made from that country whenever a connection is available there. If none is, the run still goes ahead from another country and the log says so. Leave empty to let Google decide automatically.

## `reviewsStartDate` (type: `string`):

Only collect reviews published on or after this date. Use the format YYYY-MM-DD, for example 2024-01-15. Leave empty to collect all reviews. Setting a date changes Sort Reviews By to 'Newest First' automatically, so any other sort order you picked is ignored.

## Actor input object example

```json
{
  "placeUrls": [],
  "searchQueries": [],
  "maxReviewsPerPlace": 100,
  "sortBy": "relevant",
  "language": "en"
}
```

# Actor output Schema

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

Table of scraped reviews with key fields.

## `details` (type: `string`):

Detailed review data including photos and owner responses.

# 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 = {
    "placeUrls": [],
    "searchQueries": [],
    "maxReviewsPerPlace": 100,
    "sortBy": "relevant",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/google-maps-reviews-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 = {
    "placeUrls": [],
    "searchQueries": [],
    "maxReviewsPerPlace": 100,
    "sortBy": "relevant",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/google-maps-reviews-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 '{
  "placeUrls": [],
  "searchQueries": [],
  "maxReviewsPerPlace": 100,
  "sortBy": "relevant",
  "language": "en"
}' |
apify call solidcode/google-maps-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/google-maps-reviews-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/dCxreJ9sXbeeijwPk/builds/aKurq0nwmsjfpU70Y/openapi.json
