# App Store Reviews Scraper - Apple iOS App Reviews API (`appdata-labs/app-store-reviews`) Actor

Get customer reviews and ratings for any iOS, iPadOS or macOS app from Apple's official App Store feed. Multi-country, no login, no HTML parsing.

- **URL**: https://apify.com/appdata-labs/app-store-reviews.md
- **Developed by:** [Kobkoon Janngam](https://apify.com/appdata-labs) (community)
- **Categories:** Agents, MCP servers, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 review scrapeds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## App Store Reviews Scraper — Apple iOS App Reviews API

**Get customer reviews and star ratings for any app on Apple's App Store.** Paste an App Store URL, an app ID or a bundle ID and get clean JSON back — review text, rating, author, app version and date.

**Quick start:** press **Start** with no configuration at all. The Actor ships with a working default and returns 100 recent reviews immediately. Then swap in your own app and countries.

### Sample output

| appTitle | rating | title | text | userName | version | country | updatedAt |
|---|---|---|---|---|---|---|---|
| Notion: Notes, Tasks, AI | 5 | Great app | Wonderful, but please fix the crash when scrolling… | Trstn115 | 1.7.330 | us | 2026-08-24T13:54:02-07:00 |
| Notion: Notes, Tasks, AI | 2 | Slow on iPad | Takes ten seconds to open a page since the update. | mfarrell | 1.7.331 | gb | 2026-08-23T09:11:44-07:00 |

Every row also carries `reviewId`, `appId`, `appBundleId`, `appUrl`, `appDeveloper`, `voteCount` and `voteSum`.

### What you can do with it

- **Monitor your own app.** Run it on a schedule and pipe one-star reviews into Slack the day they land, instead of finding them a month later.
- **Watch competitors.** Pull the last 500 reviews for every rival app and find the complaint they keep ignoring — the fastest product-gap research there is.
- **Feed an AI agent.** Output rows are deliberately small and consistently shaped, so you can hand them straight to an LLM for sentiment or theme extraction without blowing up its context window.
- **Track a release.** Reviews carry the exact app version, so you can measure whether a release actually fixed the thing users complained about.
- **Localise.** Apple keeps reviews separate per storefront. Ask for `us`, `jp`, `de`, `br` and `th` in one run and compare markets side by side.

### Input

| Field | Default | Notes |
|---|---|---|
| `appStoreUrlsOrIds` | 3 sample apps | App Store URL, numeric app ID, or bundle ID. Mix formats freely. Multiple apps per run. |
| `countries` | `["us"]` | Two-letter storefront codes. More countries means more reviews for the same app. |
| `maxReviewsPerApp` | `50` | Per app, per country. Apple's own ceiling is 500. |
| `fallbackCountries` | `["gb","ca","au","de"]` | Tried only when an app returns nothing in the countries you asked for. Empty list switches it off. |
| `sortBy` | `mostRecent` | `mostRecent` for monitoring, `mostHelpful` for research. |

### How it works, and why it keeps working

This Actor reads Apple's **official public customer reviews feed**. It does not parse HTML and it does not log in. Apple can redesign the App Store tomorrow and this Actor will keep returning the same fields — which is why it is not on the maintenance treadmill that breaks most scrapers.

Requests are rate-limited below Apple's threshold so a large multi-country run does not get throttled part-way and hand you a half-empty dataset.

### Limits worth knowing before you buy

**Read this one first: Apple's review feed goes quiet for individual apps, at random.** An app with millions of ratings can return nothing in a storefront where it returned fifty reviews an hour earlier, over a normal HTTP 200 with no error to catch. It is per app *and* per country, and it is Apple's behaviour, not a limit of this Actor — measured 2026-09-02, four major apps all returned nothing in the US while three of them returned fifty each in GB, CA or AU in the same minute.

Three things here are built around that, and they are the reason to pick this Actor over a thinner one:

- **Other storefronts are tried automatically.** If an app yields nothing in the countries you asked for, `fallbackCountries` is walked until one answers. Every row carries its own `country`, so nothing is mislabelled, and the run summary lists exactly which apps were served from elsewhere.
- **A blank run fails instead of pretending.** If nothing comes back anywhere, the Actor asks Apple's chart feed whether Apple is up, then **fails with that finding** rather than handing you an empty dataset that looks like an answer. You are charged per review, so a failed run costs you nothing.
- **The default is three apps, not one.** A single-app run is all-or-nothing against a feed that behaves like this; a small basket almost always returns something.

Apple also publishes at most **500 reviews per app per country**, a hard limit of the source. If you need more volume for one app, add more countries.

### Pricing

Pay per review delivered. A run that finds no reviews charges you nothing.

### Disclaimer

This is an **unofficial** tool. It is not affiliated with, authorised by, endorsed by, or in
any way officially connected to Apple Inc. "Apple", "App Store", "iOS", "iPadOS" and "macOS"
are trademarks of Apple Inc.

It reads only Apple's **public, unauthenticated** endpoints — the iTunes Search and Lookup
APIs and the public RSS feeds. It signs into nothing, stores no credentials, and parses no
HTML. Nothing it returns is behind a login or a paywall, and every field it returns is data
the App Store already shows to anyone.

Apple can change or withdraw those endpoints at any time. When a feed returns nothing, this
Actor says so in the log rather than handing you an empty result that looks like an answer.

# Actor input Schema

## `appStoreUrlsOrIds` (type: `array`):

One or more apps. Each entry can be an App Store URL (https://apps.apple.com/us/app/notion/id1232780281), a numeric app ID (1232780281), or a bundle ID (com.burbn.instagram). Mixing formats in one list is fine. The default is three apps rather than one on purpose: Apple's review feed goes quiet for individual apps at random, so a single-app run is all-or-nothing while a small basket almost always returns something.

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

Two-letter country codes of the App Store storefronts to read. Apple keeps reviews separate per country, so add more countries to get more reviews for the same app. Examples: us, gb, de, jp, th, br.

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

How many reviews to return for each app in each country. Apple publishes at most 500 reviews per app per country, so values above 500 are capped. This is per app and per country, so the rows a run returns is roughly this number times the apps times the countries that answer — keep it small for fast, cheap runs.

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

mostRecent returns the newest reviews first, which is what you want for monitoring. mostHelpful returns the reviews Apple ranks highest, which is what you want for research.

## `fallbackCountries` (type: `array`):

Apple's review feed frequently returns nothing for an app in one country while returning reviews for the same app in another — measured on 2026-09-02, four major apps returned 0 reviews in the US and three of them returned 50 in GB, CA or AU. When an app yields nothing in every country you asked for, these storefronts are tried in order until one answers. Every row carries its real country, so nothing is mislabelled. Set to an empty list to switch this off and get a hard failure instead.

## Actor input object example

```json
{
  "appStoreUrlsOrIds": [
    "https://apps.apple.com/us/app/notion/id1232780281",
    "544007664",
    "com.burbn.instagram"
  ],
  "countries": [
    "us",
    "gb",
    "jp"
  ],
  "maxReviewsPerApp": 50,
  "sortBy": "mostRecent",
  "fallbackCountries": [
    "gb",
    "ca",
    "au",
    "de"
  ]
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per review: text, rating, author, app version, country and the app it belongs to.

## `summary` (type: `string`):

What was requested, what was delivered, and per-app counts — useful for checking a run without reading every row.

# 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 = {
    "appStoreUrlsOrIds": [
        "https://apps.apple.com/us/app/notion/id1232780281",
        "310633997",
        "363590051"
    ],
    "countries": [
        "us"
    ],
    "maxReviewsPerApp": 50,
    "sortBy": "mostRecent",
    "fallbackCountries": [
        "gb",
        "ca",
        "au",
        "de"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("appdata-labs/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 = {
    "appStoreUrlsOrIds": [
        "https://apps.apple.com/us/app/notion/id1232780281",
        "310633997",
        "363590051",
    ],
    "countries": ["us"],
    "maxReviewsPerApp": 50,
    "sortBy": "mostRecent",
    "fallbackCountries": [
        "gb",
        "ca",
        "au",
        "de",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("appdata-labs/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 '{
  "appStoreUrlsOrIds": [
    "https://apps.apple.com/us/app/notion/id1232780281",
    "310633997",
    "363590051"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 50,
  "sortBy": "mostRecent",
  "fallbackCountries": [
    "gb",
    "ca",
    "au",
    "de"
  ]
}' |
apify call appdata-labs/app-store-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,appdata-labs/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/c2rL0UIrTjp1sTGJJ/builds/FWCvh3WcdieBol5ac/openapi.json
