# Google Play Review Monitor — Alerts for New App Reviews (`herus13/google-play-review-monitor`) Actor

Watch Google Play apps and get only the reviews that are NEW since the last check. Run it on a schedule for review alerting, support triage, and rating-drop detection — no re-reading the same reviews, no duplicate rows.

- **URL**: https://apify.com/herus13/google-play-review-monitor.md
- **Developed by:** [bootforge](https://apify.com/herus13) (community)
- **Categories:** Automation, Developer tools, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 per new 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/platform/actors/running/actors-in-store#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 Review Monitor — Get Alerts for New App Reviews

**Google Play Review Monitor is an Apify actor that watches Android apps on the Google Play Store and returns only the reviews that are new since the last check.** Point it at your app IDs, run it on a schedule, and every run gives you the fresh reviews and nothing else — no duplicate rows, no re-reading history, no diffing on your side. Export to JSON, CSV, or Excel, or push straight to Slack via webhook.

Built for **agencies, app developers, and ASO/support teams** who need to know about a 1-star review today, not at the end of the month. It bills per app checked, so watching 20 apps across 3 countries is one schedule, not sixty jobs.

> ### ⚠️ Run this on a Schedule — it is not a one-shot scraper
>
> A single manual run **returns nothing on purpose**: the first run records the reviews that already exist so it can tell what is new later. That run is **free** (no app-check fee).
> **[Create a Schedule](https://console.apify.com/schedules)** right after — "new since last time" needs a last time.

### Contents

- [What it does](#what-it-does)
- [Use cases](#use-cases)
- [How to monitor Google Play reviews](#how-to-monitor-google-play-reviews)
- [Setting up the schedule (60 seconds)](#setting-up-the-schedule-60-seconds)
- [Input](#input)
- [Output](#output)
- [Coverage: how it knows a review is new](#coverage-how-it-knows-a-review-is-new)
- [Pricing](#pricing)
- [Recommended proxies](#recommended-proxies)
- [Why this monitor](#why-this-monitor)
- [FAQ](#faq)
- [Rate this actor](#rate-this-actor-)
- [Related actors](#related-actors)

### What it does

- 🔔 **Only new reviews** — remembers what it already reported, per app and per country
- 🌍 **Multi-app, multi-country** — watch 20 apps across 3 storefronts from one schedule
- ⭐ **Negative-only alerts** — set `alert_max_rating: 3` to hear only about 1–3 star reviews
- 💬 **Unanswered-review triage** — surface reviews with no developer reply
- 🧾 **Flat, CSV-friendly rows** — one row per review, no nested JSON
- 🚨 **Warns when it misses something** — see [Coverage](#coverage-how-it-knows-a-review-is-new)
- ⚡ **No proxy needed** — HTTP-only, so a check costs fractions of a cent

### Use cases

**Same-day response to bad reviews** — Every run returns only reviews that are new since the last check, so a schedule plus `alert_max_rating` gives you a feed of 1- and 2-star reviews as they land. The point is reacting to a bad review today rather than discovering it in a monthly export.

**Support triage without duplicate work** — Because deduplication happens actor-side against the watch state, the same review is never delivered twice. A support queue fed from this doesn't need its own diffing logic or a "have we seen this?" table.

**Unanswered-review sweeps** — `alert_only_unanswered` narrows the feed to reviews with no developer reply, which is the queue that actually needs a human. Useful for agencies holding a response-time SLA.

**Multi-app, multi-country watching on one schedule** — Billing is per app checked, so watching 20 apps across 3 countries is a single scheduled run rather than sixty separate jobs — the difference between a practical agency workflow and an unaffordable one.

### How to monitor Google Play reviews

1. Add your app IDs — `com.spotify.music`, or paste the full Play Store URL.
2. Leave **Watch name** as `default` (or name it, to run several independent watches).
3. Run it once. **This first run returns nothing and is not charged an app-check fee** — it is recording what already exists.
4. **[Create a Schedule](https://console.apify.com/schedules)** — see below.
5. Every run after that returns only new reviews. The run status tells you which case you got.

```json
{
  "app_ids": ["com.spotify.music"],
  "watch_id": "default",
  "country": "us"
}
```

Negative reviews only, two apps, deeper scan:

```json
{
  "app_ids": ["com.spotify.music", "com.netflix.mediaclient"],
  "alert_max_rating": 3,
  "max_reviews_per_app": 500,
  "country": "us"
}
```

### Setting up the schedule (60 seconds)

1. Open **[console.apify.com/schedules](https://console.apify.com/schedules)** → **Create new**
2. Set the cron expression — `0 * * * *` for hourly, `0 9 * * *` for daily at 09:00 UTC
3. Under **Actors and tasks**, add **google-play-review-monitor** and paste the same input you just ran
4. Save

Shortcut: from a finished run, use **Actions → Schedule** to carry the input across automatically.

**Which frequency?** Match it to how fast your app collects reviews — see [Coverage](#coverage-how-it-knows-a-review-is-new). A quiet app is fine daily. A busy one wants hourly, or a higher `max_reviews_per_app`.

**Getting alerts:** attach a webhook on `ACTOR.RUN.SUCCEEDED` to post the dataset to Slack, email, or your own endpoint. Runs that find nothing produce an empty dataset, so you are only pinged when something happened.

Prefer building it as a workflow? The same actor ships as an n8n node — `Schedule Trigger → Bootforge → Slack`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `app_ids` | array | — | **Required.** Package IDs or Play Store URLs to watch |
| `watch_id` | string | `default` | Names the saved state. Keep it stable across scheduled runs |
| `seed_silently` | boolean | `true` | First run records the backlog without reporting it |
| `alert_max_rating` | integer | — | Only report reviews at or below this rating (`3` = negative only) |
| `alert_only_unanswered` | boolean | `false` | Only report reviews with no developer reply |
| `rating_filter` | array | — | Restrict to specific star ratings, e.g. `[1, 2]` |
| `max_reviews_per_app` | integer | `200` | How deep to scan per check — see [Coverage](#coverage-how-it-knows-a-review-is-new) |
| `country` | string | `us` | Storefront code — each country is tracked separately |
| `language` | string | `en` | Language code for review text |

### Output

One row per new review.

```json
{
  "platform": "google_play",
  "review_id": "2797dc0c-7faa-4a12-9d3e-5f81b0c47e29",
  "app_id": "com.spotify.music",
  "author_name": "Jane D.",
  "rating": 2,
  "text": "Crashes every time I open a playlist since the update.",
  "thumbs_up_count": 14,
  "review_date": "2026-07-27T08:49:13+00:00",
  "app_version": "8.9.60.408",
  "dev_reply_text": null,
  "dev_reply_date": null,
  "scraped_at": "2026-07-28T08:49:46+00:00"
}
```

| Field | Type | Description |
|---|---|---|
| `platform` | string | Always `google_play` |
| `review_id` | string | Stable unique review identifier |
| `app_id` | string | Play Store package ID |
| `author_name` | string | Reviewer display name |
| `author_avatar_url` | string | Reviewer avatar image, when present |
| `rating` | integer | 1–5 stars |
| `text` | string | Review body, may be null |
| `thumbs_up_count` | integer | "Helpful" votes |
| `review_date` | string | ISO 8601 timestamp of the review |
| `app_version` | string | App version reviewed, when reported |
| `dev_reply_text` | string | Developer's reply, null if unanswered |
| `dev_reply_date` | string | ISO 8601 timestamp of the reply |
| `scraped_at` | string | ISO 8601 timestamp of this check |

**An empty dataset is a normal result.** It means no new reviews since the last check.

### Coverage: how it knows a review is new

The monitor remembers every review ID it has reported, per app and per country, and delivers only IDs it has never sent. IDs are stable, so **a review is never sent twice**.

**Where it has a limit — stated plainly:** each check scans the newest `max_reviews_per_app` reviews. If more than that arrive between two checks, the overflow falls below the scan window and is not reported — and will not be reported later either, because the next check starts from the top again.

**The monitor detects this and tells you.** When a run's coverage does not connect to the previous run's, it emits a `COVERAGE GAP` warning in the log and in the run status, naming the time span it missed. Fix it by raising `max_reviews_per_app` or scheduling more often.

Rule of thumb: `max_reviews_per_app` should comfortably exceed the reviews your app receives between checks. The default of 200 with a daily schedule covers any app receiving under ~200 reviews/day.

**Two things it does not do.** It will not report an *edited* review — Google Play keeps the same ID when a user rewrites their rating or text — and it does not report deletions. This monitors new reviews, not changes to old ones.

### Pricing

You pay **per app watched, per check** — about **$1.50 per app per month** on a daily schedule (30 checks plus run fees). Halve it by checking every other day; raise coverage by checking hourly.

| Event | Price | When |
|---|---|---|
| Actor start | $0.001 | Per run |
| App check | $0.05 | Per app watched, per check — whether or not anything was new. **Not charged on the free first run.** |
| New review | $0.002 | Per new review reported |

New reviews add $0.002 each, kept deliberately small: even a busy app at 150 new reviews a month adds about $0.30. Your bill tracks **how much you watch**, not how noisy your apps happen to be — so you can forecast it.

Dedicated app-review monitoring SaaS starts around $39–100/month for a handful of apps. This is the same job at roughly $1.50 per app.

> Confirm live pricing on the actor's Apify Store page — that is always authoritative.

### Recommended proxies

**No proxy is required.** Google Play serves this actor's endpoint without one, verified on live runs, which is why a check costs fractions of a cent. **Proxy provider** is there if you want one; leaving it untouched runs direct, which is the right default here.

For your own scrapers that *do* need residential proxies, we use [DataImpulse](https://dataimpulse.com/?aff=404588\&utm_source=apify) (referral link).

### Why this monitor

- **Purpose-built for the delta.** A reviews scraper returns the same rows every run and leaves deduplication to you. This returns only what changed.
- **Honest about coverage.** It warns when it misses reviews instead of quietly under-reporting.
- **Per-country state.** The same app is a different review stream per storefront, tracked separately, so watches never contaminate each other.
- **Cheap to run.** HTTP-only, no browser, no proxy.
- **Free first run.** Setup costs nothing.

### FAQ

**Why did my first run return nothing?**
By design. The first run records the reviews that already exist so later runs can tell what is new. It is not charged an app-check fee. Set `seed_silently` to `false` if you want the existing backlog delivered once — that run bills normally.

**Why does an empty run still cost money?**
Because the checking is what you are buying. A quiet result is the monitor doing its job and confirming nothing needs your attention — that is worth the same as a noisy one. Pricing is per app watched (~$1.50/app/month daily), so your bill is predictable and does not depend on how many reviews happen to land.

**Do I need a proxy?**
No. Google Play serves this actor's endpoint from a plain datacenter IP, verified on live runs. **Proxy provider** is there for unusual cases, but leaving it untouched runs without a proxy and keeps checks cheap.

**Is scraping Google Play reviews legal?**
This actor reads only publicly visible review pages — no login, no paywall, and no personal data beyond the display name a reviewer chose to publish. Public-data scraping is broadly lawful in the US and EU, but you are responsible for your own use, especially when republishing review text or handling personal data under GDPR.

**Does it support the Apple App Store?**
No, and not by oversight. Apple's public web surface exposes a fixed 8 reviews per country ordered by *helpfulness*, not recency — that window routinely holds reviews years old and does not reliably contain new ones. There is no way to diff it, so an Apple mode would silently never alert.

**Will it miss reviews if my app is busy?**
Only if more than `max_reviews_per_app` arrive between checks — and it warns you when that happens, naming the span it missed. Raise the value or schedule more often.

**Can I change the sort order?**
No. The diff walks from the newest review and stops when it reaches ones already reported, which is only correct on a recency-ordered stream. Sort is locked so a watch cannot be silently broken.

**How do I reset a watch?**
Change `watch_id` to a new name. That starts a fresh watch with its own state and seeds again on the next run.

**Can I watch the same app in several countries?**
Yes. Each country is a separate review stream with separate state, so they never interfere.

### Rate this actor ⭐

If this saved you time, please leave a review on the actor's Apify Store page — it is the single biggest help for a small publisher, and issues raised in reviews get fixed fast.

### Related actors

- [google-play-reviews-scraper](https://apify.com/herus13/google-play-reviews-scraper) — full historical review export and app search
- [apple-app-store-scraper](https://apify.com/herus13/apple-app-store-scraper) — App Store app search and featured reviews
- [google-maps-reviews-scraper](https://apify.com/herus13/google-maps-reviews-scraper) — business reviews from Google Maps

# Actor input Schema

## `app_ids` (type: `array`):

Google Play package IDs or full Play Store URLs — e.g. <code>com.spotify.music</code> or <code>https://play.google.com/store/apps/details?id=com.spotify.music</code>. These are the apps this watch checks on every run.

## `watch_id` (type: `string`):

Names this watch's saved state. Keep it the SAME across scheduled runs — that is how the actor knows which reviews it has already reported. Change it (or use a second name) to run an independent watch over the same apps.

## `seed_silently` (type: `boolean`):

On the very first run this watch records the reviews that already exist WITHOUT reporting them, so you only get genuinely new ones from run two onward. Turn this off to receive the current backlog once.

## `alert_max_rating` (type: `integer`):

Set to <code>3</code> to be alerted only about negative reviews. Leave empty to report every new review.

## `alert_only_unanswered` (type: `boolean`):

Useful for support triage — surfaces reviews still waiting on a response.

## `rating_filter` (type: `array`):

Restrict to specific star ratings, e.g. <code>\[1, 2]</code>. Leave empty for all.

## `max_reviews_per_app` (type: `integer`):

How deep to walk on each check. The walk stops early as soon as it reaches reviews it has already seen, so this is only a ceiling for apps that received a burst of reviews between checks.

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

Two-letter storefront code. Each country is a separate review stream and is tracked separately.

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

Two-letter language code for review text.

## `transport` (type: `string`):

Leave on <code>auto</code> unless debugging.

## `proxyProvider` (type: `string`):

<b>Default</b> routes the run through DataImpulse residential IPs (falling back to Apify Proxy) and is <b>included in the price of the run</b>. <b>Custom</b> uses the proxy URLs you enter below; <b>Apify Proxy</b> uses the proxy configuration below; <b>No proxy</b> connects directly. Leave this empty to keep the behaviour this actor already had — nothing is imposed on a run that does not choose.

## `proxyUrls` (type: `array`):

Only read when <b>Proxy provider</b> is <b>Custom</b>. One gateway URL per entry, e.g. <code>http://user:pass@host:port</code> — works with any provider that issues URLs (BrightData, Oxylabs, SmartProxy, your own). Leave empty for any other Proxy provider.

## `proxy` (type: `object`):

Optional. Google Play does not require a proxy for normal volumes.

## Actor input object example

```json
{
  "app_ids": [
    "com.spotify.music"
  ],
  "watch_id": "default",
  "seed_silently": true,
  "alert_only_unanswered": false,
  "max_reviews_per_app": 200,
  "country": "us",
  "language": "en",
  "transport": "auto"
}
```

# Actor output Schema

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

Only reviews not present on a previous run of this watch — review id, app id, author, rating, text, thumbs up, date, app version, developer reply, scraped\_at. An empty dataset means nothing new, which is the normal healthy outcome; the first run of a watch is also empty by design.

# 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 = {
    "app_ids": [
        "com.spotify.music"
    ],
    "watch_id": "default",
    "max_reviews_per_app": 200,
    "country": "us",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("herus13/google-play-review-monitor").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 = {
    "app_ids": ["com.spotify.music"],
    "watch_id": "default",
    "max_reviews_per_app": 200,
    "country": "us",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("herus13/google-play-review-monitor").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 '{
  "app_ids": [
    "com.spotify.music"
  ],
  "watch_id": "default",
  "max_reviews_per_app": 200,
  "country": "us",
  "language": "en"
}' |
apify call herus13/google-play-review-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,herus13/google-play-review-monitor"
        }
    }
}

```

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/Kv3WQin16mLEbmEVJ/builds/3a4DzKPIvqcxIf5Jw/openapi.json
