# Google Play Reviews Scraper (app details, replies, no names) (`datahamster/google-play-app-reviews`) Actor

Google Play reviews scraper: app store reviews and the app card in one run. Per review you get stars, text, date, helpful votes, app version and the developer's reply, plus app name, developer, rating and category. No reviewer names. Monitor mode alerts on new reviews; empty runs cost nothing.

- **URL**: https://apify.com/datahamster/google-play-app-reviews.md
- **Developed by:** [Viktor Dubnytskiy](https://apify.com/datahamster) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 result items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Play Reviews Scraper (app details, replies, no names)

Give the actor an app id (`com.spotify.music`) or a Play Store URL and get its reviews as flat rows — star rating, review text, date, helpful votes, the app version the review was written on, and the developer's public reply. Every row also carries the app card (name, developer, store rating, rating count, price, category), so app details and app store reviews come out of a single run. No login, no cookies, no reviewer names.

### What you get

One row per review: `id`/`reviewId`, `url`, `appId`, `appName`, `developer`, `appRating`, `appRatingCount`, `appPrice`, `appCurrency`, `appCategory`, `rating`, `text`, `reviewedAt`, `helpfulCount`, `appVersion`, `developerReply`, `developerRepliedAt`, `reviewerCountry`, `query`, `rank`, `source`, `scrapedAt`.

`url` points at the single review (`...details?id=<app>&hl=en&gl=us&reviewId=<id>`), so every row is checkable by hand.

### Example output

A real row (app `com.spotify.music`, `sort: newest`):

| Field | Example value |
|---|---|
| `appId` / `appName` | `com.spotify.music` / `Spotify: Music and Podcasts` |
| `developer` / `appCategory` | `Spotify AB` / `MUSIC_AND_AUDIO` |
| `appRating` / `appRatingCount` | `4.346` / `36289009` |
| `appPrice` / `appCurrency` | `0.0` / `USD` |
| `reviewId` | `7a04c086-85ba-49c8-8b03-4cc4423b9020` |
| `rating` / `text` | `3` / `can't listen offline` |
| `reviewedAt` / `appVersion` | `2026-09-11T19:38:27Z` / `9.1.80.2221` |
| `helpfulCount` | `0` |
| `developerReply` | `Hi! We welcome your feedback. If you're on our free service, you can only enjoy music while connected to the internet...` |
| `developerRepliedAt` | `2026-09-11T19:52:42Z` |

### Use cases

- Read what users complain about in your own app or a competitor's, filtered to 1-2 stars with `minRating` left open and `sort: newest`.
- Track how a release lands: `appVersion` on every review separates feedback on the new build from the old one.
- Audit support quality — `developerReply` and `developerRepliedAt` show which reviews the developer answered and how fast.
- Watch a set of apps in monitor mode and get an alert when new reviews or a changed developer reply appear.

### How it works

1. The app's store page is fetched once per app id and the app card is read from its `SoftwareApplication` JSON-LD (name, developer, rating, rating count, price, category). An unknown app id answers 404 and is skipped, not counted as a block.
2. Reviews come from the same paged endpoint the Play web app itself calls, page by page with its own continuation token, until `maxReviewsPerApp` is reached.
3. An answer that is not a valid review page (a challenge, or a format change) is reported as a block instead of being pushed as an empty result.

### Input

| Field | Meaning | Default |
|---|---|---|
| `appIds` | App ids or Play Store URLs, e.g. `com.spotify.music` | `["com.spotify.music"]` |
| `sort` | `newest`, `relevant` or `rating` | `newest` |
| `maxReviewsPerApp` | Reviews read per app | `100` |
| `minRating` | Keep only reviews with at least this many stars (1-5) | empty |
| `language` / `country` | Play `hl` / `gl`, e.g. `en` / `us` | `en` / `us` |
| `maxItems` | Stop after this many rows in total | `100` |
| `mode` | `scrape` or `monitor` (only new/changed since last run) | `scrape` |
| `monitorKey`, `webhookUrl`, `telegramBotToken`, `telegramChatId` | Monitor-mode state key and alert targets | empty |

### Pricing

| Event | Price |
|---|---|
| result | $0.0005 per review ($0.50 per 1,000) |
| monitor-check | $0.005 per monitor run |
| change | $0.0005 per new or changed review |

You are charged only for rows actually pushed. A run that finds nothing charges no result events.

### Why this actor

- App details and reviews in one run and one row — no second actor, no join on app id.
- The developer's reply and its timestamp are first-class fields, not buried in the review text.
- Monitor mode with webhook and Telegram alerts on new reviews, edited texts and new developer replies.
- No reviewer names, profile ids or avatars are collected, so the output is safe to keep and share.
- An empty run costs nothing and the `RUN_SUMMARY` record says why it was empty.

### Limits

- Reviews are what Google Play serves publicly for the chosen `language`/`country`; other locales return other review sets. Play itself stops paging a few thousand reviews deep.
- `reviewerCountry` is always `null` — Play does not expose the reviewer's country. The column is kept so a dataset schema stays stable.
- No reviewer names, profile ids or avatar URLs, by design. If you need them, this actor is not for you.
- `appRating` is the current store rating of the app, not a per-review average, and it is the same on every row of that app.
- `minRating` filters inside the reviews read: with it set, the actor reads up to five times `maxReviewsPerApp` reviews while trying to fill the quota.
- Many Play reviews are stars only, with no words: `text` is then empty while `rating`, `reviewedAt` and `appVersion` are filled. Filter on `text` if you need written feedback only.
- The actor runs without a proxy (Apify's own egress), which is what Google Play currently answers. Under heavy parallel use Google may start rate-limiting that egress; switching the run to a datacenter proxy is then enough.

### FAQ

**Does it need a Google account or cookies?** No. Everything is read as an anonymous visitor.

**Can I get reviews in another language?** Yes — set `language` and `country` (e.g. `de` / `de`). Play returns the review set for that storefront.

**Why are there no reviewer names?** Deliberate: the actor does not collect person-level data. Ratings, texts, dates and replies are returned; identities are not.

**What happens when the app id does not exist?** Play answers 404, the app is skipped and the run ends as `no_matches` with no charge, not as a block.

### Changelog

- 0.1: initial release — app card plus reviews in one row, developer replies, sort and rating filter, monitor mode.

***

If this actor saved you time, a short review on its Store page genuinely helps other people find it. Found a bug or need a field that is missing? Open a ticket on the **Issues** tab.

# Actor input Schema

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

Stop after this many results (you are charged only for pushed items)

## `mode` (type: `string`):

scrape = full results; monitor = only new/changed items since the previous run of this task

## `monitorKey` (type: `string`):

Optional state key when not running as a saved task

## `webhookUrl` (type: `string`):

POST a change summary here in monitor mode

## `telegramBotToken` (type: `string`):

Optional: bot token for monitor-mode change summaries

## `telegramChatId` (type: `string`):

Optional: chat id that receives monitor-mode summaries

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

Android app ids, one per line, e.g. "com.spotify.music", "com.whatsapp". A full Play Store URL works too, e.g. "https://play.google.com/store/apps/details?id=com.spotify.music".

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

Order in which Play returns the reviews. "newest" for monitoring and release feedback, "relevant" for the reviews Play itself highlights, "rating" to walk the scale. Example: newest.

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

How many reviews to read for each app, e.g. 100. Reviews are read in pages of 40. Range 1-5000; the total is still capped by Max items.

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

Keep only reviews with at least this many stars, e.g. 4. Leave empty for all reviews. With a filter set, the actor reads up to five times "Reviews per app" while trying to fill the quota.

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

Play interface and review language, e.g. "en", "de", "es". Play returns the review set of that storefront language.

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

Two-letter Play storefront country, e.g. "us", "de", "br". Affects price and which reviews are shown.

## Actor input object example

```json
{
  "maxItems": 100,
  "mode": "scrape",
  "appIds": [
    "com.spotify.music"
  ],
  "sort": "newest",
  "maxReviewsPerApp": 100,
  "language": "en",
  "country": "us"
}
```

# Actor output Schema

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

All pushed rows (dataset, JSON)

## `resultsTable` (type: `string`):

Dataset in the Console viewer

## `runSummary` (type: `string`):

RUN\_SUMMARY record

# 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 = {
    "appIds": [
        "com.spotify.music"
    ],
    "sort": "newest",
    "maxReviewsPerApp": 100,
    "language": "en",
    "country": "us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("datahamster/google-play-app-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 = {
    "appIds": ["com.spotify.music"],
    "sort": "newest",
    "maxReviewsPerApp": 100,
    "language": "en",
    "country": "us",
}

# Run the Actor and wait for it to finish
run = client.actor("datahamster/google-play-app-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 '{
  "appIds": [
    "com.spotify.music"
  ],
  "sort": "newest",
  "maxReviewsPerApp": 100,
  "language": "en",
  "country": "us"
}' |
apify call datahamster/google-play-app-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datahamster/google-play-app-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/1WcauJ0n7hXWhLbru/builds/aWXmNmy7ShqE6qu0m/openapi.json
