# App Review Radar - Multi-Country iOS Reviews + Summary (`always_yao/app-review-radar`) Actor

Collect public App Store reviews across countries and turn them into an actionable complaint/praise summary with prioritized recommendations.

- **URL**: https://apify.com/always_yao/app-review-radar.md
- **Developed by:** [yao yao](https://apify.com/always_yao) (community)
- **Categories:** Developer tools, E-commerce
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 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/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 Review Radar — Multi-Country App Store Reviews + Actionable Summary

Stop reading thousands of App Store reviews across countries.

App Review Radar collects public iOS App Store reviews from multiple storefronts, normalizes them into one dataset, and adds a one-page report of what users complain about, what they praise, and what to fix first.

No login. No proxy. No browser. Public Apple data only.

### The problem

- Your reviews are spread across US, UK, Japan, Germany and more.
- The 1-star reviews are buried in noise.
- You can see the rating, but not **why** it dropped.
- Raw CSV exports don't tell you what to fix next.

### What you get

#### 1. One row per review

App ID, app name, country, star rating, title, body, author, app version, review date, review URL.

#### 2. One app report per app

- Average rating and rating distribution
- Negative-review share
- **Rating by country** (this is where the surprises are)
- Top complaint categories with counts and representative quotes
- Top praise categories
- Prioritized recommendations
- Optional Chinese labels (`summaryLanguage: "zh"`)

In Apify Console, the dataset opens with two table views: **Reviews** (one row per review) and **App reports** (one row per app).

Complaint categories:

`Crashes / stability`, `Login / accounts`, `Ads`, `Pricing / subscriptions`, `Performance / lag`, `UI / usability`, `Missing features`, `Customer support`, `Notifications`, `Content quality`, `Version / update issues`.

### Real sample: Notion, 200 reviews, 4 countries

Input: `appIds: ["1232780281"]`, countries `us, gb, jp, de`, 50 reviews each.

```text
Average rating: 2.59 / 5
Negative share: 55.5%

Rating by country
  us  2.52
  gb  2.82
  jp  2.62
  de  2.40
```

Top complaints:

| Category | Negative reviews |
|---|---|
| Version / update issues | 21 |
| Crashes / stability | 14 |
| Missing features | 14 |

Example quote:

> "Now I cannot manage my page hierarchy any more??? This makes this app unusable on iPad."
> — 1 star, US

Recommendations returned:

1. Watch for regressions in new releases. Compare complaint themes before and after the update.
2. Fix crashes and stability first, especially in the latest release.
3. Rank feature requests by frequency. Ship the one that affects retention first.

That is the whole point: **200 reviews in, one decision out.**

### Real sample: Duolingo, 200 reviews, 4 countries

```text
Average rating: 3.65 / 5
Negative share: 28.0%

Rating by country
  us  3.68
  gb  4.10
  jp  3.26
  de  3.56
```

Same app, same version, **0.84 stars between the UK and Japan**. A single-country review feed would never show you that.

Top complaints:

| Category | Negative reviews |
|---|---|
| Pricing / subscriptions | 11 |
| Missing features | 7 |
| Version / update issues | 7 |

### Output example

```json
{
  "_type": "app_summary",
  "appName": "Notion",
  "countries": ["de", "gb", "jp", "us"],
  "reviewCount": 200,
  "averageRating": 2.59,
  "negativeShare": 0.555,
  "countryBreakdown": [
    { "country": "de", "reviewCount": 50, "averageRating": 2.4, "negativeShare": 0.6 },
    { "country": "gb", "reviewCount": 50, "averageRating": 2.82, "negativeShare": 0.5 }
  ],
  "topComplaints": [
    {
      "category": "update",
      "label": "Version / update issues",
      "count": 21,
      "share_of_negative": 0.189,
      "examples": [
        {
          "rating": 1,
          "country": "us",
          "title": "The new version is unusable",
          "body": "Now I cannot manage my page hierarchy any more."
        }
      ]
    }
  ],
  "unclassifiedNegative": 51,
  "unclassifiedShare": 0.459,
  "recommendations": [
    "Watch for regressions in new releases. Compare complaint themes before and after the update."
  ]
}
```

`unclassifiedNegative` is published on purpose: short reviews like "Awful" carry no signal, and pretending otherwise would be dishonest. Their quotes are still in the dataset so you can spot a new issue manually.

### Input

```json
{
  "appIds": ["1232780281"],
  "countries": ["us", "gb", "jp", "de"],
  "maxReviewsPerCountry": 100,
  "minRating": 1,
  "maxRating": 5,
  "includeSummary": true,
  "summaryLanguage": "en"
}
```

| Field | Type | Description |
|---|---|---|
| `appIds` | array | Numeric App Store IDs or App Store URLs. |
| `countries` | array | Two-letter storefront codes. Default: `us, gb, jp, de`. |
| `maxReviewsPerCountry` | integer | 1–500. Apple's public RSS caps at ~500 per country. |
| `minRating` / `maxRating` | integer | Filter by star rating. |
| `since` | string | Optional `YYYY-MM-DD`; skip older reviews. |
| `includeSummary` | boolean | Add one app report per app. |
| `summaryLanguage` | string | `en` or `zh`. Default: `en`. |

### Pricing

Pay per event:

- **$0.50 per 1,000 reviews** (`review-scraped`)
- **$0.01 per app report** (`app-summary`)

No monthly subscription. You only pay for what you collect.

A 4-country, 400-review run costs about **$0.20**.

### Why not the $0.10 / 1,000 scraper?

Because you would still have to read the reviews.

| | Cheap review scraper | App Review Radar |
|---|---|---|
| Output | Raw rows | Rows + report |
| Countries | Usually one | Aggregated |
| "Why did rating drop?" | You figure it out | Complaint categories + quotes |
| "What do I fix first?" | — | Recommendations |
| Price | $0.10 / 1k | $0.50 / 1k |

You are paying $0.40 more per 1,000 reviews to skip an afternoon of reading.

### Use cases

- ASO and keyword research
- Competitor review analysis
- Localization QA: compare the same app across countries
- Version regression monitoring
- Product prioritization from real user feedback
- Feed an LLM or MCP agent with clean, structured review data

### Limitations

- Apple's public RSS returns the **most recent ~500 reviews per country**, not full history.
- Reviews are point-in-time; run on a schedule to track changes.
- Category classification is keyword-based and intentionally conservative. Very short reviews are counted as unclassified.
- Public data only. The Actor does not log in, bypass challenges or access private data.
- iOS App Store only. Google Play is not supported yet.
- Not affiliated with Apple.

### FAQ

**Do I need an Apple developer account?**
No. This uses Apple's public iTunes lookup and customer-reviews RSS.

**Why only ~500 reviews per country?**
That is Apple's public RSS window. Add more countries or run more often to widen coverage.

**Does it work for Google Play?**
Not yet. This Actor is iOS App Store only.

**Can I get Chinese labels?**
Yes. Set `summaryLanguage` to `zh`.

**Can I run it on a schedule?**
Yes. Use Apify Schedules, the API, MCP, Zapier, Make or n8n.

# Actor input Schema

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

Numeric App Store IDs (e.g. 310633997) or App Store URLs.

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

Two-letter App Store storefront codes, e.g. us, gb, jp, de, ca, au.

## `maxReviewsPerCountry` (type: `integer`):

Apple's public RSS returns at most ~500 reviews per country.

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

Minimum star rating to include.

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

Maximum star rating to include.

## `since` (type: `string`):

Optional YYYY-MM-DD. Reviews older than this are skipped.

## `includeSummary` (type: `boolean`):

Add one app_summary record per app with complaint categories and recommendations.

## `summaryLanguage` (type: `string`):

Language for category labels and recommendations.

## Actor input object example

```json
{
  "appIds": [
    "310633997"
  ],
  "countries": [
    "us",
    "gb",
    "jp",
    "de"
  ],
  "maxReviewsPerCountry": 100,
  "minRating": 1,
  "maxRating": 5,
  "includeSummary": true,
  "summaryLanguage": "en"
}
```

# Actor output Schema

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

Dataset with one row per review and one app_summary row per app (rating distribution, top complaints, recommendations).

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("always_yao/app-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("always_yao/app-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 '{}' |
apify call always_yao/app-review-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,always_yao/app-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/eItTb9P0GMRVUcf5b/builds/4hIasBrD3WTMinDeU/openapi.json
