# App Store Reviews API: Apple App Reviews by App ID and Country (`ailu_studio/app-store-reviews`) Actor

Fetch Apple App Store reviews by app id or URL and country from the public iTunes RSS feed: rating, title, text, version, votes, author, date, plus app rating summary. No login, no proxies.

- **URL**: https://apify.com/ailu_studio/app-store-reviews.md
- **Developed by:** [Ailu Studio](https://apify.com/ailu_studio) (community)
- **Categories:** E-commerce, Marketing, Agents
- **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 and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Store Reviews API: Apple App Reviews by App ID and Country

Fetch Apple App Store customer reviews for any iOS app and get them as clean, flat rows: star rating, title, text, app version, helpfulness votes, reviewer nickname and date, together with the app name and store URL. Give the Actor one or more app ids or App Store URLs and a list of storefront countries, pick the sort order (most recent or most helpful), optionally filter by star rating or age, and it reads Apple's public customer-reviews RSS feed (JSON) page by page. One free summary row per app and country adds the current average rating, rating counts, version, price and developer from the iTunes lookup API. No login, no proxies, no browser, no HTML scraping, so it runs in seconds and works well as an MCP tool for AI agents and in scheduled automations.

### Use cases

- Product and support teams: pull the newest 1- and 2-star reviews of your app every morning and route them to Slack or a ticket queue.
- Competitive analysis: compare ratings and complaints for several competing apps across the US, UK, German and Japanese storefronts.
- Sentiment and topic analysis: build a dataset of recent reviews per version to see which release introduced a problem.
- AI agents: answer "what are users saying about app X this week?" with one structured call.
- Monitoring: schedule a run with `sinceDays` to collect only reviews written since the last run.

### Input

| Field | Default | Meaning |
|---|---|---|
| `apps` | `["284882215"]` | Apple app ids or App Store URLs containing `/id<digits>`. Each app is fetched for every country. |
| `countries` | `["us"]` | Two-letter storefront codes, e.g. `us`, `gb`, `de`, `jp`. |
| `sortBy` | `mostRecent` | `mostRecent` or `mostHelpful`; decides which reviews come first when the run is capped. |
| `maxPagesPerApp` | `3` | RSS pages per app and country, 1 to 10 (50 reviews per page). |
| `minRating` | – | Keep only reviews with this rating or higher (1 to 5). |
| `maxRating` | – | Keep only reviews with this rating or lower (1 to 5). |
| `sinceDays` | – | Keep only reviews updated in the last N days; stops paging early with `mostRecent`. |
| `includeAppMetadata` | `true` | Add one free `rowType: "app"` summary row per app and country. |
| `maxItems` | `500` | Maximum charged review rows per run. |

The default run returns the newest reviews of Facebook (id 284882215) from the US storefront, up to 150 reviews plus one app row.

### Output

| Field | Meaning |
|---|---|
| `id` | Stable key: `<appId>:<country>:<reviewId>`, or `<appId>:<country>:app` for the summary row. |
| `rowType` | `review` (charged) or `app` (free summary row). |
| `appId`, `appName`, `country` | App id, app name from the lookup API, storefront code. |
| `reviewId`, `title`, `text` | Apple's review id, review title and body (paragraph breaks preserved). |
| `rating` | Stars 1 to 5 as a number. |
| `version` | App version the review was written for. |
| `voteSum`, `voteCount` | Helpfulness votes on the review. |
| `author`, `authorUrl` | Reviewer nickname and public profile URL. |
| `updatedAt` | ISO 8601 UTC time the review was written or last edited. |
| `url` | App Store page of the app in that storefront (reviews have no public URL of their own). |
| `fetchedAt` | ISO 8601 UTC fetch time. |

App rows (`rowType: "app"`) additionally carry `developer`, `primaryGenre`, `averageRating`, `ratingCount`, `averageRatingCurrentVersion`, `ratingCountCurrentVersion`, `versionReleasedAt`, `price`, `currency`, `bundleId`, `minimumOsVersion` and `contentAdvisoryRating`.

```json
{
  "id": "284882215:us:14740119862", "rowType": "review",
  "appId": "284882215", "appName": "Facebook", "country": "us", "reviewId": "14740119862",
  "title": "Review for Facebook",
  "text": "Sick of gambling advertisements. Are you trying to turn me into a gambler",
  "rating": 2, "version": "585.0.0", "voteSum": 0, "voteCount": 0,
  "author": "Karen Munsell", "authorUrl": "https://itunes.apple.com/us/reviews/id872857104",
  "updatedAt": "2026-11-02T01:28:40.000Z",
  "url": "https://apps.apple.com/us/app/facebook/id284882215",
  "fetchedAt": "2026-11-03T15:00:00.000Z"
}
```

The run summary (apps, countries, pages read, reviews seen, errors) is stored in the `OUTPUT` record of the default key-value store.

### How it works and limits

- For each app and country the Actor calls `GET https://itunes.apple.com/lookup?id=<appId>&country=<cc>` once (app name, URL and the free summary row) and then `GET https://itunes.apple.com/<cc>/rss/customerreviews/id=<appId>/sortBy=<sort>/page=<n>/json` for pages 1 to `maxPagesPerApp`, stopping early at the last page, when `maxItems` is reached or, with `sinceDays` and `mostRecent`, when a page holds no review inside the window.
- Apple serves at most 10 pages of 50 reviews per app and country, so the feed covers roughly the latest 500 reviews per storefront. Older reviews are not retrievable through this endpoint.
- Rating and date filters are applied after fetching, so a page is always read in full; filtered-out reviews are not charged.
- Politeness: requests to Apple are spaced at least 300 ms apart; 429 and 5xx responses are retried with exponential back-off, and 403 responses are retried twice after 2 s and 4 s. One app and country with 3 pages takes about 2 seconds.
- Apple's feed is live and its pages can overlap or shift between requests, so consecutive pages sometimes repeat reviews. The Actor removes duplicates by review id within a run, which is why a page can yield fewer than 50 new reviews.
- A country where the app has no reviews returns an empty feed and no rows. An app id that does not exist in a storefront is reported in the run summary and the run finishes with status `partial`.
- Reviews are returned as Apple publishes them; there is no developer-reply field in this feed. Review language follows the storefront.

### Pricing

Pay per result: **$0.50 per 1,000 rows** (`result` event). Platform usage is billed separately by Apify. Removed/free rows are not charged.

A default run (one app, one country, up to 150 reviews) takes a few seconds and four requests.

### Legal

Not affiliated with Apple Inc. Uses the public iTunes customer-reviews RSS feed and iTunes Search (lookup) API only. Data licence/terms: https://www.apple.com/legal/internet-services/terms/site.html (reviews are user-generated content published by Apple; use them in accordance with Apple's terms and applicable law).

### FAQ

**Where do I find the app id?** It is the number after `id` in any App Store URL, e.g. `https://apps.apple.com/us/app/facebook/id284882215` gives `284882215`. You can paste the whole URL into `apps`.

**Can I get all reviews of an app?** No. Apple's feed exposes at most 500 reviews (10 pages of 50) per app and country. To build a complete history, run the Actor regularly (for example daily with `sinceDays: 2`) and deduplicate on `id`.

**How do I get only negative reviews?** Set `minRating: 1` and `maxRating: 2`. Pages are still read in full, but only matching reviews are returned and charged.

**Why is `appName` empty for some rows?** The name comes from the lookup API. If that request fails, review rows are still returned with `appName: null` and the summary row is skipped; the error is listed in the run summary.

**Does the Actor return developer responses?** No. Apple's RSS feed does not include developer replies.

# Actor input Schema

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

One or more apps as numeric Apple app ids (e.g. "284882215") or App Store URLs containing the id (e.g. "https://apps.apple.com/us/app/facebook/id284882215"). Each app is fetched for every country listed below.

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

Two-letter storefront codes to fetch reviews from, e.g. \["us", "gb", "de"]. Reviews are stored per country; a country with no reviews for the app simply returns nothing.

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

Order Apple applies before paging: newest reviews first, or reviews with the most helpful votes first. It decides which reviews are included when maxPagesPerApp or maxItems cuts the run short.

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

How many RSS pages (50 reviews each) to read per app and country, 1 to 10 (default 3 = up to 150 reviews). Apple exposes at most 10 pages, i.e. the latest ~500 reviews per country.

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

Keep only reviews with this star rating or higher (1 to 5). Optional; filtering is done after fetching, so pages are still read in full.

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

Keep only reviews with this star rating or lower (1 to 5). Set minRating=1 and maxRating=2 to collect only negative reviews. Optional.

## `sinceDays` (type: `integer`):

Keep only reviews updated within the last N days. With sortBy=mostRecent the Actor stops paging as soon as a page contains no review inside the window. Optional.

## `includeAppMetadata` (type: `boolean`):

When true (default), one extra row with rowType "app" per app and country is added from the iTunes lookup API: app name, developer, genre, average rating, rating counts, version, price. These rows are free (not charged).

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

Upper limit on charged review rows for this run (default 500). Free app-summary rows do not count. Each RSS page yields up to 50 reviews.

## Actor input object example

```json
{
  "apps": [
    "284882215"
  ],
  "countries": [
    "us"
  ],
  "sortBy": "mostRecent",
  "maxPagesPerApp": 3,
  "includeAppMetadata": true,
  "maxItems": 500
}
```

# Actor output Schema

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

All rows in the default dataset.

# 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": [
        "284882215"
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ailu_studio/app-store-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": ["284882215"],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("ailu_studio/app-store-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": [
    "284882215"
  ],
  "countries": [
    "us"
  ]
}' |
apify call ailu_studio/app-store-reviews --silent --output-dataset

```

## MCP server setup

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