# Google Maps Reviews Scraper: Text, Ratings, Photos & Replies (`stratumics/google-maps-reviews-scraper`) Actor

Get the Google Maps reviews of any place: rating, full text, exact date, photos, owner reply, reviewer details and food or service scores. Sort by newest to collect only recent reviews.

- **URL**: https://apify.com/stratumics/google-maps-reviews-scraper.md
- **Developed by:** [Stratum ICS](https://apify.com/stratumics) (community)
- **Categories:** SEO tools, Travel, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.20 / 1,000 reviews

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

### What does Google Maps Reviews Scraper do?

**Google Maps Reviews Scraper** extracts the Google reviews of any place on [Google Maps](https://www.google.com/maps): **star rating, full review text, exact date, photos, the owner's reply, the reviewer's name and profile, and scores such as Food, Service and Atmosphere** (Rooms, Service and Location for hotels) when the reviewer gave them. Paste place links or place IDs, or find places with a search term and a location, and get one clean row per review for reputation monitoring, sentiment analysis or competitor research.

Reviews in other languages come with Google's own translation into the language you pick. Sort by newest and set a date limit, and the scraper reads only the reviews posted since then, so a weekly check of all your locations costs cents. Use it from the Apify Console, through the **Apify API** as a Google reviews API, or from any AI agent connected to Apify.

### Why use this Google Maps reviews scraper?

- **The whole review history.** The scraper pages through every review Google lists for a place. A dental office with 735 reviews returned all 735, back to 2018, and one run collected 5,000 reviews of the Eiffel Tower in three and a half minutes.
- **Exact dates.** `publishedAt` is the exact time Google stores for the review, in ISO 8601, next to the "3 weeks ago" text Google shows.
- **Built for monitoring.** With newest-first sorting and **Only reviews newer than** set to "7 days", the scraper stops reading a place at the first older review. Reviews skipped by the date limit are free.
- **Translations included.** You get the original text, its language code, and Google's translation in `textTranslated`.
- **Owner replies, photos and context.** The owner's response, full-size photo links, per-aspect scores (Food, Service and Atmosphere for restaurants; Rooms, Service and Location for hotels), and the answers to Google's follow-up questions (meal type, price per person, wait time, trip type, parking and more).
- **Any link works.** Place page links, `maps.app.goo.gl` share links, `?cid=` links, links with `query_place_id`, and plain place IDs.
- **A privacy switch.** Turn off reviewer details to collect reviews without names, profile links or photos of the people who wrote them.
- **Fast and light.** Plain HTTP requests and no browser: about 20 to 45 seconds per 1,000 reviews of a place, with three places read at the same time.

Typical uses: **reputation monitoring** for multi-location businesses and agencies, **sentiment analysis** and AI summaries of what customers say, competitor research before opening a location, finding unhappy customers to answer (sort by lowest rating), and local SEO audits of how often owners reply.

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

| Field                                                         | Example                                                                      |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `placeName`, `placeAddress`, `placeCategory`                  | Corner Restaurant · 110 E 2nd St, Austin, TX 78701 · Restaurant              |
| `placeRating`, `placeReviewsCount`                            | 4.8 · 18425                                                                  |
| `placeId`, `googleMapsUrl`                                    | ChIJxcCceAi1RIYR9AqXT8eWDyc · link to the place                              |
| `reviewId`, `reviewUrl`                                       | stable review ID · link to the review on Google Maps                         |
| `rating`                                                      | 5                                                                            |
| `text`, `textTranslated`, `language`                          | 美味實惠 · Delicious and affordable · zh-Hant                                |
| `publishedAt`, `publishedAtRelative`                          | 2026-09-25T21:51:46.947Z · 3 weeks ago                                       |
| `isEdited`, `updatedAt`                                       | true when the reviewer edited the review, with the date of the edit          |
| `photos`                                                      | full-size links to the photos attached to the review                         |
| `ownerResponse`                                               | the owner's reply and when it was posted ("2 weeks ago")                     |
| `reviewerName`, `reviewerUrl`, `reviewerPhotoUrl`             | Giovanni Cardenas · public profile link · profile picture                    |
| `reviewerReviewsCount`, `reviewerPhotosCount`, `isLocalGuide` | 45 · 79 · true                                                               |
| `aspectRatings`                                               | {"Food": 5, "Service": 5, "Atmosphere": 5}                                   |
| `reviewContext`                                               | {"Meal type": "Lunch", "Price per person": "$10–20", "Wait time": "No wait"} |
| `searchTerm`, `scrapedAt`                                     | the search that found the place · time of the run                            |

Each run also saves a free summary of every place (name, address, rating, review count, reviews saved, and why a place was skipped) in the **Places** output, the `PLACES` record of the run's key-value store.

### How to scrape Google Maps reviews

1. Open the **Input** tab and paste one or more Google Maps links or place IDs into **Places**, one per line. To pick places by search instead, fill in **Search terms** and **Location**.
2. Set **Max reviews per place**. This also caps what you pay.
3. Choose the **sort order**. For monitoring, pick **Newest** and set **Only reviews newer than**, for example `7 days`.
4. Optionally turn on **Only reviews with text**, turn off **Include reviewer details**, or pick the **language** for translations and relative dates.
5. Click **Start**. Reviews appear in the **Output** tab.
6. Download the results as **CSV, Excel, JSON or HTML**, or send them to Google Sheets, Slack, Zapier, Make or n8n.

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

You pay per review saved:

| Event                                                              | Price                      |
| ------------------------------------------------------------------ | -------------------------- |
| Review saved (all fields above)                                    | $0.00035 ($0.35 per 1,000) |
| Place summaries, reviews skipped by your filters, places not found | Free                       |

**1,000 reviews cost $0.35.** Watching 20 locations every week with a 7-day limit, at about 30 new reviews per location, comes to roughly 2,600 reviews a month, or **$0.91**. Apify's free plan includes $5 of monthly credit, enough for about 14,000 reviews.

Larger Apify plans pay less per review automatically: $0.30 per 1,000 on Starter, $0.25 on Scale and $0.20 on Business. Each run also has a start fee of $0.00005.

### Input

See the **Input** tab for every option. A weekly monitoring run:

```json
{
    "places": [
        "https://www.google.com/maps/place/Toothbar/@30.2671177,-97.7527535,17z/data=!3m1!4b1!4m6!3m5!1s0x8644b511d14d4c3b:0x3062648265433120!8m2!3d30.2671177!4d-97.7527535",
        "https://maps.google.com/?cid=2814634074907806452",
        "ChIJLU7jZClu5kcR4PcOOO6p3I0"
    ],
    "maxReviewsPerPlace": 1000,
    "sort": "newest",
    "reviewsNewerThan": "7 days",
    "includeReviewerDetails": true,
    "language": "en"
}
```

The complaints of the top 10 dentists in a city, in German:

```json
{
    "searchTerms": ["dentist"],
    "location": "Austin, TX",
    "maxPlacesPerSearch": 10,
    "maxReviewsPerPlace": 50,
    "sort": "lowestRating",
    "onlyWithText": true,
    "language": "de"
}
```

- **Places**: any Google Maps link to a place, or a place ID. Links that only point at a map area are skipped and listed in the Places summary.
- **Only reviews newer than**: a date (`2026-01-31`) or a period back from now (`30 days`, `6 months`, `1 year`). It compares against `publishedAt`, which for edited reviews is the date of the last edit.
- **Language and country**: the language sets the translations, the relative dates and the names of the aspect scores and follow-up questions ("Food" becomes "Essen" in German), so keep it the same between runs you want to compare. The country sets where Google looks up searches.

### Output

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. Two records from real runs:

```json
{
    "placeId": "ChIJxcCceAi1RIYR9AqXT8eWDyc",
    "placeName": "Corner Restaurant",
    "placeAddress": "110 E 2nd St, Austin, TX 78701",
    "placeCategory": "Restaurant",
    "placeRating": 4.8,
    "placeReviewsCount": 18425,
    "googleMapsUrl": "https://www.google.com/maps/search/?api=1&query=Corner%20Restaurant&query_place_id=ChIJxcCceAi1RIYR9AqXT8eWDyc",
    "reviewId": "Ci9DQUlRQUNvZENodHljRjlvT2pSUmMyRXpSMU00YjAxNWJGVlNWV3h0U0ZscVNWRRAB",
    "reviewUrl": "https://www.google.com/maps/reviews/data=!4m8!14m7!1m6!2m5!1sCi9DQUlRQUNvZENodHljRjlvT2pSUmMyRXpSMU00YjAxNWJGVlNWV3h0U0ZscVNWRRAB!2m1!1s0x0:0x270f96c74f970af4!3m1!1s2@1:CAIQACodChtycF9oOjRRc2EzR1M4b015bFVSVWxtSFlqSVE%7C%7C",
    "rating": 5,
    "text": "This place was really good everything was so good and the service was amazing!",
    "textTranslated": null,
    "language": "en",
    "publishedAt": "2026-09-25T21:51:46.947Z",
    "publishedAtRelative": "3 weeks ago",
    "updatedAt": null,
    "isEdited": false,
    "photos": [
        "https://lh3.googleusercontent.com/grass-cs/AABkmLc7NnefDwFx28U6udJ_Ov3scD0vocLknAsGLqdEPrGo_gOUSiobHLke9uC4_LHbxf2SgVVL-HLRN5fgbj54nB4nlE8A6kgnBc3Qagd3ZbWdKRqR8VXqHLMBFakozEn4zJBN8x4vcGnfZ8Y8=w1600-h1600-k-no",
        "https://lh3.googleusercontent.com/grass-cs/AABkmLedk-te9R19CmydChreOfpyC1yY2xG-Ftv-oNxvG2GwjeQUwmhwUx3xB29s37Ys2NNKhVr_g80QUSw6LUYuSoyCxJS2iAHvynbYaMRof5dPGdAWCSjhEtYwOTLlowYPFeLZrQFTV64fVi_A=w1600-h1600-k-no"
    ],
    "ownerResponse": {
        "text": "Dear Giovanni Cardenas, thank you so much for your wonderful review! We're thrilled to hear that you had a great experience at The Corner. Our team works hard to create a welcoming atmosphere and serve delicious food, so it means the world to us that you enjoyed your visit. We can't wait to welcome you back again soon! Best Regards, Corner Restaurant Team",
        "publishedAt": null,
        "publishedAtRelative": "2 weeks ago"
    },
    "reviewerName": "Giovanni Cardenas",
    "reviewerId": "116280267191313209109",
    "reviewerUrl": "https://www.google.com/maps/contrib/116280267191313209109/reviews",
    "reviewerPhotoUrl": "https://lh3.googleusercontent.com/a-/ALV-UjVL15yamVuDGbOLf_uJjJRaVaGyFpDKDnep0PMgSCBp7oQlQxZtgA=s128-c-rp-mo-ba12-br100",
    "reviewerReviewsCount": 45,
    "reviewerPhotosCount": 79,
    "isLocalGuide": true,
    "aspectRatings": { "Food": 5, "Service": 5, "Atmosphere": 5 },
    "reviewContext": {
        "Meal type": "Lunch",
        "Price per person": "$10–20",
        "Wait time": "No wait",
        "Seating type": "Indoor dining area, Outdoor patio / terrace, Booth seating",
        "Recommendation for vegetarians": "Highly recommend",
        "Dietary restrictions": "Very accommodating  and ask if u havw allergies before hand.",
        "Kid-friendliness": "Pretty good",
        "Wheelchair accessibility": "Good"
    },
    "source": "Google",
    "searchTerm": null,
    "scrapedAt": "2026-10-18T02:34:49.433Z"
}
```

A review in Chinese with Google's English translation (place fields trimmed):

```json
{
    "placeName": "美德耐 台科大活動中心第一餐廳",
    "placeCategory": "Food court",
    "rating": 5,
    "text": "美味實惠",
    "textTranslated": "Delicious and affordable",
    "language": "zh-Hant",
    "publishedAt": "2025-10-04T13:24:55.126Z",
    "publishedAtRelative": "a year ago",
    "photos": [
        "https://lh3.googleusercontent.com/grass-cs/AABkmLfFfTH-VyCipam4aWY3Qt1U42cA6rXsNxxSUfk9PK7lGfkDzNqX1vxCtlYbhLHLq6kw8hol9JMfKmEVd6VdBRMH6aYVwC80yKIsjr4eLDU2RGUscDD6ThRxnUib6nstkMnzU1MgoY4XhFVs=w1600-h1600-k-no"
    ],
    "ownerResponse": null,
    "reviewerReviewsCount": 46,
    "isLocalGuide": true,
    "aspectRatings": { "Food": 5, "Service": 5, "Atmosphere": 5 },
    "reviewContext": {
        "Order type": "Dine in",
        "Meal type": "Dinner",
        "Price per person": "NT$1–200",
        "Wait time": "No wait"
    }
}
```

### Tips for better results

- **Monitor with a date limit.** Sort by newest, set **Only reviews newer than** a little longer than your schedule (for example 8 days for a weekly run), and merge results on `reviewId`, which never changes.
- **Most relevant** gives a representative sample: Google puts detailed reviews with photos first. **Lowest rating** finds complaints fast.
- **Tens of thousands of reviews from one place?** The scraper read 1,400 to 3,000 reviews a minute per place in our tests; for very large places, raise the run timeout in the run options.
- **Only need the words?** Turn off reviewer details and turn on **Only reviews with text** for a lean dataset for sentiment analysis.
- **A place shows 0 reviews?** Check that the link points at the business itself and not at a whole market, park or neighborhood around it.

### Integrations and API

- **API**: start runs and download results from any language. The **API** tab has ready code in Python, JavaScript and cURL.
- **Python**: `from apify_client import ApifyClient`, then `client.actor("stratumics/google-maps-reviews-scraper").call(run_input={"places": ["ChIJxcCceAi1RIYR9AqXT8eWDyc"], "maxReviewsPerPlace": 200})`.
- **JavaScript**: `import { ApifyClient } from 'apify-client'`, then `client.actor('stratumics/google-maps-reviews-scraper').call({ places: ['ChIJxcCceAi1RIYR9AqXT8eWDyc'], maxReviewsPerPlace: 200 })`.
- **No-code**: Zapier, Make, n8n, Google Sheets and Slack from the **Integrations** tab, for example to add each week's new reviews to a Google Sheet after a scheduled run.
- **AI agents**: connect any MCP-capable assistant to Apify's MCP server (`mcp.apify.com`) and it can call this scraper as a tool to read and summarize the reviews of a place.

### FAQ

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

Google reviews are published for everyone to read, and this scraper does not log in. Reviews do contain personal data, though: the reviewer's name, profile link and picture, and sometimes names inside the text. Personal data is protected by the GDPR in the European Union and by other laws around the world, so only collect it when you have a legitimate reason, keep it no longer than you need, and consult a lawyer if you are unsure. Also consider Google's Terms of Service for your use case.

#### What personal data does it collect, and can I turn it off?

With **Include reviewer details** on (the default), each review carries the reviewer's public name, profile ID and link, profile picture, number of reviews and photos, and Local Guide status, exactly as Google Maps shows them. Turn the option off and those fields are `null`; you still get the rating, text, date, photos and owner reply. The review text itself can still mention people by name.

#### How many reviews can I get from one place?

All the reviews Google lists for it: a dental office with 735 reviews returned all 735. For a place with hundreds of thousands of reviews, set **Max reviews per place** to what you need and raise the run timeout.

#### Why is there no likes count?

The review data Google serves to visitors who are not signed in does not include the number of likes, and this scraper never signs in. The field is left out rather than filled with zeros.

#### Why does the owner reply have no exact date?

Google gives the reply date only as relative text ("2 weeks ago"), which is in `ownerResponse.publishedAtRelative`. `ownerResponse.publishedAt` stays `null` until Google provides more.

#### What is the date of an edited review?

Google keeps one date per review. For an edited review it is the time of the last edit: `isEdited` is `true`, `publishedAtRelative` carries Google's label ("Edited 2 weeks ago"), and `updatedAt` repeats the date. The original posting date is not available.

#### Why are the newest reviews of some landmarks weeks old?

For a few very large landmarks, Google's own newest-first list starts weeks back. When we checked, the Golden Gate Bridge listing's newest reviews were about two months old. Busy places such as restaurants usually show reviews from the same day.

#### Does it collect reviews from other sites shown on Google?

No. It collects Google reviews only, and `source` is "Google".

#### Found a problem or need a field?

Open an issue in the **Issues** tab with the input you used. Every issue is read and usually answered within a day.

# Actor input Schema

## `places` (type: `array`):

The places to read reviews from, one per line. Paste any Google Maps link (a place page, a maps.app.goo.gl share link, a ?cid= link, a link with query_place_id) or a place ID such as ChIJLU7jZClu5kcR4PcOOO6p3I0. Leave empty to find places with the search terms below instead.

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

How many reviews to save for each place. You pay per review saved, so this also caps the cost. Set a high number (for example 10000) to get all reviews.

## `sort` (type: `string`):

The order Google returns reviews in. Newest first is best for monitoring and works with the date limit below.

## `reviewsNewerThan` (type: `string`):

Keep only reviews published (or last edited) after this point: a date such as 2026-01-31, or a period back from now such as 30 days, 6 months or 1 year. With newest-first sorting the scraper stops reading a place at the first older review, so monitoring runs stay cheap. Leave empty for no limit.

## `onlyWithText` (type: `boolean`):

Skip reviews that have a star rating but no written text. Skipped reviews are free.

## `includeReviewerDetails` (type: `boolean`):

Add the reviewer's name, profile link, photo, review count and Local Guide status. Turn off to collect reviews without personal data about the people who wrote them.

## `searchTerms` (type: `array`):

Instead of links, find places on Google Maps and read their reviews, for example "dentist" or "hotel". Used together with the location below.

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

City, region, postal code or country for the search terms, written as in Google Maps: "Austin, TX", "Manchester, UK". Leave empty to put the location inside the search term ("dentist in Austin").

## `maxPlacesPerSearch` (type: `integer`):

How many places to take for each search term, in Google's order.

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

Language of relative dates ("2 weeks ago") and of Google's translations: reviews written in other languages get a translation into this one in textTranslated.

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

Two-letter country code Google uses to look up places and searches ("us", "gb", "de").

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

Apify's datacenter proxy works with Google reviews and is used by default. If Google blocks it, the scraper switches to a direct connection on its own.

## Actor input object example

```json
{
  "places": [
    "https://www.google.com/maps/place/Eiffel+Tower/@48.8583701,2.2944813,17z/data=!4m6!3m5!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0!8m2!3d48.8583701!4d2.2944813"
  ],
  "maxReviewsPerPlace": 20,
  "sort": "newest",
  "reviewsNewerThan": "",
  "onlyWithText": false,
  "includeReviewerDetails": true,
  "searchTerms": [],
  "location": "",
  "maxPlacesPerSearch": 10,
  "language": "en",
  "countryCode": "us",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `replies` (type: `string`):

No description

## `allFields` (type: `string`):

No description

## `places` (type: `string`):

No description

# 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 = {
    "places": [
        "https://www.google.com/maps/place/Eiffel+Tower/@48.8583701,2.2944813,17z/data=!4m6!3m5!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0!8m2!3d48.8583701!4d2.2944813"
    ],
    "maxReviewsPerPlace": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("stratumics/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 = {
    "places": ["https://www.google.com/maps/place/Eiffel+Tower/@48.8583701,2.2944813,17z/data=!4m6!3m5!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0!8m2!3d48.8583701!4d2.2944813"],
    "maxReviewsPerPlace": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("stratumics/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 '{
  "places": [
    "https://www.google.com/maps/place/Eiffel+Tower/@48.8583701,2.2944813,17z/data=!4m6!3m5!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0!8m2!3d48.8583701!4d2.2944813"
  ],
  "maxReviewsPerPlace": 20
}' |
apify call stratumics/google-maps-reviews-scraper --silent --output-dataset

```

## MCP server setup

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