# App Reviews Scraper & Insights: Google Play + App Store (`psgameplay121/app-review-insights`) Actor

Google Play and Apple App Store reviews for any app and country, plus a per-app insights report: official star histogram, rating trend by version, complaint and praise keywords, topics (crashes, login, pricing, ads), feature requests and developer reply rate.

- **URL**: https://apify.com/psgameplay121/app-review-insights.md
- **Developed by:** [Vivek Sinha](https://apify.com/psgameplay121) (community)
- **Categories:** Marketing, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## App Reviews Scraper & Insights: Google Play + App Store

Get **Google Play and Apple App Store reviews** for any app, in any country, as clean rows. Then get an **app insights report** for each app: what users complain about, what they love, how ratings move from version to version, and how the developer responds. No login, no API key, no AI subscription needed.

Use it to:

- **Monitor your own app** after every release: spot a rating drop on the new version, a crash or login problem, or a pricing backlash before it hits your store rating.
- **Research competitors**: compare complaint themes, feature requests and reply rates across rival apps in a single run.
- **Feed your tools**: export reviews to Google Sheets, a BI tool, Slack alerts or your own AI pipeline, with topics and sentiment already tagged.

### What you get

#### 1. Review rows (event `review`)

One row per review, with:

| Field | Example |
|---|---|
| `store` | `google-play` or `apple` |
| `appName`, `appId` | Duolingo, `com.duolingo` / `570060128` |
| `country` | `us` |
| `rating` | 1–5 |
| `title`, `text` | the review (App Store reviews have a title, Google Play reviews don't) |
| `appVersion` | `7.146.1`, the app version the user reviewed |
| `reviewedAt` | ISO date |
| `helpfulVotes` | thumbs-up count |
| `developerReply`, `developerReplyAt` | Google Play: the developer's public reply |
| `sentiment` | `positive` / `neutral` / `negative` (from the star rating) |
| `topics` | e.g. `crash-freeze`, `login-account`, `pricing-subscription`, `ads`, `ui-ux`, `update-regression`, `customer-support`, `feature-request`, `notifications`, `sync-data-loss`, `privacy-security`, `performance-speed`, `bugs-errors`, `content-quality` |
| `language` | Google Play review language |
| `isNew` | `true` in monitoring mode for reviews not seen before |

Reviewer names are **left out by default** (privacy-friendly); turn on *Include reviewer nicknames* if you need them.

#### 2. App insights report (event `app-report`, one row per app)

- **Official rating**: the store's all-time average, rating count and **star histogram** (per country for the App Store).
- **Recent reviews vs all-time**: e.g. "Recent reviews are below the all-time rating of 4.5★ (-1.6)".
- **Rating distribution** of the reviews read.
- **Trend by app version** (average stars and % negative per version) and **latest version vs previous version**.
- **Trend over time** by week or month.
- **Per-country comparison**.
- **Topics**: share of reviews, average stars and % negative for each topic, plus the main **complaint themes**.
- **Top complaint keywords** and **top praise keywords**: terms that are over-represented in 1–2★ vs 4–5★ reviews (statistical log-odds ranking, no paid AI API).
- **Feature requests**, **most helpful negative reviews** and **positive highlights** (quoted).
- **Developer replies** (Google Play): reply rate, reply rate on negative reviews, median reply time.
- A one-paragraph **plain-English summary**.

Example summary (Calm, Google Play, US + Germany, 400 reviews):

> 400 reviews from 2 countries: average 2.87★, 49% negative (1-2★). Recent reviews are below the all-time rating of 4.5★ (-1.6). Version 7.4 averages 3.24★ vs 3.32★ for 7.3. Main complaint themes: pricing-subscription, customer-support, bugs-errors. Top complaint terms: pay, premium, subscription, free, cancel. Developer replied to 32.5% of reviews (50% of negative ones), median 17.1 h after the review.

### How to use

1. Add apps:
   - **Google Play**: a link like `https://play.google.com/store/apps/details?id=com.duolingo` or just `com.duolingo`.
   - **App Store**: a link like `https://apps.apple.com/us/app/duolingo-language-lessons/id570060128`, the id `570060128`, a bundle id, or the app name.
2. Pick **countries** (`us`, `gb`, `in`, `de`, `jp`, ...).
3. Set **Reviews to read per app and country** (default 100).
4. Optional filters: **date range** (`2026-10-01` or `30 days`), **star ratings** (e.g. only 1 and 2), **keywords** (e.g. `crash`, `refund`).
5. Run. Review rows and reports land in the dataset; switch between the *Reviews* and *App reports* views.

**Report only:** turn off *Output review rows* to pay just for the report (one charge per app).

**Monitoring:** turn on *Only new reviews since the last run* and schedule the Actor daily or weekly. You only pay for new reviews. Use a separate *Monitoring state name* per schedule.

#### Input example

```json
{
  "googlePlayApps": ["com.duolingo", "com.babbel.mobile.android.en"],
  "appStoreApps": ["https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 500,
  "dateFrom": "90 days",
  "appReport": true
}
```

### Pricing (pay per event)

- **$0.20 per 1,000 reviews** (`review`, $0.0002 each), with topics and sentiment included.
- **$0.02 per app insights report** (`app-report`).
- Filters run first: you pay only for rows you receive. Duplicates across countries and sort orders are removed before charging.
- A report is **free** if fewer than 10 (configurable) reviews were found for that app in the store's review feed.
- Set a maximum charge per run in Apify to cap your spend.

### Data sources and limits (please read)

- **Public data only**, no login. Google Play: the public web endpoints the Play Store website uses. App Store: Apple's public customer-reviews feed, the iTunes Lookup API and the public app page.
- **Google Play** is the most complete source: thousands of reviews per app, newest first. Google groups Play reviews by language more than by country, so `us`, `gb` and `in` (all English) return largely the same reviews; duplicates are removed. Non-English countries are read in their main language (change with *Google Play review language*).
- **App Store**: Apple's public feed serves at most 500 recent reviews per country (and 500 "most helpful"), and **in 2026 it often returns empty pages**. The Actor tries several equivalent feed addresses for each page and skips empty ones, then adds the featured reviews from the app page. Expect anywhere from about 10 to a few hundred App Store reviews per country per run; `feedCoverage` in the report shows how many feed pages were available. The official star histogram and rating per country are always included. For steady App Store coverage, use monitoring mode on a schedule: new reviews are collected run after run.
- Topics and keywords work best for English; other languages get keywords but fewer topic tags.
- Sentiment comes from the star rating, not from text analysis.

### FAQ

**Can I get reviews for my competitors?** Yes, any public app.

**Is this legal?** The Actor collects publicly visible reviews and skips reviewer names by default. You are responsible for using the data in line with applicable laws (e.g. GDPR) and the stores' terms.

**Something missing or broken?** Open an issue on the Actor page. Fixes are usually quick.

# Actor input Schema

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

One per line. An App Store link (https://apps.apple.com/us/app/duolingo-language-lessons/id570060128), a numeric app id (570060128), a bundle id (com.burbn.instagram) or an app name (the top search result is used, so a link is safer).

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

One per line. A Google Play link (https://play.google.com/store/apps/details?id=com.duolingo) or a package name (com.duolingo).

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

Two-letter country codes, one per line (us, gb, in, de, fr, jp, br, ...). App Store: each country is a separate storefront with its own reviews. Google Play: each country is read in its main language (see Google Play review language). Default: us.

## `playLanguage` (type: `string`):

Google Play groups reviews by language. 'auto' reads each country in its main language (de for Germany, ja for Japan, en for the US/UK/India...). Or set one language code for all countries, e.g. en.

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

How many reviews to read per app per country, newest first. Google Play: up to 5,000. App Store: Apple's public feed serves at most 500 per country and sort order, and often leaves pages empty, so expect fewer.

## `sortBy` (type: `string`):

Newest is best for monitoring, date ranges and version trends.

## `dateFrom` (type: `string`):

Only reviews on or after this date, e.g. 2026-10-01 or a relative value like 30 days. Leave empty for no limit.

## `dateTo` (type: `string`):

Only reviews on or before this date. Leave empty for no limit.

## `ratings` (type: `array`):

Return only review rows with these star ratings, e.g. 1 and 2 for complaints. The app report still uses all reviews in the date range. Empty = all.

## `reviewKeywords` (type: `array`):

Return only review rows whose title or text contains at least one of these words (case-insensitive), e.g. crash, subscription, login. The app report still uses all reviews.

## `outputReviews` (type: `boolean`):

One row per review (charged per row). Turn off to get only the app insights report.

## `appReport` (type: `boolean`):

One extra row per app: official star histogram, rating distribution of recent reviews, trend by version and by week/month, per-country ratings, complaint topics, top complaint and praise keywords, feature requests, developer reply rate (Google Play) and the most helpful negative reviews. Charged once per app.

## `minReviewsForReport` (type: `integer`):

If fewer reviews than this are found for an app, its report is still returned but free of charge.

## `includeAuthorNames` (type: `boolean`):

Off by default for privacy. Turn on to add the reviewer's public display name to each review row.

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

Stop returning review rows after this many across all apps and countries. Useful to cap cost.

## `incremental` (type: `boolean`):

Remembers which reviews were already returned (per app and country) and returns only new ones, so scheduled monitoring runs only pay for new reviews. New rows have isNew: true.

## `stateKey` (type: `string`):

Use a different name for each separate monitoring schedule so they don't share memory.

## Actor input object example

```json
{
  "appStoreApps": [
    "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"
  ],
  "googlePlayApps": [
    "com.duolingo"
  ],
  "countries": [
    "us"
  ],
  "playLanguage": "auto",
  "maxReviewsPerApp": 30,
  "sortBy": "newest",
  "outputReviews": true,
  "appReport": true,
  "minReviewsForReport": 10,
  "includeAuthorNames": false,
  "maxReviews": 0,
  "incremental": false,
  "stateKey": "default"
}
```

# Actor output Schema

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

All rows returned by this run: review rows and app insights reports.

## `runReport` (type: `string`):

Summary of the run: apps resolved, reviews read per country, and any errors.

# 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 = {
    "appStoreApps": [
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"
    ],
    "googlePlayApps": [
        "com.duolingo"
    ],
    "countries": [
        "us"
    ],
    "maxReviewsPerApp": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("psgameplay121/app-review-insights").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 = {
    "appStoreApps": ["https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"],
    "googlePlayApps": ["com.duolingo"],
    "countries": ["us"],
    "maxReviewsPerApp": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("psgameplay121/app-review-insights").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 '{
  "appStoreApps": [
    "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"
  ],
  "googlePlayApps": [
    "com.duolingo"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 30
}' |
apify call psgameplay121/app-review-insights --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,psgameplay121/app-review-insights"
        }
    }
}
```

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/wi0cZXLHkjYssVOQp/builds/prm4lvxdI1I5SeVyu/openapi.json
