# Apple App Store Reviews Scraper (`lightmoon/apple-app-store-reviews-scraper`) Actor

Export Apple App Store reviews for any iOS app to CSV, Excel or JSON: stars, title, text, date, reviewer, app version and helpful votes, plus the app's rating and rating count on every row. Pick countries, filter by stars and date. $0.09 per 1,000 reviews, empty apps free.

- **URL**: https://apify.com/lightmoon/apple-app-store-reviews-scraper.md
- **Developed by:** [Stable](https://apify.com/lightmoon) (community)
- **Categories:** Developer tools, Marketing, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.09 / 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

> **Unofficial.** This Actor is not affiliated with, endorsed by or sponsored by Apple. It reads only what the App Store publishes to any visitor through its public feeds, does not log in and does not bypass any access control. All product names and trademarks belong to their respective owners.

### One row of output

Paste app ids or App Store links, name the countries; get one flat table of
reviews. This is a real row from a real run, not a mock-up:

```json
{
  "store": "app-store",
  "appId": "284882215",
  "appTitle": "Facebook",
  "developer": "Meta Platforms, Inc.",
  "reviewId": "14573977320",
  "score": 4,
  "title": "A good way to lose track of time",
  "text": "With everyone's busy lives going on, Facebook is still one of the best way to keep in touch with friends and family you don't see often. My biggest problem is putting it down, Hence the four stars.",
  "reviewedAt": "2026-09-20T22:07:29Z",
  "authorName": "Spicelady2",
  "authorId": "1578663174",
  "thumbsUp": 0,
  "appVersion": "579.0.0",
  "country": "us",
  "appUrl": "https://apps.apple.com/us/app/facebook/id284882215",
  "appRating": 4.526,
  "appRatingCount": 28432878,
  "category": "Social Networking"
}
```

**The app's own figures ride on every row** — name, developer, category,
average rating and rating count for the storefront the review came from — so
a sheet of reviews from fifty apps in ten countries sorts and pivots without
a second export.

### What you get

**19 columns per row**, all flat — one CSV, no nested cells to unpick.

| | |
|---|---|
| The review | `reviewId`, `score` (1–5), `title`, `text`, `reviewedAt` (UTC, to the second), `thumbsUp`, `appVersion` |
| Who wrote it | `authorName`, `authorId` |
| The app | `appId`, `appTitle`, `developer`, `category`, `appRating`, `appRatingCount`, `appUrl` |
| Where it came from | `store`, `country`, `scrapedAt` |

Export to CSV, Excel, JSON or read it from the API. No Apple account, no API
key, no cookies.

### Three things this does that are worth knowing

**1. Several countries in one run.** The App Store keeps reviews per
storefront. Name `["us", "gb", "de", "jp"]` and the run reads each one, with
`country` on every row and the app's rating for that storefront beside it.

**2. A daily watch costs only the new reviews.** Reviews come newest first,
and with `reviewedAfter` set the run stops reading the moment it reaches your
date. Schedule it, and a quiet day for an app is a few cents.

**3. Nothing is guessed, nothing empty is billed.** A field the store did not
publish comes back empty — never `"N/A"`. An app id the store has nothing for,
a storefront with no reviews, a review outside your stars or dates, and a
duplicate are all free, and the run summary says how many of each there were.

### Input

```json
{
  "apps": ["284882215", "https://apps.apple.com/us/app/notion-notes-docs-tasks/id1232780281"],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 500,
  "scores": ["1", "2"],
  "reviewedAfter": "2026-09-01",
  "includeAppDetails": true
}
```

Apps are accepted as a numeric id (`284882215`) or any App Store link
carrying `/id<number>`. Up to 500 apps and 40 countries per run.
`maxReviewsPerApp` counts across all the countries you named.

### Price

**$0.09 per 1,000 reviews** on the Store card. A typical run — 5 apps, 3
countries, 200 reviews each — is 3,000 rows for **$0.27**.

Everything on the row is included at that price, the app's own figures too.
There is no per-run start fee and no second event, so an app with nothing to
return costs $0.

**Free plan:** runs work in full, with no feature held back. The $5 of monthly
platform credit on a free Apify plan covers roughly 7,000 reviews.

### Limits, stated plainly

- **500 most recent reviews per app per country.** That is the size of the
  App Store's public feed and it cannot be widened. For more, name more
  countries — each storefront has its own 500 — or run on a schedule with
  `reviewedAfter` and keep the history yourself.
- **No developer replies.** Apple does not publish them in the feed this
  Actor reads. The Google Play listing on the same engine does return them.
- **Newest first is the only order** the feed offers, so there is no "most
  helpful" sort; `thumbsUp` is on every row for sorting after export.
- **Star filtering happens after fetching** — the feed has no filter of its
  own — so asking for 1-star reviews still reads the pages; the rows it drops
  are free.
- **Reviews arrive 50 at a time, and Apple's feed has bad hours.** Its server
  answers a page empty at random — measured at 4 answers in 10 on a normal
  day and 9 in 10 on a bad hour. The run asks each page again, up to twelve
  times with growing pauses, before believing it; on a bad hour a storefront
  can still come back short, and the run summary names every page it gave up
  on (`pagesGivenUp`) so a short storefront is never mistaken for an app with
  few reviews. Rows that never arrived are never charged. A run for 3,000
  reviews takes a minute on a good day and a few minutes on a bad one.
- This reads what the App Store shows to a visitor. Reviews the reviewer
  deleted or the store hid are not visible and are not returned.

### Typical uses

- Pull the 1- and 2-star reviews of your own app across your top markets
  since the last release, and group by `appVersion`.
- Compare five competing apps in three countries: reviews with `appRating`,
  `appRatingCount` and `developer` on every row, ready for a pivot table.
- Watch a list of apps daily with `reviewedAfter` set to yesterday and get
  only what is new.
- Feed a sentiment or topic model with clean titled text and a star label per
  row, per country.
- Pair with the Google Play listing on the same engine and compare the same
  app's iOS and Android reviews in one table — the columns match.

### FAQ

#### How much does it cost to scrape 10,000 reviews?

$0.90 at the Store card rate, plus nothing else — no start fee, no per-page
charge. A run that finds fewer reviews than you asked for charges only for
the rows it stored.

#### Can I get all reviews of an app?

The store publishes the 500 most recent per country. Twenty countries give up
to 10,000 in one run; for the full history over time, schedule a daily run
with `reviewedAfter` and append.

#### Which countries can I use?

Any App Store storefront, as a two-letter code: `us`, `gb`, `ca`, `au`, `de`,
`fr`, `es`, `it`, `br`, `mx`, `jp`, `kr`, `in`, `cn` and the rest. A
storefront where the app is not sold comes back empty and free.

#### Why did an app come back with no rows?

Either the id has no listing on the storefronts you named, or the store has
no reviews there yet. The run summary names the app and the storefront either
way, and nothing was charged.

# Actor input Schema

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

One per line. A numeric app id (284882215) or the app's App Store link (https://apps.apple.com/us/app/facebook/id284882215) both work. The id is the number after /id in any App Store URL.

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

App Store storefronts to read, as two-letter codes: us, gb, de, jp, br... Each storefront has its own reviews in its own language; the row says which one it came from. Up to 40 per run.

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

How many reviews to return for each app, newest first, across all the countries you named. The store publishes at most 500 recent reviews per app per country, so 3 countries means up to 1,500.

## `scores` (type: `array`):

Only reviews with these star ratings. Leave empty for all. Reviews outside your choice are dropped before billing and never charged.

## `reviewedAfter` (type: `string`):

Skip reviews older than this date. Reviews come newest first, so the run stops reading as soon as it reaches the date - a daily watch of new reviews costs only the new ones.

## `includeAppDetails` (type: `boolean`):

Adds the app's name, developer, category, average rating and rating count to each review. One small lookup per app per country. Turn off for the smallest possible rows.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/facebook/id284882215"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 100,
  "includeAppDetails": true
}
```

# Actor output Schema

## `reviews` (type: `string`):

No description

## `all` (type: `string`):

No description

# 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": [
        "https://apps.apple.com/us/app/facebook/id284882215"
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lightmoon/apple-app-store-reviews-scraper").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": ["https://apps.apple.com/us/app/facebook/id284882215"],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("lightmoon/apple-app-store-reviews-scraper").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": [
    "https://apps.apple.com/us/app/facebook/id284882215"
  ],
  "countries": [
    "us"
  ]
}' |
apify call lightmoon/apple-app-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lightmoon/apple-app-store-reviews-scraper"
        }
    }
}
```

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/uztZGdRZL1gh1idUv/builds/AhhIIyDg5E6jvqQIT/openapi.json
