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

Scrape App Store reviews for any app and country, from app links or IDs: rating, title, text, author, date, developer reply, app version when given. Full history, four sorts, filters by rating, date and keyword.

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

## Pricing

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

## Apple App Store Reviews Scraper & API

Get the reviews of any app on the Apple App Store, in bulk, without an account or API key. Give it app links or IDs and
one or more countries. Each review comes back with its rating, title, text, author name as shown in the store, date
and the developer's reply when there is one, plus the app version and votes when the store gives them. Full history, four sorts, and filters by rating,
date and keyword. Export as JSON, CSV or Excel, or read it through the Apify API.

**$0.10 per 1,000 reviews**, plus a small start fee per run. Reviews that do not match your filters, repeats and inputs
that fail are not charged, and each review is charged once per run at most.

### Quick start

1. Paste app links (`https://apps.apple.com/us/app/whatsapp-messenger/id310633997`) or app IDs into **App links or IDs**.
2. Pick the **Countries** (each country has its own reviews) and **Max reviews per app and country**.
3. Click **Start** and read the reviews in the run's **Output** tab.

Like any Apify Actor, it can also be run and read through the Apify API, scheduled, and connected to webhooks, Make,
Zapier, n8n or Apify's MCP server for AI agents.

### What it is used for

- **Product feedback**: what users of your app (or a competitor's) complain about or love, with the app version.
- **Release monitoring**: newest reviews since a date, run every day, to catch a bad release early.
- **Support**: reviews with a low rating that still have no developer reply.
- **Market research**: the same question across countries, or across the apps of a category.
- **AI agents and sentiment analysis**: one clean record per review, the same fields on every store.

### What you get

| | |
|---|---|
| Review ID (stable: use it to deduplicate between runs) | yes |
| Rating, title, text | yes |
| Author name, as shown publicly in the store | yes |
| Date (UTC, ISO 8601) and whether the review was edited | yes |
| App version the review was written for | only when the store gives it: part of the most recent reviews, often none |
| Helpful votes and total votes | same as the app version |
| Developer reply and its date | yes, when there is one |
| App name, store page, country | yes |
| Position in the chosen sort | yes |

The same field names are used by our [Google Play Reviews Scraper](https://apify.com/quarra/google-play-store-reviews-scraper),
so you can mix both stores in one pipeline. A field a store does not give is `null`, never missing.

### Inputs

- **App links or IDs**: store links in any language or plain numeric IDs (`310633997` or `id310633997`). Up to 500 app and country pairs per run.
- **Countries**: two-letter codes, one per line (`us`, `fr`, `gb`, `de`…). Each app is read in each country. Left empty,
  the country of the link is used, otherwise `us`.
- **Max reviews per app and country** and **Max reviews in total**: counted exactly.
- **Sort**: newest first, most helpful, most favorable, most critical. Only "newest first" lets **Since** stop early.
- **Minimum rating**, **Maximum rating**, **Since**, **Until** (a date such as `2026-01-31`, or a duration such as `30 days`), and
  **Review contains** (up to 50 words, one per line). Ratings are whole stars. With a date filter, the rare reviews
  that have no date are left out.

Example, through the API:

```json
{
  "apps": ["https://apps.apple.com/us/app/whatsapp-messenger/id310633997"],
  "countries": ["us", "gb"],
  "sort": "newest",
  "maxRating": 2,
  "since": "30 days",
  "maxReviewsPerApp": 500,
  "maxItems": 1000
}
```

### Output

One record per review in the dataset. A shortened review:

```json
{
  "type": "review",
  "status": "ok",
  "platform": "apple",
  "reviewId": "14670930642",
  "appId": "310633997",
  "appName": "WhatsApp Messenger",
  "country": "us",
  "language": null,
  "rating": 5,
  "title": "Five star",
  "text": "This is a good app cause it has really good features so that is why it is a five star.",
  "author": "diego2817h",
  "authorImageUrl": null,
  "date": "2026-10-15T20:41:40Z",
  "isEdited": false,
  "appVersion": "26.40.77",
  "helpfulVotes": 0,
  "totalVotes": 0,
  "replyText": null,
  "replyAuthor": null,
  "replyDate": null,
  "reviewUrl": null,
  "appUrl": "https://apps.apple.com/us/app/id310633997",
  "input": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
  "position": 1,
  "scrapedAt": "2026-10-17T06:24:02Z"
}
```

- `status`: `ok` (delivered, charged) or `error` (free; `errorCode` and `error` say why, `retryable` says if a later run
  may work). An app that is not in a country's store gets a free `app_not_found` record.
- `position` is the rank of the review in the chosen sort for that app and country.
- `language`, `authorImageUrl`, `replyAuthor` and `reviewUrl` are kept for the shared layout and are `null` on this store.

The run summary (counts per app, name, rating, why the run stopped, notes) is the `OUTPUT` record of the run's
key-value store.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| Review | $0.10 per 1,000 |
| Run start | $0.0006 per GB of memory (1 GB minimum; $0.0006 at the default 256 MB) |

Never charged: reviews that do not match your filters, error records, repeats (a review already delivered in the
same run is skipped). Set **Maximum cost per run** in the run
options and the run stops before going over it, with the reviews delivered so far.

### Limits

- **Version and votes are rare.** The App Store gives them only for part of the most recent reviews of each country, and
  for many big apps for none (we checked in October 2026). Reviews without them have `null`, and the `note` of each app
  says how many of the reviews delivered have them.
- **Reviews are per country.** An app has a separate set of reviews in each country's store; ask for every country you
  need.
- **Filters on rating and words are applied while reading**: the run reads reviews to find the ones that match. With the
  "newest first" sort, a date range is found directly, even years back. Reading that finds nothing has a limit per
  run (it is not charged); a very rare word on a big app can reach it, and the run says how far it read. Only matching
  reviews are charged.
- The store may show fewer reviews than the app's rating count says: ratings without text are not reviews.
- Anything missing from a result is said: in the run's status, in the `note` of each app in the `OUTPUT` record (for
  example version and votes missing on some reviews), or in a free error record when an app stopped before the end.
- If the store limits access during a run, the run says so in its status and keeps what it delivered; running it again
  later gives the rest.

### FAQ

**Do I need an Apple account or API key?** No.

**What if the run is restarted by the platform (migration or reboot)?** It resumes where it was: reviews already in the
dataset are not delivered or charged again.

**Can I get reviews of an app that is not in my country?** Reviews are per country store: use the country where the app
is sold.

**Is it legal?** It collects public reviews shown to any visitor of the App Store. Check the rules that apply to your
use of the data, in particular for personal data such as author names.

**Does the Actor send anything to Quarra?** Only when a run fails or runs out of time: the Actor, its build, the error type, the line of our code where it happened, and the memory and time the run was given, so we can fix it fast. Never your input, your results, your account or the run ID.

### Related tools from Quarra

- [Google Play Reviews Scraper](https://apify.com/quarra/google-play-store-reviews-scraper): the same fields for Android
  apps, by language.

# Actor input Schema

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

One per line: App Store links (apps.apple.com/us/app/…/id310633997) or numeric app IDs.

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

Store countries, two letters, one per line (us, fr, gb, de…). App Store reviews belong to a country: each app is read in each country. Empty: the country of the link, otherwise us. Up to 500 app and country pairs per run.

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

Stop an app after this many reviews (per country).

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

Stop the run after this many reviews, all apps together.

## `sort` (type: `string`):

Order of the reviews. 'Newest first' is the one that lets 'Since' stop early.

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

Keep only reviews with at least this many stars (1 to 5). Empty keeps all. Reviews that do not match are not charged.

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

Keep only reviews with at most this many stars (1 to 5). Set both to 1 for one-star reviews only.

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

Only reviews from this date on: 2026-01-31, or a duration such as '30 days', '3 months'. Empty keeps all. With a date filter, the rare reviews that have no date are left out (not charged).

## `until` (type: `string`):

Only reviews up to this date (included). Empty keeps all.

## `keywords` (type: `array`):

Keep only reviews whose title or text contains one of these words (not case-sensitive). One per line, 50 at most.

## `proxyConfiguration` (type: `object`):

Connection. Keep the default (automatic). Costs are included in the price.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 100,
  "maxItems": 1000,
  "sort": "newest",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every review with all its fields, and free records with the reason.

## `overview` (type: `string`):

One line per review.

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

Counts per app, why the run stopped, errors.

# 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/whatsapp-messenger/id310633997"
    ],
    "countries": [
        "us"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("quarra/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/whatsapp-messenger/id310633997"],
    "countries": ["us"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("quarra/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/whatsapp-messenger/id310633997"
  ],
  "countries": [
    "us"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call quarra/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,quarra/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/SCqapSs94Bn9M3cBg/builds/LYkJPFg2XtCC4clcp/openapi.json
