# Google Maps Reviews Scraper (`mina_safwat/google-maps-reviews-scraper`) Actor

Scrapes Google Maps reviews of any place from its link, place ID or a search such as "The Savoy London": rating, text with translation, date, likes, owner response, reviewer name and Local Guide status, photos, plus the place's rating and review count. No login needed.

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

## Pricing

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

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** downloads the **reviews of any place on [Google Maps](https://www.google.com/maps)**: restaurants, hotels, shops, attractions, clinics, any business. Give it a **Google Maps link, a place ID or just a search** such as `The Savoy London`, and it returns one row per review with the **star rating, text (with Google's translation), exact publish date, likes, the owner's response, the reviewer's name and Local Guide status, photos**, plus the **place's overall rating and total review count** on every row (the count is sometimes empty, when Google leaves it out).

It needs **no Google account, no login and no API key**, and it reads up to thousands of reviews per place, newest first or in any order Google Maps offers. Running it on Apify gives you API access, scheduling, integrations (Google Sheets, Slack, Zapier, Make, webhooks), proxy rotation and run monitoring.

### Why use Google Maps Reviews Scraper?

- **Reputation monitoring**: track new reviews of your own locations every day and answer unhappy customers fast.
- **Competitor research**: compare ratings, complaints and praise across competing restaurants, hotels or stores.
- **Sentiment and topic analysis**: feed review text (translated into one language) into your analytics or AI pipeline.
- **Market research and lead qualification**: see how busy and well-rated businesses in an area are.
- **Owner-response audits**: check which reviews got an answer and how quickly.

### How to scrape Google Maps reviews

1. Open the Actor and go to the **Input** tab.
2. In **Places**, paste one place per line: a Google Maps link, a place ID, or a search such as `Dishoom Covent Garden`.
3. Set **Max reviews per place** and the **sort order** (newest first by default).
4. Click **Start** and wait a few seconds: 100 reviews of a place take about 10-15 seconds including start-up.
5. Download the reviews from the **Output** tab as JSON, CSV, Excel or HTML, or read them through the API.

### Input

Everything is set in the **Input** tab. Only **Places** is required.

| Field | Default | What it does |
|---|---|---|
| `places` | (required) | One place per line. Accepted: Google Maps place links (`/maps/place/...`, with or without `https://`), share links (`https://maps.app.goo.gl/...`), links with `?cid=`, `ftid=` or `query_place_id=`, Maps search links (`/maps/search/...`, which take the first place shown), place IDs (`ChIJ...`), feature IDs (`0x...:0x...`), and plain searches (`The Savoy London`). API callers can also send `{"url": "..."}` objects. |
| `max_reviews_per_place` | 100 | Stops after this many reviews per place. |
| `sort` | `newest` | `newest`, `most_relevant`, `highest_rating` or `lowest_rating` — the orders Google Maps offers. |
| `language` | `en` | Language code (`en`, `de`, `fr`, `pt-BR`...). Google translates reviews written in other languages into it, as Google Maps does, and names the place in it. |
| `include_original_text` | `false` | Adds `text_original`, the review as its author wrote it, to reviews Google translated. |
| `proxyConfiguration` | none | Leave empty: the Actor picks the cheapest connection Google answers. |

A search takes the **first place Google Maps shows** for it, so include the city (`Café de Flore Paris`, not `Café de Flore`). A Maps search link (`/maps/search/pizza/@41.9,12.49,15z`) or a place link without a place ID (`/maps/place/Starbucks/@51.51,-0.13,17z`) is searched in the map area the link shows, as Google Maps does.

```json
{
  "places": [
    "https://www.google.com/maps/place/Eiffel+Tower/data=!4m2!3m1!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0",
    "ChIJxZXYx7cEdkgRdgAOZ6OHOJw",
    "Café de Flore Paris"
  ],
  "max_reviews_per_place": 200,
  "sort": "newest",
  "language": "en",
  "include_original_text": true
}
```

### Output

One row per review. A real row from Café de Flore in Paris (the reviewer's name and ID are masked here, long texts shortened; with `include_original_text` on, a `text_original` field holds the author's Greek original):

```json
{
  "review_id": "Ci9DQUlRQUNvZENodHljRjlvT201bFVYWkdkbWxtUWs1UkxYVTFWRGhTUTBNeWJrRRAB",
  "review_url": "https://www.google.com/maps/reviews/data=!4m8!14m7!1m6!2m5!1sCi9DQUlRQUNvZENodHljRjlvT201bFVYWkdkbWxtUWs1UkxYVTFWRGhTUTBNeWJrRRAB!2m1!1s0x0:0x18bba6dd45e173ff...",
  "rating": 3,
  "text": "From the outside when you walk by and see it, it's actually a pretty cute shop. There's a bit of a wait in line, but they serve you quickly. We chose 2 savory options that were not edible. Very expensive for no reason and the shop inside is quite uninteresting.",
  "original_language": "el",
  "is_translated": true,
  "published_at": "2026-10-04T14:55:08+00:00",
  "is_edited": false,
  "likes_count": 0,
  "owner_response_text": "Thank you for taking the time to share your impressions following your visit. ...",
  "owner_response_ago": "4 days ago",
  "owner_response_date": "2026-10-06",
  "reviewer_name": "Traveltales G.",
  "reviewer_id": "1094288580745786473xx",
  "reviewer_url": "https://www.google.com/maps/contrib/1094288580745786473xx",
  "reviewer_reviews_count": 154,
  "reviewer_photos_count": 1048,
  "reviewer_is_local_guide": true,
  "photos_count": 6,
  "photo_urls": ["https://lh3.googleusercontent.com/grass-cs/AABkmLdPVI1-ZV1w...=k-no"],
  "details": {
    "Meal type": "Lunch",
    "Price per person": "€30–40",
    "Food": 3,
    "Service": 3,
    "Atmosphere": 3,
    "Seating type": "Indoor dining area, Outdoor patio / terrace"
  },
  "place_name": "Café de Flore",
  "place_id": "ChIJq537gddx5kcR_3PhRd2muxg",
  "place_url": "https://www.google.com/maps/place/?q=place_id:ChIJq537gddx5kcR_3PhRd2muxg",
  "place_address": "Café de Flore, 172 Bd Saint-Germain, 75006 Paris, France",
  "place_rating": 3.9,
  "place_reviews_count": 14541,
  "input": "Café de Flore Paris",
  "scraped_at": "2026-10-10T14:22:45+00:00"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Data fields

| Field | Type | Description |
|---|---|---|
| `review_id` | string | Google's ID of the review; each review is saved once per run. |
| `review_url` | string | Link that opens the review on Google Maps. |
| `rating` | number | Stars, 1 to 5. |
| `text` | string or null | The review text in the chosen `language` (Google's translation when it was written in another language). Null for star-only reviews. |
| `original_language` | string or null | Language code the review was written in (null for star-only reviews). |
| `is_translated` | boolean | Whether `text` is Google's translation. |
| `text_original` | string or null | Only with `include_original_text`: the author's own words when `text` is a translation, otherwise null. |
| `published_at` | string | Exact publish time, or last edit time for edited reviews; ISO 8601 in UTC (from Google's own timestamp). |
| `is_edited` | boolean or null | Whether Google marks the review as edited ("Edited 2 days ago"), so `published_at` is the edit time. Read from Google's English wording, so null when `language` is not English. |
| `likes_count` | number | How many people reacted to the review (likes and Google's other reactions). |
| `owner_response_text` | string or null | The business owner's response. |
| `owner_response_ago` | string or null | When the owner responded, as Google words it (`4 days ago`), in the chosen language. |
| `owner_response_date` | string or null | Approximate response date (`YYYY-MM-DD`): Google only gives the relative age, so it is counted back from the run date (a month as 30 days, a year as 365). Null when `language` is not English. |
| `reviewer_name` | string | The reviewer's public Google name. |
| `reviewer_id`, `reviewer_url` | string | The reviewer's public Google Maps contributor ID and profile link. |
| `reviewer_reviews_count`, `reviewer_photos_count` | number | How many reviews and photos the reviewer has posted on Google Maps. |
| `reviewer_is_local_guide` | boolean | Whether the reviewer is a Google Local Guide. |
| `photos_count`, `photo_urls` | number, list | Photos attached to the review. |
| `details` | object or null | The reviewer's answers to Google's follow-up questions, such as meal type, price per person, or 1-5 scores for food, service, atmosphere or rooms. |
| `place_name`, `place_id`, `place_url`, `place_address` | string | The place the review belongs to. |
| `place_rating` | number | The place's overall Google rating. |
| `place_reviews_count` | number or null | The place's total number of Google reviews. Google leaves it out of many replies at random; the Actor asks up to eight times, but it is sometimes empty. |
| `input` | string | The `places` entry the row came from. |
| `scraped_at` | string | When the row was saved (UTC). |

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

You pay per review saved; see the **Pricing** tab for the exact price. Places that fail or have no reviews cost nothing. The Actor runs over plain HTTP with 512 MB of memory, so platform usage is tiny: our test run of 3,000 reviews from six places took 45 seconds and used **$0.015 of platform resources** (about $0.005 per 1,000 reviews). Apify's free plan credits cover many thousands of reviews a month.

### Tips and advanced options

- **Newest first** is the default and the best choice for monitoring: schedule the Actor daily with a small `max_reviews_per_place` to collect only fresh reviews.
- For a **representative sample**, use `most_relevant`; to find **complaints fast**, use `lowest_rating`.
- In the **rating orders** (`highest_rating`, `lowest_rating`) Google lists only part of a place's reviews (194 of 466 in one test). The run's log and status message say when the list ended before your limit (when Google gave no review count, it may simply be every review there is); use `newest` to get them all.
- Paste the **share link** or the **place page link** when a search could match several places.
- Set `language` to your analysis language to get every review translated by Google; turn on `include_original_text` if you also need the author's words.
- Several places run in parallel; a run with 10 places of 100 reviews each finishes in well under a minute.

### FAQ, disclaimers and support

**Do I need a Google account or API key?** No. The Actor reads the same public review lists Google shows on the web, without signing in.

**How many reviews can I get?** As many as Google lists for the place; the Actor reads them in pages of up to 50 until it reaches your limit or the last review. Sorted `newest` or `most_relevant`, Google lists every review; sorted by rating, it lists only part of them.

**What happens with links that don't work?** Inputs that are not places, places Google doesn't know, places without reviews and dropped-pin links (coordinates) save nothing and cost nothing. They are listed with the reason in the `FAILED_INPUTS` record of the run's key-value store, and the run's status message sums them up.

**Is it legal to scrape Google Maps reviews?** The Actor only reads publicly visible reviews. Whether you may use them depends on your purpose and your country's laws, and on Google's terms. If unsure, consult a lawyer.

**What about personal data and GDPR?** Reviews contain **personal data**: the reviewer's public name, profile ID and link, and whatever they wrote. Under the GDPR and similar laws you need a legitimate reason to collect and keep it. Collect only what you need (drop the reviewer fields if you only analyse text), keep it no longer than necessary, protect it, and honour removal requests. Do not use it to contact or profile individuals without a legal basis.

**Known limitations**: owner-response dates are approximate (Google only says "4 days ago"); `place_reviews_count` is sometimes empty; directions links (`/maps/dir/`) are not read, give one place per line instead; the rating orders list only part of the reviews (see Tips); hotel reviews from partner sites (Tripadvisor, booking sites) are not included, only Google reviews.

**Found a bug or need a feature?** Open an issue on the **Issues** tab and we'll look at it quickly. Need a custom solution, such as a combined places-and-reviews pipeline? Ask there too.

# Actor input Schema

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

One place per line: a Google Maps link (a place page, a share link such as https://maps.app.goo.gl/..., or a link with ?cid= or place_id), a place ID such as ChIJLU7jZClu5kcR4PcOOO6p3I0, or what you would type into Google Maps, such as The Savoy London. A search takes the first place Google Maps shows for it, so add the city to be sure.

## `max_reviews_per_place` (type: `integer`):

Stops after this many reviews for each place, in the order chosen below. Every review is a dataset row.

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

The order Google Maps offers. With a limit set, this decides which reviews you get.

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

Language code such as en, de, fr or pt-BR. Google translates reviews written in other languages into it (as Google Maps does) and names the place in it.

## `include_original_text` (type: `boolean`):

Adds text_original with the review as its author wrote it, for reviews Google translated into the language above.

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

Leave this empty: the Actor picks the cheapest connection Google answers on its own. Set a proxy only to force one.

## Actor input object example

```json
{
  "places": [
    "https://www.google.com/maps/place/Eiffel+Tower/data=!4m2!3m1!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0"
  ],
  "max_reviews_per_place": 30,
  "sort": "newest",
  "language": "en",
  "include_original_text": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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/data=!4m2!3m1!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0"
    ],
    "max_reviews_per_place": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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/data=!4m2!3m1!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0"],
    "max_reviews_per_place": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/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/data=!4m2!3m1!1s0x47e66e2964e34e2d:0x8ddca9ee380ef7e0"
  ],
  "max_reviews_per_place": 30
}' |
apify call mina_safwat/google-maps-reviews-scraper --silent --output-dataset

```

## MCP server setup

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