# App Store Reviews Scraper - By Country & Version (`dataio/app-store-reviews-by-country-version`) Actor

Scrape App Store reviews across up to 40 countries in one table, each review tagged with the app version it was written against, so you can see which release broke what, and where. Rating, title, text and date for every review. No API key.

- **URL**: https://apify.com/dataio/app-store-reviews-by-country-version.md
- **Developed by:** [Tom Awake](https://apify.com/dataio) (community)
- **Categories:** E-commerce, SEO tools, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.33 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What does App Store Reviews Scraper do?

Every review, across every market, in one table — each one tagged with the
**app version it was written against**.

Apple publishes reviews as an RSS feed: one country, one page of 50 at a
time. Reading the Japanese and Brazilian reviews of an app means twenty
requests and a manual merge. And every review carries the version number
the user was running, which almost nobody uses.

That version tag is the point. A global rating of 4.7 can hide a collapse
on a single market, or a single release.

No API key. No account.

***

### What the data actually shows

950 Spotify reviews, 7 markets, one run:

| Market | Average rating | 1-2 star share |
|---|---|---|
| **South Korea** | **3.73** | 23% |
| India | 3.84 | 26% |
| United Kingdom | 3.85 | 23% |
| Germany | 3.96 | 18% |
| Japan | 3.99 | 18% |
| Brazil | 4.13 | 19% |
| **United States** | **4.21** | 14% |

Nearly half a point between Korea and the US, and complaints running from
14% to 26% of reviews depending on where you look. The store's headline
rating shows none of this.

And by version, from the same run:

| Version | Average | Reviews |
|---|---|---|
| 9.1.78 | **3.67** | 76 |
| 9.1.80 | 3.97 | 358 |
| 9.1.82 | 3.98 | 514 |

A bad release and its recovery, visible as a table.

***

### The three things this does that the source does not

**1. Every market in one table.**

Up to 500 reviews per country — Apple's ceiling, reached at ten pages of
fifty. Seven markets in the run above meant 21 requests, merged and
aligned into one dataset.

**2. The version tag, as a column you can group by.**

`appVersion` comes straight from the feed, plus `versionSort` — a
zero-padded key, because `9.1.9` sorts after `9.1.80` as plain text and
that ruins every chart built on it.

**3. Review age in days.**

`daysAgo` on every row. Sorted most recent first, median review age in the
run above was **3 days** — this is what users are saying now, not an
accumulated average from three years ago.

***

### Field coverage

Measured on 950 reviews across 7 markets.

| Field | Coverage |
|---|---|
| `rating`, `title`, `content`, `author` | 100% |
| `appVersion`, `versionSort` | 100% |
| `reviewedAt`, `daysAgo` | 100% |
| `reviewId`, `appName`, `countryName` | 100% |
| `voteCount`, `helpfulness` | **0.6%** |

That last row is not a bug and is worth stating plainly: helpfulness votes
are almost never present on recent reviews, because nobody has voted on
them yet. Sort by **most helpful** if you need that field populated —
those reviews are older, by construction.

***

### What it is for

- **Post-release triage.** Filter to 1-2 stars and one version. The
  complaints about what you just shipped, separated from the background
  noise.
- **Localisation and market health.** The market with the lowest rating is
  the one to read first, and it is rarely the one you are watching.
- **Competitive research.** Point it at a competitor's app ID and read
  what their users complain about, market by market.
- **Feature demand.** Recurring requests in low-rated reviews are a
  roadmap someone else wrote for you.
- **Support monitoring.** Run daily with `postedWithinDays: 1`.

Three dataset views ship with the Actor: **Reviews**, **Complaints** and
**By version**.

Pairs with **App Store Intelligence**, which covers the listing itself —
price, rating and distribution per market.

***

### Limits

Stated plainly, because they affect what you can conclude.

- **500 reviews per country, hard.** Page 11 returns HTTP 400. For an app
  with millions of reviews this is a recent sample, not a census — treat
  per-market averages as indicative, and read the counts.
- **Only two sort orders work.** `mostRecent` and `mostHelpful`.
  Apple documents `mostFavorable` and `mostCritical`; both return HTTP 500.
  Use the rating filter instead.
- **Sampling bias by design.** Most recent reviews skew toward whoever is
  motivated to write today, which is disproportionately people with a
  problem. The share of 1-2 star reviews here is higher than the app's
  lifetime distribution.
- **Reviews are not translated.** Japanese reviews come back in Japanese.
  That is the real text; translating it is your choice, not ours.
- **Author names are display names.** Public pseudonyms chosen by the
  reviewer and published by Apple. They are not identities, and should not
  be treated as such.
- **Some markets return nothing for some apps.** That means no reviews
  there, not a failure. The status message names those combinations.
- **A version with few reviews proves little.** Group by version only when
  the count supports it.

***

### How much does it cost?

You pay per review returned: **$0.002 each**, that is $2.00 per 1,000. There is no start fee, and subscription plans pay less per review.

The example input below asks for up to 1,000 reviews, so it costs **$2.00 at most**.

If a run reaches the spending limit you set, the output stops at that limit and never goes past it. You are never charged for rows that were not delivered.

### Use App Store Reviews Scraper as an API

Call it from your own code with the Apify client, here in Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/app-store-reviews-by-country-version").call(run_input={
    'appIds': ['324684580'],
    'countries': ['us', 'gb', 'de', 'jp', 'br'],
    'pagesPerCountry': 3,
    'maxItems': 1000,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

### Other actors you might like

- [App Store Price Scraper](https://apify.com/DataIO/app-store-price-intelligence): Compare by Country
- [Steam Price Scraper](https://apify.com/DataIO/steam-regional-pricing-intelligence): Regional Game Prices
- [Steam Reviews Scraper](https://apify.com/DataIO/steam-reviews-playtime-scraper): With Playtime Data

### FAQ

#### Is it legal to use this data?

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

#### Can I run it on a schedule?

Yes. Create a schedule in Apify Console, daily or weekly for example, and each run delivers a fresh dataset, which you can send by email, webhook or integration.

#### Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

### Source

Apple's public App Store customer review RSS feeds, the same ones that
power review sections across the web. No authentication. This Actor is not
affiliated with Apple.

# Actor input Schema

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

Numeric App Store IDs — the digits after /id in an App Store URL. Up to 50 apps per run.

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

Two-letter country codes. This is where the value is: measured on 950 Spotify reviews, the average rating ran from 3.73 in South Korea to 4.21 in the United States, and the share of 1-2 star reviews from 14% to 26%.

## `pagesPerCountry` (type: `integer`):

50 reviews per page, 10 pages maximum — Apple's own ceiling, so 500 reviews per country at most.

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

Most recent gives you what users are saying now — median review age is 3 days. Most helpful surfaces the reviews other users voted up.

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

Select 1 and 2 to read only the complaints. Leave empty for all.

## `appVersion` (type: `string`):

Exact version string, for example 9.1.80. Every review carries the version it was written against — this is how you isolate what a release broke.

## `postedWithinDays` (type: `integer`):

A one-star review from three years ago says nothing about today's product.

## `maxItems` (type: `integer`):

One row per review. Most recent first.

## Actor input object example

```json
{
  "appIds": [
    "324684580"
  ],
  "countries": [
    "us",
    "gb",
    "de",
    "jp",
    "br"
  ],
  "pagesPerCountry": 3,
  "sortBy": "recent",
  "maxItems": 1000
}
```

# Actor output Schema

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

Every row produced by the run, in JSON.

# 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 = {
    "appIds": [
        "324684580"
    ],
    "countries": [
        "us",
        "gb",
        "de",
        "jp",
        "br"
    ],
    "pagesPerCountry": 3,
    "maxItems": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataio/app-store-reviews-by-country-version").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 = {
    "appIds": ["324684580"],
    "countries": [
        "us",
        "gb",
        "de",
        "jp",
        "br",
    ],
    "pagesPerCountry": 3,
    "maxItems": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("dataio/app-store-reviews-by-country-version").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 '{
  "appIds": [
    "324684580"
  ],
  "countries": [
    "us",
    "gb",
    "de",
    "jp",
    "br"
  ],
  "pagesPerCountry": 3,
  "maxItems": 1000
}' |
apify call dataio/app-store-reviews-by-country-version --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataio/app-store-reviews-by-country-version"
        }
    }
}
```

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/SdMFb8aIFfdhmkJy2/builds/GxghlAc408uehyqHA/openapi.json
