# Google Play Reviews Scraper & API (`quarra/google-play-store-reviews-scraper`) Actor

Scrape Google Play reviews for any app and language, from app links or package names: rating, text, author, date, app version, helpful votes, developer reply. Full history, filters by rating, date and keyword.

- **URL**: https://apify.com/quarra/google-play-store-reviews-scraper.md
- **Developed by:** [Quarra Labs](https://apify.com/quarra) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 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

## Google Play Reviews Scraper & API

Get the reviews of any app on Google Play, in bulk, without an account or API key. Give it app links or package names,
and the languages you want. Each review comes back with its rating, text, author name as shown in the
store, date, app version, helpful votes and the developer's reply with its date when there is one. Full history, three
sorts, and filters by rating, date and keyword. Export as JSON, CSV or Excel, or read it through the Apify API.

**$0.10 per 1,000 reviews**, plus a small start fee per run. Reviews that do not match your filters, repeats and inputs
that fail are not charged, and each review is charged once per run at most.

### Quick start

1. Paste app links (`https://play.google.com/store/apps/details?id=com.whatsapp`) or package names (`com.whatsapp`) into
   **App links or package names**.
2. Pick the **Languages** and **Max reviews per app and language**.
3. Click **Start** and read the reviews in the run's **Output** tab.

Like any Apify Actor, it can also be run and read through the Apify API, scheduled, and connected to webhooks, Make,
Zapier, n8n or Apify's MCP server for AI agents.

### What it is used for

- **Product feedback**: what users of your app (or a competitor's) complain about or love, version by version.
- **Release monitoring**: newest reviews since a date, run every day, to catch a bad release early.
- **Support**: low ratings that still have no developer reply.
- **Market research**: the same question across languages, or across the apps of a category.
- **AI agents and sentiment analysis**: one clean record per review, the same fields on every store.

### What you get

| | |
|---|---|
| Review ID (stable: use it to deduplicate between runs) | yes |
| Rating and text | yes |
| Author name and public avatar, as shown in the store | yes |
| Date (UTC, ISO 8601) | yes |
| App version the review was written for | yes, when Google Play gives it |
| Helpful votes | yes |
| Developer reply, who replied, and the date of the reply | yes, when there is one |
| App name, store page, country, language | yes |
| Position in the chosen sort | yes |

The same field names are used by our [Apple App Store Reviews Scraper](https://apify.com/quarra/apple-app-store-reviews-scraper),
so you can mix both stores in one pipeline. A field a store does not give is `null`, never missing.

### Inputs

- **App links or package names**: Google Play links in any language, or package names. Up to 500 app and language pairs per run.
- **Languages**: language codes (`en`, `fr`, `zh-TW`…). Each app is read in each language (a regional variant such as
  `pt-BR` gives the same reviews as `pt`: see Limits). Left empty, the language of
  the link is used, otherwise `en`.
- **Country** (`countries` in the API): a two-letter code (`us`, `fr`, `in`…). Google Play shows the same reviews in every
  country (we checked it from several countries), so one is enough: only the first is used, and the run says so. It
  only changes the order of "most relevant" and the app's average rating. Left empty, the country of the link is
  used, otherwise `us`.
- **Max reviews per app and language** and **Max reviews in total**: counted exactly.
- **Sort**: newest first, most relevant, by rating. Only "newest first" lets **Since** stop early.
- **Minimum rating**, **Maximum rating**, **Since**, **Until** (a date such as `2026-01-31`, or a duration such as `30 days`), and
  **Review contains** (up to 50 words, one per line). Ratings are whole stars. With a date filter, the rare reviews
  that have no date are left out.

Example, through the API:

```json
{
  "apps": ["com.whatsapp"],
  "countries": ["us"],
  "languages": ["en"],
  "sort": "newest",
  "maxRating": 2,
  "since": "30 days",
  "maxReviewsPerApp": 1000,
  "maxItems": 5000
}
```

### Output

One record per review in the dataset. A shortened review:

```json
{
  "type": "review",
  "status": "ok",
  "platform": "google-play",
  "reviewId": "dd0ac9db-67bd-4b25-aa0f-ab53da6cec6f",
  "appId": "com.whatsapp",
  "appName": "WhatsApp Messenger",
  "country": "us",
  "language": "en",
  "rating": 5,
  "title": null,
  "text": "very good",
  "author": "Mide Ogundari",
  "authorImageUrl": "https://play-lh.googleusercontent.com/a/…",
  "date": "2026-10-13T11:17:50Z",
  "isEdited": null,
  "appVersion": "2.26.38.73",
  "helpfulVotes": 0,
  "totalVotes": null,
  "replyText": null,
  "replyAuthor": null,
  "replyDate": null,
  "reviewUrl": null,
  "appUrl": "https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=us",
  "input": "com.whatsapp",
  "position": 1,
  "scrapedAt": "2026-10-17T06:30:02Z"
}
```

- `status`: `ok` (delivered, charged) or `error` (free; `errorCode` and `error` say why, `retryable` says if a later run
  may work). A package that does not exist gets a free `app_not_found` record.
- `position` is the rank of the review in the chosen sort for that app and language.
- `country` is the country used to read the reviews; Google Play reviews do not belong to a country.
- `title`, `isEdited`, `totalVotes` and `reviewUrl` are kept for the shared layout and are `null` on this store.

The run summary (counts per app, name, rating, why the run stopped, notes) is the `OUTPUT` record of the run's
key-value store.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| Review | $0.10 per 1,000 |
| Run start | $0.0006 per GB of memory (1 GB minimum; $0.0006 at the default 256 MB) |

Never charged: reviews that do not match your filters, error records, repeats (a review already delivered in the
same run, for another language or input, is skipped). Set **Maximum cost per run** in the run
options and the run stops before going over it, with the reviews delivered so far.

### Limits

- **Language counts, country does not.** Google Play groups reviews by language, and shows the same reviews in every
  country. Regional variants of a language give the same reviews as the language itself (`en-GB` = `en`, `fr-CA` = `fr`,
  `pt-BR` = `pt`…; only Chinese has two sets: traditional `zh-TW`, `zh-HK`, and simplified `zh`, `zh-CN`), so they are
  read once and the run says so. A language the app has no reviews in gives an empty result, with a note.
- **Filters on rating, date and words are applied while reading** (a single rating is applied by Google Play itself).
  Google Play is read from the newest review on, so an older date range is reached by reading everything newer, and
  reading that finds nothing has a limit per run (it is not charged): about 10,000 reviews. On a very big app (WhatsApp
  gets about 2,000 English reviews a day) that is a few days back; the run says how far back it read. Only matching
  reviews are charged.
- **Developer replies** are returned with the review they answer; a reply is not a review of its own.
- Anything missing from a result is said: in the run's status, in the `note` of each app in the `OUTPUT` record, or in
  a free error record.
- If Google Play limits access during a run, the run says so in its status and keeps what it delivered; running it
  again later gives the rest.

### FAQ

**Do I need a Google account or API key?** No.

**What if the run is restarted by the platform (migration or reboot)?** It resumes where it was: reviews already in the
dataset are not delivered or charged again.

**Why do I get fewer reviews than the app's rating count?** Ratings without text are counted by Google Play but have no
review.

**Is it legal?** It collects public reviews shown to any visitor of Google Play. Check the rules that apply to your use
of the data, in particular for personal data such as author names.

**Does the Actor send anything to Quarra?** Only when a run fails or runs out of time: the Actor, its build, the error type, the line of our code where it happened, and the memory and time the run was given, so we can fix it fast. Never your input, your results, your account or the run ID.

### Related tools from Quarra

- [Apple App Store Reviews Scraper](https://apify.com/quarra/apple-app-store-reviews-scraper): the same fields for iOS
  apps, by country.

# Actor input Schema

## `apps` (type: `array`):

One per line: Google Play links (play.google.com/store/apps/details?id=com.whatsapp) or package names.

## `languages` (type: `array`):

Review languages, one per line (en, fr, de, zh-TW…). Each app is read in each language; a regional variant (en-GB, pt-BR…) gives the same reviews as its language and is read once. Empty: the language of the link, otherwise en.

## `countries` (type: `array`):

Google Play country, two letters (us, fr, in…). Google Play shows the same reviews in every country, so one is enough: only the first is used. It only changes the order of 'Most relevant' and the app rating. Empty: the country of the link, otherwise us.

## `maxReviewsPerApp` (type: `integer`):

Stop an app after this many reviews (per language).

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

Stop the run after this many reviews, all apps together.

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

Order of the reviews. 'Newest first' is the one that lets 'Since' stop early.

## `minRating` (type: `integer`):

Keep only reviews with at least this many stars (1 to 5). Empty keeps all. Reviews that do not match are not charged.

## `maxRating` (type: `integer`):

Keep only reviews with at most this many stars (1 to 5). Set both to 1 for one-star reviews only.

## `since` (type: `string`):

Only reviews from this date on: 2026-01-31, or a duration such as '30 days', '3 months'. Empty keeps all. With a date filter, the rare reviews that have no date are left out (not charged).

## `until` (type: `string`):

Only reviews up to this date (included). Empty keeps all.

## `keywords` (type: `array`):

Keep only reviews whose title or text contains one of these words (not case-sensitive). One per line, 50 at most.

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

Connection. Keep the default (automatic). Costs are included in the price.

## Actor input object example

```json
{
  "apps": [
    "com.whatsapp"
  ],
  "languages": [
    "en"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 100,
  "maxItems": 1000,
  "sort": "newest",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Every review with all its fields, and free records with the reason.

## `overview` (type: `string`):

One line per review.

## `summary` (type: `string`):

Counts per app, why the run stopped, errors.

# 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 = {
    "apps": [
        "com.whatsapp"
    ],
    "languages": [
        "en"
    ],
    "countries": [
        "us"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("quarra/google-play-store-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 = {
    "apps": ["com.whatsapp"],
    "languages": ["en"],
    "countries": ["us"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("quarra/google-play-store-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 '{
  "apps": [
    "com.whatsapp"
  ],
  "languages": [
    "en"
  ],
  "countries": [
    "us"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call quarra/google-play-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,quarra/google-play-store-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/ulPEVr1dFhPHLTbai/builds/hJdbuHCjx6U2fcanf/openapi.json
