# App Store, Google Play & Chrome Web Store Reviews Scraper (`tiandu-tech/apify-002-app-reviews`) Actor

Scrape public reviews from Google Play, the Chrome Web Store and the Apple App Store in one run. Paste app or extension URLs or IDs; the store is auto-detected. Get ratings, text, versions, dates and developer replies, deduplicated, most emails and phones masked. App Store feed currently limited.

- **URL**: https://apify.com/tiandu-tech/apify-002-app-reviews.md
- **Developed by:** [天度科技](https://apify.com/tiandu-tech) (community)
- **Categories:** Developer tools, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## App Store, Google Play & Chrome Web Store Reviews Scraper

Collects public reviews from the Apple App Store, Google Play and the Chrome Web Store in one run. Paste app or extension URLs or IDs; the store is detected from each one. The output is one deduplicated dataset with the same fields for every store. Export it as JSON, CSV or Excel, or read it through the Apify API.

- No login, no accounts, no cookies. Public data only.
- One input list for mobile apps **and** browser extensions.
- Same output fields across all three stores.
- Most emails and phone numbers inside review text are masked (best effort).
- Currently no Actor fee: you only pay for Apify platform usage.

> **Known limit:** since October 2026 Apple's public review feed sometimes returns no reviews. When that happens the run tells you clearly instead of silently returning 0 rows. Google Play and the Chrome Web Store are not affected. See [Limits](#limits).

This is an independent tool. It is not an official Apple or Google tool and is not affiliated with or endorsed by Apple Inc. or Google LLC. App Store, Google Play and Chrome Web Store are named only to describe which public sources are supported; no Apple or Google logos are used.

### What can you use it for?

- **Product feedback:** pull recent reviews of your app or extension into one table and look for bugs, crashes and feature requests.
- **Competitor research:** compare what users praise and complain about in competing apps or extensions, across stores and countries.
- **Extension developers:** Chrome Web Store reviews are hard to export by hand. This gives you reviews with rating, extension version and "helpful" count.
- **Release monitoring:** group ratings by `appVersion` to see what changed after an update.
- **Support QA:** check which reviews already have a developer reply (`developerReply`).
- **Analysis and AI pipelines:** feed the dataset into Python, a spreadsheet or an LLM for sentiment and topic analysis.

### Why three stores in one Actor?

Some products ship in more than one store: an iOS app, an Android app, sometimes a Chrome extension. With separate scrapers you get separate inputs, different field names and three exports to merge. This Actor takes one `apps` list with any mix of the three stores and writes one dataset with one schema. The `store` field (`apple`, `google`, `chrome`) tells you where each review came from.

### How to use it

1. Open the Actor in Apify Console.
2. In **Apps or Chrome extensions**, paste one item per line. You can mix stores:
   - Apple: a numeric app ID like `310633997` or an `apps.apple.com` URL
   - Google Play: a package name like `com.whatsapp` or a `play.google.com` URL
   - Chrome Web Store: a 32-letter extension ID like `ddkjiahejlhfcafbddmgiahcphecmpfh` or a `chromewebstore.google.com` URL
3. Set countries, language and how many reviews you want per app.
4. Run it, then open the **Reviews** tab or export the dataset.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `apps` (required) | array of strings | WhatsApp (Google Play) + uBlock Origin Lite (Chrome) | App IDs, package names, extension IDs or store URLs. Store is auto-detected. |
| `countries` | array of strings | `["us"]` | Two-letter country codes such as `us`, `gb`, `de`. Used by Apple and Google Play. Ignored for Chrome extensions. |
| `language` | string | `en` | Review language for Google Play and the Chrome Web Store. For Chrome, only reviews in this language are returned. Apple's language follows the country. |
| `maxReviewsPerApp` | integer | `100` | Maximum reviews per app per country (per extension for Chrome). Apple allows at most 500 per app per country. The form is prefilled with 5 to keep the first run small. |
| `includeReviewerName` | boolean | `false` | Adds a masked reviewer nickname: first character + `***` (e.g. `A***`). Full names are never stored. |
| `sentiment` | boolean | `false` | Adds a simple rule-based `positive` / `neutral` / `negative` label (English keywords + star rating; mostly rating-based for other languages). Not an ML model. |

#### Example inputs

**Google Play only, two countries**

```json
{
  "apps": ["com.whatsapp"],
  "countries": ["us", "gb"],
  "language": "en",
  "maxReviewsPerApp": 200
}
```

**Chrome Web Store only**

```json
{
  "apps": [
    "ddkjiahejlhfcafbddmgiahcphecmpfh",
    "https://chromewebstore.google.com/detail/ddkjiahejlhfcafbddmgiahcphecmpfh"
  ],
  "language": "en",
  "maxReviewsPerApp": 300
}
```

(Both lines point to the same extension, shown only to illustrate the two accepted formats; use one per extension.)

**Apple App Store only**

```json
{
  "apps": ["https://apps.apple.com/us/app/whatsapp-messenger/id310633997"],
  "countries": ["us"],
  "maxReviewsPerApp": 500
}
```

**All three stores in one run, with sentiment**

```json
{
  "apps": [
    "310633997",
    "com.whatsapp",
    "ddkjiahejlhfcafbddmgiahcphecmpfh"
  ],
  "countries": ["us"],
  "language": "en",
  "maxReviewsPerApp": 100,
  "sentiment": true
}
```

### Output

Each review is one dataset item. All three stores use the same fields.

| Field | Type | Description |
|---|---|---|
| `store` | string | `apple`, `google` or `chrome` |
| `appId` | string | App ID, package name, or 32-letter extension ID |
| `country` | string or null | Country the review was fetched from. Always `null` for Chrome (reviews are not per country). |
| `language` | string or null | Review language |
| `reviewId` | string | Review ID, unique within a store |
| `rating` | integer or null | Star rating, 1 to 5 |
| `title` | string or null | Review title. Always `null` for Chrome; Google Play reviews have no title either, so it may be empty. |
| `text` | string or null | Review body, with most emails and phone numbers masked (best effort) |
| `appVersion` | string or null | App or extension version the reviewer used |
| `thumbsUp` | integer or null | Helpful / thumbs-up count |
| `reviewedAt` | string or null | Review time (ISO 8601) |
| `developerReply` | string or null | Developer reply text, if any |
| `sentiment` | string or null | Only when `sentiment` is on: `positive`, `neutral`, `negative` |
| `reviewerName` | string or null | Only when `includeReviewerName` is on: masked nickname such as `J***` |

#### Example item

Illustrative values based on the dataset schema examples (the `reviewId` is a placeholder, not a real review):

```json
{
  "store": "google",
  "appId": "com.whatsapp",
  "country": "us",
  "language": "en",
  "reviewId": "example-review-0001",
  "rating": 5,
  "title": null,
  "text": "Example review text.",
  "appVersion": "1.0.0",
  "thumbsUp": 0,
  "reviewedAt": "2026-10-01T00:00:00.000Z",
  "developerReply": null
}
```

#### Run summary

Besides the dataset, each run writes a summary: duplicates removed across countries, apps that returned nothing (for example a wrong ID), apps that hit Apple's 500-review cap, and store-level warnings such as an empty Apple feed.

### How it works

- **Apple App Store:** Apple's public customer-reviews feed (RSS/JSON).
- **Google Play:** the open-source `google-play-scraper` library (MIT).
- **Chrome Web Store:** the same anonymous data request the store's public reviews page makes. Reviews come newest first, 50 per request, at most one request per second.
- **Deduplication:** the same `reviewId` is kept once across countries; `country` is the first country it was seen in.
- **Retries:** network errors, HTTP 429 and 5xx are retried up to 3 times (2s / 4s / 8s back-off). After that the app/country is skipped and the reason is logged.
- **Circuit breaker:** if 2 consecutive Google Play tasks, or 2 consecutive Chrome extensions, fail to parse, the rest of that store's tasks are skipped and the summary says the store page may have changed. Parsing failures are skipped, not written as data.

### Privacy

- Reviewer nicknames are off by default. When on, only the first character plus `***` is output. Avatars, profile links and user IDs are never output.
- Emails and phone numbers in titles, review text and developer replies are replaced with placeholders (currently `[邮箱已隐藏]` for email and `[电话已隐藏]` for phone). Matching is conservative, so some phone formats may be missed. Names or addresses that reviewers typed themselves are not detected.
- Review text is never written to the log.
- You are responsible for complying with the data-protection laws that apply to you. Do not use the data for spam or harassment.

### FAQ

**Do I need an App Store, Google or Chrome account?**
No. The Actor only reads public review data. No login, no cookies, no CAPTCHA bypass.

**Can I mix apps and extensions in one run?**
Yes. Put Apple IDs, Google package names and Chrome extension IDs (or their URLs) in the same `apps` list.

**Why did I get no Apple reviews?**
Since October 2026 Apple's public feed sometimes returns empty pages. The run summary and log say so (`APPLE_ALL_EMPTY` or `APPLE_NO_REVIEWS`). If nothing at all was written, the run is marked failed; if other stores returned reviews, it finishes with a warning. An empty result can also mean a wrong app ID or a country with no reviews.

**How many reviews can I get?**
Up to `maxReviewsPerApp` per app per country (per extension for Chrome). Apple caps at 500 per app per country; this cannot be exceeded.

**Why is `country` empty for Chrome extensions?**
The Chrome Web Store does not split reviews by country. Use `language` to filter instead.

**Does it return only new reviews since my last run?**
No. Each run fetches up to your limit. To track new reviews, schedule the Actor and keep the `reviewId`s you have already seen (see the tutorial linked below).

**Is the sentiment label AI?**
No. It is a simple rule based on English keywords and the star rating. For deeper analysis, export the dataset and run your own model.

**How much does it cost?**
There is currently no Actor fee. You pay only the Apify platform usage of the run.

**Is this an official Apple or Google tool?**
No. It is an independent tool, not affiliated with or endorsed by Apple Inc. or Google LLC. Store names are used only to describe the supported sources. Example apps are used only as public examples.

### Limits

- Apple's public review feed is currently unreliable and may return no reviews.
- Apple: at most 500 reviews per app per country.
- Google Play support relies on an unofficial open-source library and may break when Google changes its site.
- Chrome Web Store support uses the store's own page data request, which is not a documented API and may break if the site changes.
- Phone and email redaction is conservative and may miss some formats.
- This is an independent tool, not an official Apple or Google tool, and is not affiliated with or endorsed by Apple Inc. or Google LLC. No Apple or Google logos are used.

### Support

Found a bug or need a field? Open an issue on the **Issues** tab of this page. On a valid complaint from a platform or rights holder, the Actor will be taken down within 24 hours.

# Actor input Schema

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

Apple numeric ID / apps.apple.com URL, Google package name / play.google.com URL, or Chrome extension ID (32 letters a–p) / chromewebstore.google.com URL. Store auto-detected. Example (prefilled): WhatsApp on Google Play and uBlock Origin Lite on the Chrome Web Store. Apple App Store is temporarily limited (its public review feed sometimes returns no reviews). If apps is left out, the example apps above are used (default); the count then follows maxReviewsPerApp (default 100).

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

Two-letter country codes, e.g. us, gb. Not used for Chrome extensions (Chrome Web Store reviews are not per country).

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

Apple does not support language selection; it is determined by country. For Chrome extensions, only reviews written in this language are returned.

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

Default 100. The form is prefilled with 5 so the example run stays small; raise it for real runs. Apple hard limit is 500 per app per country.

## `includeReviewerName` (type: `boolean`):

Off by default. When on, only the first character plus \*\*\* is output.

## `sentiment` (type: `boolean`):

Adds a simple sentiment label per review. Off by default.

## Actor input object example

```json
{
  "apps": [
    "com.whatsapp",
    "ddkjiahejlhfcafbddmgiahcphecmpfh"
  ],
  "countries": [
    "us"
  ],
  "language": "en",
  "maxReviewsPerApp": 5,
  "includeReviewerName": false,
  "sentiment": false
}
```

# Actor output Schema

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

All reviews in the default dataset: 12 default fields, plus optional nullable sentiment (off by default) and reviewerName (masked public nickname, only when the switch is on).

# 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",
        "ddkjiahejlhfcafbddmgiahcphecmpfh"
    ],
    "maxReviewsPerApp": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("tiandu-tech/apify-002-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 = {
    "apps": [
        "com.whatsapp",
        "ddkjiahejlhfcafbddmgiahcphecmpfh",
    ],
    "maxReviewsPerApp": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("tiandu-tech/apify-002-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 '{
  "apps": [
    "com.whatsapp",
    "ddkjiahejlhfcafbddmgiahcphecmpfh"
  ],
  "maxReviewsPerApp": 5
}' |
apify call tiandu-tech/apify-002-app-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tiandu-tech/apify-002-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/oOhmPJI6dESohJ5g1/builds/DG4i4rbncICtwZwtd/openapi.json
