# Google Play & App Store Reviews | AppReview Radar (`reliable_quatrain/google-play-app-store-review-radar`) Actor

Track new-to-baseline and edited Google Play/App Store reviews. Filter ratings, app versions and visible replies before billing. Export CSV and feedback reports with keyword evidence; skip unchanged reviews using a supplied snapshot.

- **URL**: https://apify.com/reliable_quatrain/google-play-app-store-review-radar.md
- **Developed by:** [Trần Quốc Việt](https://apify.com/reliable_quatrain) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 matching review saveds

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 & App Store Reviews | AppReview Radar

**Turn public app reviews into a feedback shortlist for your next product decision.** Read Android and iOS reviews in one run, filter by stars and words, and export CSV plus a Markdown report with source evidence.

Built for indie app founders, product teams, ASO specialists, and agencies comparing competitor feedback. No store login, LLM key, paid upstream API, or proxy setup is required.

![Illustrative workflow: public reviews, transparent filters, and an exportable feedback shortlist.](https://raw.githubusercontent.com/boyhoanghoi/appreview-radar-apify/main/assets/launch/review-radar-preview.png)

### Try a small run

Choose the **ChatGPT demo preset**, or paste this into JSON input:

```json
{
  "appPreset": "chatgpt",
  "country": "gb",
  "language": "en",
  "maxReviews": 20,
  "maxReviewsPerApp": 10,
  "maxPagesPerApp": 1,
  "maxRating": 3
}
```

Click **Start**, then open the dataset and the **Output tab**. It links `results.csv` and `feedback-report.md`. The run requests up to 20 saved reviews across Android and iOS; it may return fewer or zero because filters apply to a bounded source window. Check **DIAGNOSTICS** for source failures or page limits. The separate `OUTPUT` record is the complete JSON report.

[Step-by-step guide](https://github.com/boyhoanghoi/appreview-radar-apify/blob/main/docs/FIRST_RUN.md) · [Hướng dẫn tiếng Việt](https://github.com/boyhoanghoi/appreview-radar-apify/blob/main/docs/FIRST_RUN_VI.md)

### What you get

- **One schema for two stores:** review ID, store, app ID, requested locale, rating, review text, date/version when supplied, public reply where exposed, source URL, and matched topic evidence.
- **Filters before billing:** rating band, ISO date cutoff, included words, excluded words, topic matches, and an explicit feature-request phrase option.
- **Transparent topic tags:** stability, performance, billing, login, ads, privacy, and feature-request mentions using English/Vietnamese literal rules.
- **Ready-to-use exports:** dataset/CSV, Markdown feedback report, and `TOPICS` with per-topic counts and evidence.
- **Repeat-review deduplication:** pass `KNOWN_REVIEW_IDS` into your next input to skip saved reviews before output and charging.
- **Review edit monitoring:** supply `SNAPSHOT` and `changedOnly` to detect exposed same-ID content changes while skipping unchanged review events.
- **Release/support filters:** match source app versions or visible Google Play developer replies. Apple RSS reply status remains unavailable.

Topic matches are rules, not AI analysis or a verified bug diagnosis. Read the original evidence: a request phrase does not prove intent or demand. The report uses saved reviews only; it is not representative polling or the app's overall rating.

### Useful recipes

**Compare complaints about two apps:** set your Android package IDs or iOS numeric IDs, `maxRating: 2`, and the same country/page settings. Group exported rows by app; compare the original text and available versions rather than treating different sample sizes as market share.

**Inspect login problems:** choose `topicFilters: ["login"]`, optionally add `reviewedAfter`, and download the report. Topic keywords match literal text and can miss paraphrases or match a negated phrase.

**Find feature-request mentions:** set `featureRequestsOnly: true`. Results must contain a supported request phrase; they are candidates for human review, not verified feature requests.

**Skip reviews already exported:** copy the previous `KNOWN_REVIEW_IDS` array into `knownReviewIds`. Your workflow must pass that state explicitly; attaching a schedule does not do it automatically. This mode skips same-key edits too.

### Track review edits with a snapshot

Use `previousSnapshot` plus `changedOnly: true`, and leave `knownReviewIds` empty.
The first run produces `SNAPSHOT`; copy it to the next run's `previousSnapshot`
with the same country/language. The Actor compares exposed title/text, rating,
app version and developer reply. It saves `NEW` to that baseline or `UPDATED`
reviews; matching `UNCHANGED` reviews are skipped before output and billing.

A `NEW` key may be an old review not yet in your supplied snapshot. Source
windows are partial; missing reviews never become deletion claims. Only saved
rows advance the baseline. Snapshots retain at most 10,000 hashes and 2 MiB;
oldest entries can be evicted with `snapshotTruncated: true`. Same-key reviews in
`knownReviewIds` still take priority and are skipped without edit checking.
Default `changedOnly: false` saves/bills matching unchanged rows.

[Snapshot workflow and caveats](https://github.com/boyhoanghoi/appreview-radar-apify/blob/main/docs/CHANGE_MONITOR.md) ·
[Hướng dẫn theo dõi review đã sửa](https://github.com/boyhoanghoi/appreview-radar-apify/blob/main/docs/CHANGE_MONITOR_VI.md)

### Main inputs

| Input | Purpose |
| --- | --- |
| `appPreset` | `none` or Android + iOS `chatgpt` demo |
| `googlePlayApps`, `appStoreApps` | App IDs or standard store URLs; combined maximum 10 apps |
| `country`, `language` | Requested store country and Google Play language hint; not reviewer residence/language verification |
| `maxReviews` | Global saved cap; default 100, maximum 2,000 |
| `maxReviewsPerApp` | Saved cap per app; default 100, maximum 1,000 |
| `maxPagesPerApp` | Source-page cap per app; default 3, maximum 10 |
| `minRating`, `maxRating` | Inclusive 1–5-star range |
| `includeKeywords`, `excludeKeywords` | Case-insensitive substring lists; any excluded match removes the review |
| `topicFilters` | Any selected topic must match, in addition to other filters |
| `featureRequestsOnly` | Require an explicit supported request phrase |
| `reviewedAfter` | ISO cutoff; unknown review dates are excluded |
| `knownReviewIds` | Saved keys to skip, up to 10,000 |
| `previousSnapshot`, `changedOnly` | Caller-supplied review fingerprints and optional suppression of unchanged rows |
| `appVersionKeywords` | Source-version substring filter; missing versions excluded when set |
| `replyFilter` | `all`, `with-reply`, or `without-visible-reply`; reply-specific filters exclude Apple RSS |

Preset apps and supplied apps are combined and deduplicated. App names are not searched automatically; use an ID or a store listing URL.

### Pricing

Launch rate: **$0.50 per 1,000 saved matching reviews**, one `review-saved` event per saved row. Confirm the live rate in **Pricing**. No Actor start fee and no extra review events for report/topic evidence.

At that rate, 20 saved reviews generate **$0.01** in review events. Source failures, filtered reviews, duplicates, and supplied known IDs do not generate review events. Platform usage follows Apify's applicable plan and pricing model. Set a **maximum total charge** for the run.

### Important limits

- Public web/feed data only. This is not the official authenticated Google Play Developer or App Store Connect API.
- Source windows are incomplete. The reader scans at most 10 pages per app, and available pages may contain fewer reviews or be empty. Google Play is bounded by your page cap and what the source returns. No full-history guarantee.
- Apple RSS does not expose developer replies. Missing source values stay `null`; labels are not verified app metadata.
- The requested country is not verified reviewer residence. Language is a Google Play hint, not a guaranteed review-language filter.
- Failures are explained in `DIAGNOSTICS`; they are not silently treated as an app having no reviews.
- Known-key history rolls at 10,000 saved keys and must be passed explicitly. Same-key edited reviews are skipped.
- Snapshot edit tracking is separate from known-key skipping and also needs explicit state handoff. Only exposed bounded fields are compared; changes outside fetched windows or beyond the text limit cannot be recovered.
- No login, private data access, CAPTCHA bypass, proxy rotation, or automated review posting.

[Source policy and field caveats](https://github.com/boyhoanghoi/appreview-radar-apify/blob/main/docs/SOURCES.md) · [Open-source repository](https://github.com/boyhoanghoi/appreview-radar-apify)

This independent tool is not affiliated with OpenAI, Google, or Apple. The ChatGPT preset is a public-app example, not an endorsement.

# Actor input Schema

## `appPreset` (type: `string`):

ChatGPT selects its Android and iOS app IDs as a demo, not a customer or endorsement. Custom app IDs are added before the preset. Choose Custom only to use your own apps.

## `googlePlayApps` (type: `array`):

Android package IDs such as com.openai.chatgpt or HTTPS play.google.com/store/apps/details?id=... URLs. Up to 10 apps across both stores and the selected demo.

## `appStoreApps` (type: `array`):

Numeric Apple IDs such as 6448311069 or HTTPS apps.apple.com/.../id... URLs. Reads a limited public feed; no promise of full review history.

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

Two-letter store code, e.g. us, gb or vn. This is request context, not the reviewer's country of residence. Results may vary by storefront.

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

Language code such as en or vi. Google Play request hint only; no guaranteed language filtering. Does not change Apple's public storefront feed.

## `maxReviews` (type: `integer`):

Global cap after filters and known-ID skips; also bounded by the run spending limit. Source data can yield fewer or zero matching reviews.

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

Per app/store cap after filtering. Apps are processed in input order; a low global cap can skip later apps.

## `maxPagesPerApp` (type: `integer`):

Bounds scans even if filters reject most reviews. Public feeds are partial; max 10 pages is not a guarantee of 500/1000 reviews or complete history.

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

Inclusive 1-5 star filter applied before saving and charging.

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

Inclusive 1-5 star filter. Choose 3 for a low-rating shortlist; a rating does not prove a particular problem or sentiment.

## `appVersionKeywords` (type: `array`):

Optional case-insensitive substring OR matching against the version exposed by each review. Unknown versions are excluded when set; no release date is inferred. Up to 30 values.

## `replyFilter` (type: `string`):

Google Play can expose replies. Apple RSS reply status is unavailable, so Apple reviews are excluded by either reply-specific filter. Not shown means no reply in this public feed, not proof of no reply elsewhere.

## `includeKeywords` (type: `array`):

Case-insensitive substring OR matching across review title and text. Empty means unrestricted. Up to 30 terms; combined with other filters using AND.

## `excludeKeywords` (type: `array`):

Case-insensitive substring OR exclusions. Up to 30 terms. Applied before saving/charging.

## `topicFilters` (type: `array`):

Allowed labels: stability, performance, billing, login, ads, privacy, feature-request. Matches literal English/Vietnamese terms, not AI intent. Praise and negations can match. Empty means any topic; see each row's evidence.

## `featureRequestsOnly` (type: `boolean`):

Requires a configured phrase such as 'please add', 'I wish' or 'vui lòng thêm'. This is a keyword heuristic, not proof of demand or intended meaning. English/Vietnamese phrases only.

## `reviewedAfter` (type: `string`):

Inclusive ISO date/timestamp. Reviews with unknown dates are excluded when set. Dates may reflect edits; this is not guaranteed original publication.

## `knownReviewIds` (type: `array`):

Paste the KNOWN_REVIEW_IDS array from a previous run to skip those keys before saving/billing. Same-ID edited reviews are also skipped. Up to 10,000 keys; callers must transfer the returned state explicitly.

## `previousSnapshot` (type: `object`):

Paste SNAPSHOT from a prior run to identify NEW/UPDATED/UNCHANGED reviews. Must match country/language. Bounded to 10,000 review hashes and 2 MiB UTF-8; oldest saved entries are evicted with snapshotTruncated=true if needed. Only saved rows advance state; absent reviews are never marked deleted. Keep knownReviewIds empty to allow same-ID edits to be checked.

## `changedOnly` (type: `boolean`):

With previousSnapshot, skip unchanged reviews before saving and review-saved billing. NEW means absent from this supplied baseline, not newly posted. Text/rating/version/reply changes within exposed fields are detected; votes, dates and observation time alone are not edits. Schedules must explicitly pass SNAPSHOT to the next run.

## `timeoutSeconds` (type: `integer`):

Verified HTTPS requests with no redirect following. At most one retry for transient network/5xx errors; access denials and rate limits stop that source.

## `minDelaySeconds` (type: `number`):

Sequential paced requests, bounded by 60 HTTP attempts and a 180-second source-processing deadline per run. No proxies or login bypass.

## Actor input object example

```json
{
  "appPreset": "chatgpt",
  "googlePlayApps": [],
  "appStoreApps": [],
  "country": "gb",
  "language": "en",
  "maxReviews": 20,
  "maxReviewsPerApp": 10,
  "maxPagesPerApp": 1,
  "minRating": 1,
  "maxRating": 3,
  "appVersionKeywords": [],
  "replyFilter": "all",
  "includeKeywords": [],
  "excludeKeywords": [],
  "topicFilters": [],
  "featureRequestsOnly": false,
  "reviewedAfter": "",
  "knownReviewIds": [],
  "previousSnapshot": {},
  "changedOnly": false,
  "timeoutSeconds": 20,
  "minDelaySeconds": 0.5
}
```

# Actor output Schema

## `reviews` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `feedbackReport` (type: `string`):

No description

## `topics` (type: `string`):

No description

## `knownReviewIds` (type: `string`):

No description

## `snapshot` (type: `string`):

No description

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

No description

## `diagnostics` (type: `string`):

No description

## `report` (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 = {
    "appPreset": "chatgpt",
    "country": "gb",
    "maxReviews": 20,
    "maxReviewsPerApp": 10,
    "maxPagesPerApp": 1,
    "maxRating": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("reliable_quatrain/google-play-app-store-review-radar").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 = {
    "appPreset": "chatgpt",
    "country": "gb",
    "maxReviews": 20,
    "maxReviewsPerApp": 10,
    "maxPagesPerApp": 1,
    "maxRating": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("reliable_quatrain/google-play-app-store-review-radar").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 '{
  "appPreset": "chatgpt",
  "country": "gb",
  "maxReviews": 20,
  "maxReviewsPerApp": 10,
  "maxPagesPerApp": 1,
  "maxRating": 3
}' |
apify call reliable_quatrain/google-play-app-store-review-radar --silent --output-dataset

```

## MCP server setup

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

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/NsFUW9rONTkafXY5T/builds/EPkad7qI6DSNhl4jF/openapi.json
