# Google Play Reviews Scraper Pro (`goldenbios/my-actor-2`) Actor

Extract Google Play app reviews with ratings, full text, dates, thumbs up counts, app versions and developer replies. Filter by date and rating, sort four ways, choose language and country, and get a per-app analytics summary with the full star distribution.

- **URL**: https://apify.com/goldenbios/my-actor-2.md
- **Developed by:** [Goldenbios](https://apify.com/goldenbios) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 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?

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 Pro

Extract **Google Play Store reviews** for any Android app — author, star rating, full text, date, helpful count, the app version reviewed, and **the developer's public reply**. Sort by newest, most relevant, highest or lowest rating; filter by date range, rating range, or "developer replied only". Every app ends with a summary item that accounts honestly for what was fetched, emitted, and filtered, with the 1–5 star distribution of the result set.

Built for app developers doing ASO and review mining, support teams tracking complaints after a release, and market researchers comparing competitors' ratings over time.

### Why this actor?

|  | Google Play Reviews Scraper Pro | The niche leader |
| --- | --- | --- |
| Price | **Flat per review** (see the Pricing tab) — no subscription | **$25/month flat subscription** ($19.99 tier) |
| Small jobs | 2,000 reviews cost pocket change, once | A one-off job still pays a full month |
| Date range filter | **Yes** — start and end date, with early stop on newest sort | Limited |
| Rating range filter | **Yes** — min and max stars | Star filter only |
| Developer replies | Text + date on every review, plus a "replied only" filter | Partial |
| Per-app summary | Fetched / emitted / filtered + average rating + 1–5 star distribution | Usually absent |
| Minimums / start fees | **None** | Subscription commitment |

### What it extracts (per review)

| Field | Description |
| --- | --- |
| `authorName` | Review author's display name |
| `rating` | Star rating, 1–5 |
| `text` | Full review text (`null` for rating-only reviews) |
| `reviewDate` | When the review was posted, ISO 8601 UTC |
| `thumbsUpCount` | How many users marked the review helpful |
| `appVersion` | The app version the review was written against, when Google knows it |
| `developerReply` / `developerReplyDate` | The developer's public reply and when it was posted |
| `reviewId` / `reviewUrl` | Google's review id and the public Play link anchoring to it |
| `appId` | The package name the review belongs to |

### Inputs

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `appIds` | string list | — | Package names (`com.whatsapp`) and/or Play Store URLs — the `id=` parameter is read from URLs |
| `maxReviewsPerApp` | integer | 100 | Cap on reviews emitted per app, after filters |
| `sortOrder` | select | `newest` | `newest`, `mostRelevant`, `highestRating`, or `lowestRating` (see Honest limits) |
| `language` | string | `en` | Storefront language (`hl`) |
| `country` | string | `us` | Storefront country (`gl`) |
| `reviewsStartDate` / `reviewsEndDate` | date | — | Keep reviews inside this window (inclusive, UTC) |
| `minRating` / `maxRating` | number | — | Keep reviews inside this star range |
| `onlyWithDeveloperReply` | boolean | false | Keep only reviews the developer replied to |
| `includeSummary` | boolean | true | Emit one summary item per app |
| `proxyConfiguration` | proxy | Apify Proxy | Standard Apify Proxy is normally enough; RESIDENTIAL is the fallback for repeated 403s |

### Outputs

Three item types share one dataset, told apart by the `type` field:

- **`review`** — one per review, fields as in the table above.
- **`summary`** — one per app: `fetchedCount`, `emittedCount`, `filteredOutCount`, `averageRating`, `ratingDistribution` (emitted reviews per star), and `stoppedReason` (`resultsExhausted`, `maxReviewsReached`, `dateRangePassed`, `fetchSafetyCapReached`, `appFailed`). The identity `fetched = emitted + filtered` always holds, so you can see exactly what your filters cost you.
- **`error`** — one per failed app (for example a package name that does not exist), with the reason; if every app fails, the run itself is marked failed rather than returning an empty success.

### Recipes

**Release damage check.** App: your own package. `sortOrder: newest`, `reviewsStartDate:` the release date, `maxRating: 2`. You get exactly the angry reviews since the update, and the summary's distribution shows the damage shape.

**Replied vs ignored.** Run once with `onlyWithDeveloperReply: true`, once without, same window. The difference is your unanswered-review backlog, ready for a support sprint.

**Competitor pulse.** App ids: your top 3 competitors. `sortOrder: mostRelevant`, `maxReviewsPerApp: 200`. The summary's `averageRating` and star distribution per app compare directly.

**Lowest-rated recent complaints.** `sortOrder: lowestRating`, `maxReviewsPerApp: 50` — the worst of the recent stream (see the honest note below on how lowest is built).

### FAQ

**How much does a typical job cost?** Pricing is flat per review with no subscription and no start fee — see the Pricing tab. 10,000 reviews across 5 apps is one run, one per-review charge, nothing monthly.

**Can it get ALL reviews of a huge app?** The stream is paginated to exhaustion — the summary's `stoppedReason: resultsExhausted` tells you the stream ended. Very large caps take proportionally longer (one request per 100 reviews).

**Why is a review I see in the Play app missing?** Google serves the review stream per storefront country and language (`country` / `language` inputs). A review visible in one storefront may not be in another. Match the inputs to the storefront you are looking at.

**Does it need my Google account?** No. Reviews are read from the Play Store's public web endpoint; there is no login and nothing to connect.

### Honest limits

- **`lowestRating` is built, not native.** Google's public endpoint has no lowest-first stream, so the actor fetches the newest stream and sorts it ascending: "lowest" means *lowest among the most recent reviews fetched*, not the app's all-time lowest. The other three sort orders are Google's own streams.
- **Public stream only.** These are the reviews Google shows publicly on the storefront for the chosen country/language — not Play Console data (no private or deleted reviews, no reply threading beyond the one public reply).
- **Rating-only reviews have `text: null`** — that is what the user posted, not a scrape gap; they still count in the summary's distribution.
- Google occasionally reshapes its payloads; the parser reads typed slots defensively and emits `null` rather than guessing when a field is absent.

# Actor input Schema

## `appIds` (type: `array`):

Android apps to scrape reviews from: package names (e.g. com.whatsapp) and/or Google Play Store URLs (the id= parameter is read from the URL). Each app is processed in order.

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

2-letter country code sent to Google Play (gl), e.g. us, fr, de, ma. Google serves the review stream for that storefront country.

## `includeSummary` (type: `boolean`):

Emit one summary item per app: reviews fetched, emitted, filtered out, average rating, the 1-5 star distribution, and why fetching stopped.

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

Language code for the review stream (hl), e.g. en, fr, de, es, ar. Reviews are returned in the original languages users wrote them; this steers the storefront locale.

## `maxRating` (type: `number`):

Only reviews with at most this star rating (1-5).

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

Maximum reviews emitted per app, after filters. Fetching stops once the cap is reached.

## `minRating` (type: `number`):

Only reviews with at least this star rating (1-5).

## `onlyWithDeveloperReply` (type: `boolean`):

Keep only reviews the developer has publicly replied to.

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

The Play Store reviews endpoint is a public web endpoint. Apify Proxy (standard) is the prepared default and is normally enough; switch to RESIDENTIAL only if you see repeated HTTP 403 errors. You pay only your own run's proxy usage; traffic is one small request per 100 reviews.

## `reviewsEndDate` (type: `string`):

Only reviews dated on or before this day (inclusive, UTC).

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

Only reviews dated on or after this day (inclusive, UTC). With the newest sort order, fetching stops as soon as the stream passes this date.

## `sortOrder` (type: `string`):

Review order. newest, mostRelevant and highestRating are Google's native streams. lowestRating is built from the newest stream and re-sorted ascending, because Google's public endpoint has no native lowest-first stream (see the README's honest limits).

## Actor input object example

```json
{
  "appIds": [],
  "country": "us",
  "includeSummary": true,
  "language": "en",
  "maxReviewsPerApp": 100,
  "onlyWithDeveloperReply": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "sortOrder": "newest"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing review items and per-app summary items.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("goldenbios/my-actor-2").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 = { "proxyConfiguration": { "useApifyProxy": True } }

# Run the Actor and wait for it to finish
run = client.actor("goldenbios/my-actor-2").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 '{
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call goldenbios/my-actor-2 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,goldenbios/my-actor-2"
        }
    }
}
```

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/ftnopsTlh3coxCUrV/builds/6UYHDlOoSsaxicQEa/openapi.json
