# Google Maps Reviews Scraper: Ratings, Text & Owner Reply (`themineworks/google-maps-reviews`) Actor

Scrape Google Maps reviews: star rating, reviewer name, full text, date, owner response and photo count. Works as MCP tool in Claude, ChatGPT & AI agents. Pay per result, first 10 free.

- **URL**: https://apify.com/themineworks/google-maps-reviews.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Social media, Business, MCP servers
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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: Ratings, Text & Owner Replies

💰 From $7.00 / 1,000 results.

Pay only for results delivered. [Browse all Actors](https://apify.com/themineworks).

> ### ✅ Rebuilt 2026-08-18, working again, and much cheaper
>
> In February 2026 Google stopped showing reviews to logged-out visitors. Every
> scraper that read reviews off the Maps page, including this one, started returning
> empty results. An earlier note on this page claimed the problem was fixed by
> reading the rendered page instead. **That claim was wrong** and this page has been
> corrected: those runs were still returning zero reviews.
>
> This Actor no longer tries to read the blocked page. It now reads reviews through a
> licensed upstream data source that has working access, so reviews flow again,
> including reviews posted in the last few days. Verified live 2026-08-18.
>
> Two things got better as a side effect: every review now carries a **real
> timestamp** (`reviewDateIso`) instead of only "a month ago" text, and the Actor no
> longer needs a browser or proxy, so it is dramatically cheaper to run.
>
> For Google Maps *business listings* (name, category, address, phone, website,
> rating, hours), the
> [Google Maps Search Scraper](https://apify.com/themineworks/google-maps-search-scraper)
> is a separate, cheaper option when you don't need reviews.

### Overview

Give this Actor one or more Google Maps place URLs and it returns their reviews as
clean, structured rows: star rating, the full review text, a real timestamp, the
reviewer's profile and Local Guide status, the owner's reply, per-category
subratings (food, service, atmosphere) and any photos attached to the review.

No login. No cookies. No proxy configuration. No Google API key.

✅ Works after Google's 2026 logged-out review blackout · ✅ Real ISO timestamps · ✅ Owner replies included · ✅ Pay only for reviews delivered · ✅ MCP-ready for AI agents

### How to scrape Google Maps reviews after the 2026 blackout

Google's official Places API caps you at **five reviews per place**, gives you no
control over sort order, and needs a billing-enabled Google Cloud project. Reading
the Maps page directly no longer works at all for logged-out visitors, which is what
any scraper is.

This Actor takes the third route: it reads the same public reviews through a licensed
upstream data source that still has access. You get far more than five reviews per
place, you choose the sort order, and there is nothing to configure.

```json
{
  "placeUrls": ["https://www.google.com/maps/place/Starbucks/@40.7566447,-73.9859019,17z/data=!4m6!3m5!1s0x89c258552071bcb3:0x5cc7129cc313de1a"],
  "maxReviews": 50,
  "sortBy": "newest"
}
```

### Input configuration

| Field | Type | Description |
|---|---|---|
| `placeUrls` | array | Google Maps place URLs. Paste straight from the Maps address bar. A bare `place_id` (`ChIJ...`) or `data_id` (`0x...:0x...`) also works. If a URL has no id but does have a place name, it is resolved automatically. **Max 25 places per run.** |
| `maxReviews` | integer | Maximum reviews **per place**, not per run. 50 with three places returns up to 150. Default 20, max 500. |
| `sortBy` | select | `newest` (default), `mostRelevant`, `highestRating`, `lowestRating`. |
| `language` | string | Two-letter language code, e.g. `en`, `hi`, `fr`. Default `en`. |
| `country` | string | Optional two-letter country code, e.g. `in`, `us`, `gb`. |
| `includeReviewInsights` | boolean | Adds one insights row per place. See below. Off by default. |
| `litescrapeApiKey` | string | Advanced and almost nobody needs it. Leave blank to use the Actor's own licensed source; supply your own key to bill upstream usage to yourself. |

#### Finding a place URL

Search the place on [Google Maps](https://www.google.com/maps), click it, and copy
the URL from your browser's address bar. That URL contains everything this Actor
needs.

### Output format

One row per review:

```json
{
  "reviewId": "Ci9DQUlRQUNvZENodHljRjlvT21sUFEzcG5XakJQVURWeWNWVnpXbm81ZDBSdGVrRRAB",
  "placeId": "0x89c258552071bcb3:0x5cc7129cc313de1a",
  "placeName": "Starbucks Coffee Company",
  "reviewerName": "Melih can Odacioglu",
  "reviewerUrl": "https://www.google.com/maps/contrib/108626243016843073804",
  "reviewerIsLocalGuide": true,
  "reviewerReviewCount": 83,
  "rating": 1,
  "reviewText": "staff are extremely slow",
  "reviewDate": "3 days ago",
  "reviewDateIso": "2026-08-15T03:11:54Z",
  "ownerResponse": null,
  "ownerResponseDate": null,
  "photoCount": 1,
  "photoUrls": ["https://lh3.googleusercontent.com/..."],
  "subratings": { "food": 1, "service": 1, "atmosphere": 1 },
  "reviewUrl": "https://www.google.com/maps/reviews/...",
  "likes": 0
}
```

Every field that Google does not publish for a given review is returned as `null`
rather than guessed. A rating-only review (very common) has `reviewText: null` and is
still a real, charged row.

Each place also gets a `_type: "summary"` row, and every run ends with a
`_type: "run_summary"` row carrying totals and the realised upstream cost.

### Review insights (optional, `includeReviewInsights: true`)

Adds one extra row per place, computed from the reviews already collected in the same
run. No AI, no second fetch, no guesswork:

```json
{
  "_type": "review_insights",
  "placeName": "Starbucks Coffee Company",
  "rating_distribution": { "1_star": { "count": 2, "pct": 20 }, "5_star": { "count": 4, "pct": 40 } },
  "reply_rate_negative_pct": 33.3,
  "top_complaint_terms": [{ "term": "slow", "count": 4 }, { "term": "queue", "count": 3 }],
  "rating_trend": [
    { "month": "2026-07", "review_count": 3, "avg_rating": 3.67 },
    { "month": "2026-08", "review_count": 7, "avg_rating": 3.57 }
  ],
  "based_on_reviews": 10,
  "based_on_negative_reviews": 3
}
```

- **`rating_distribution`**, how the stars actually split, not just the average.
- **`reply_rate_negative_pct`**, how often the owner answers 1 and 2 star reviews. The single best signal of whether a business manages its reputation.
- **`top_complaint_terms`**, the words that recur in negative reviews. Needs a decent sample: set `maxReviews` to 50 or more, or you will often get an empty list because nothing repeats.
- **`rating_trend`**, average rating month by month, so you can see a business getting better or worse.

Charged once per place, and only for a place that actually returned reviews.

### Common use cases

- **Reputation monitoring**, schedule it daily on your own locations and your competitors', sorted by `newest`, and watch ratings move.
- **Competitor teardown**, pull `lowestRating` first to read exactly what customers complain about next door.
- **Location benchmarking**, run 25 branches in one go and rank them by rating distribution and owner reply rate.
- **Pre-acquisition due diligence**, `rating_trend` shows whether a business's reputation is improving or sliding.
- **Review response workflows**, find unanswered negative reviews (`ownerResponse: null`, `rating <= 2`) and work the list.

### Getting started

1. Open Google Maps, find your place, copy the URL from the address bar.
2. Paste it into **Place URLs**.
3. Set **Max reviews per place** (start with 10 to see the shape, then raise it).
4. Optionally switch on **Include review insights**.
5. Click **Start**.

### Run on a schedule

Reputation data is only useful if it is current. In Apify Console open this Actor →
**Schedules** → **Add schedule** → pick a frequency (daily works well for
monitoring) → **Save**. It reruns with the same input automatically. Combine a daily
schedule with `sortBy: newest` and a modest `maxReviews` to keep costs low while
never missing a new review.

### FAQ

**Do I need a Google account, cookies, or an API key?**
No. Nothing to log into and nothing to configure.

**Why did this Actor stop returning reviews earlier in 2026?**
Google stopped rendering reviews for logged-out visitors in February 2026. Any
scraper reading the Maps page directly, including this one, went empty. It now reads
through a licensed upstream source instead, which is why it works again.

**How many reviews can I get per place?**
Up to 500 per run via `maxReviews`. That is far beyond Google's official Places API,
which caps at five.

**Why is `top_complaint_terms` empty?**
A term has to recur to be a pattern. On a handful of reviews nothing repeats. Raise
`maxReviews` to 50 or more.

**Why is `reviewText` null on some rows?**
Plenty of people leave a star rating and no words. That is a real review, so it is
returned rather than dropped.

**Am I charged if a place returns nothing?**
No. You are charged per review delivered, and the insights row is only charged for a
place that actually returned reviews. A blocked or empty run costs you nothing.

**Is scraping Google Maps reviews legal?**
This Actor collects only publicly visible review content. Public data can still
contain personal data under laws like the GDPR, so collect only what you have a
legitimate purpose for, and keep it no longer than you need.

### Use in Claude, ChatGPT and any MCP agent

```
https://mcp.apify.com/?tools=themineworks/google-maps-reviews
```

Or call it programmatically:

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/google-maps-reviews').call({
  placeUrls: ['https://www.google.com/maps/place/...'],
  maxReviews: 50,
  sortBy: 'newest',
  includeReviewInsights: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### 🛠️ Complete your Google Maps pipeline

Pair this reviews scraper with the rest of the themineworks Google Maps and lead gen suite:

- **[Google Maps Search Scraper](https://apify.com/themineworks/google-maps-search-scraper)**: turn a Maps search into a plain business listing dataset, no email step, the cheapest way to find the businesses in the first place.
- **[Google Maps Leads Scraper](https://apify.com/themineworks/maps-leads)**: turn a Maps search into B2B leads with verified emails.
- **[Website Contact Scraper](https://apify.com/themineworks/website-contact-finder)**: extract emails, phones, and socials from any domain list.
- **[Email Verifier & Validator](https://apify.com/themineworks/email-verifier-validator)**: MX and SMTP verify addresses before you send.
- **[B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder)**: find named decision makers at target companies.

Common flow: google-maps-search-scraper finds businesses, maps-leads adds verified emails, then google-maps-reviews pulls reviews for the same businesses to gauge reputation.

***

**Disclaimer:** This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Google LLC. Google and Google Maps are trademarks of Google LLC. Use scraped public data in line with GDPR, CCPA, and your local laws.

Found a bug or have a feature request? Open an issue on the Actor's Apify Console page or reach out through the Apify profile.

### Related guides

- [Google Maps Reviews Scraper: Extract Ratings, Text and Owner Replies Without an API](https://themineworks.com/blog/google-maps-reviews-scraper-python)

*Last verified: 2026-08*

# Actor input Schema

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

Google Maps place URLs to scrape reviews from, e.g. https://www.google.com/maps/place/Starbucks/@40.7566,-73.9859,17z. Paste them straight from the Maps address bar. A bare Google place\_id (ChIJ...) or data\_id (0x...:0x...) also works. If a URL carries no id but does carry a place name, it is resolved automatically. Max 25 places per run.

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

Maximum reviews PER PLACE (not per run), so 50 with three places can return up to 150. Reviews arrive in pages of 8-20. You are never charged for reviews that do not exist, or for a place that returns nothing.

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

Which reviews to take first. Newest is the default and is what most monitoring uses.

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

Two-letter language code for the results, e.g. en, hi, fr.

## `includeReviewInsights` (type: `boolean`):

Adds one extra insights row PER PLACE: rating breakdown, the most common phrases in negative reviews, the owner's reply rate on negative reviews, and a month by month rating trend. Computed from the reviews already collected in this run — no AI, no extra fetch. Only charged for a place that actually returned reviews.

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

Two-letter country code to localise results, e.g. in, us, gb. Leave blank for default.

## `litescrapeApiKey` (type: `string`):

Advanced, and almost nobody needs this. Leave blank and the actor uses its own licensed data source. Supply your own litescrape.com key to bill that upstream usage to your account instead.

## Actor input object example

```json
{
  "placeUrls": [
    "https://www.google.com/maps/place/Starbucks/@40.7566447,-73.9859019,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258552071bcb3:0x5cc7129cc313de1a!8m2!3d40.75664!4d-73.9859!16s%2Fg%2F1tj6vr2s"
  ],
  "maxReviews": 10,
  "sortBy": "newest",
  "language": "en",
  "includeReviewInsights": false,
  "country": "us"
}
```

# Actor output Schema

## `results` (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 = {
    "placeUrls": [
        "https://www.google.com/maps/place/Starbucks/@40.7566447,-73.9859019,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258552071bcb3:0x5cc7129cc313de1a!8m2!3d40.75664!4d-73.9859!16s%2Fg%2F1tj6vr2s"
    ],
    "maxReviews": 10,
    "sortBy": "newest",
    "language": "en",
    "includeReviewInsights": false,
    "country": "us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/google-maps-reviews").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": ["https://www.google.com/maps/place/Starbucks/@40.7566447,-73.9859019,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258552071bcb3:0x5cc7129cc313de1a!8m2!3d40.75664!4d-73.9859!16s%2Fg%2F1tj6vr2s"],
    "maxReviews": 10,
    "sortBy": "newest",
    "language": "en",
    "includeReviewInsights": False,
    "country": "us",
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/google-maps-reviews").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": [
    "https://www.google.com/maps/place/Starbucks/@40.7566447,-73.9859019,17z/data=!3m1!4b1!4m6!3m5!1s0x89c258552071bcb3:0x5cc7129cc313de1a!8m2!3d40.75664!4d-73.9859!16s%2Fg%2F1tj6vr2s"
  ],
  "maxReviews": 10,
  "sortBy": "newest",
  "language": "en",
  "includeReviewInsights": false,
  "country": "us"
}' |
apify call themineworks/google-maps-reviews --silent --output-dataset

```

## MCP server setup

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

```

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/0bXQKjmwptDNjBbQq/builds/oj9DbjW32g5kdiySA/openapi.json
