# App Store Reviews Scraper \[FAST] | iOS Ratings & Reviews (`apizy/apple-app-store-reviews-scraper`) Actor

Scrape Apple App Store reviews from up to 100 iOS apps. Get ratings, text, dates, and reviewer names; filter by stars or date. Results are newest within the scanned sample. Pay $0.0001 per saved review ($0.10/1,000); failed or empty results have no review charge. Actor Start and usage are separate.

- **URL**: https://apify.com/apizy/apple-app-store-reviews-scraper.md
- **Developed by:** [Apizy](https://apify.com/apizy) (community)
- **Stats:** 2 total users, 1 monthly users, 60.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.10 / 1,000 review scrapeds

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

## Apple App Store Reviews Scraper

Turn public App Store reviews into structured feedback you can analyze. Enter an Apple App Store URL or numeric app ID to collect written reviews, star ratings, dates, and public reviewer names. Scrape one app or compare up to **100 apps in one run**. No browser, Apple account, or API key is required.

Use the results to understand customer complaints, spot feature requests, compare competing iOS apps, and monitor feedback after a release. Every delivered review is one row in the Dataset, ready for spreadsheets, dashboards, and automation tools.

### What does Apple App Store Reviews Scraper do?

The Actor collects public **written reviews** from the App Store storefront you choose. Each review can include:

- Star rating, review title and text, and review date
- Public reviewer name and whether Apple marks the review as edited
- App ID, App Store URL, storefront country, and scrape time

Filter the inspected reviews by an exact star rating or an inclusive date. Results are sorted **newest first within the inspected sample**. Apple supplies the source reviews in its own relevance order, so the Actor cannot guarantee the newest reviews across an app's entire history. [How sampling works](#how-review-sampling-works) explains this in detail.

#### What can you use it for?

- **Improve your app:** Find recurring bugs, confusing flows, and requested features in real customer feedback.
- **Research competitors:** Compare what users praise and complain about across similar iOS apps.
- **Watch a release:** Filter reviews by date to inspect feedback found after an update or launch.
- **Prioritize support:** Focus on one-star or two-star reviews to identify common problems.
- **Find an app idea:** Look for unmet needs in competitors' reviews before building an MVP.
- **Support AI-assisted development:** Give a coding assistant review excerpts to draft user stories, feature briefs, or bug-fix plans grounded in user feedback.
- **Automate feedback analysis:** Send review rows to Make, n8n, Zapier, a spreadsheet, or your own pipeline.

### How to use

1. Enter one App Store URL or numeric ID in **App Store URL or app ID**, or enter up to 100 under **Apps**.
2. Choose the **Store country** and **Maximum reviews per app**. The defaults are `us` and 100.
3. Optionally open **Advanced options** to filter by star rating or date, or inspect a wider review sample.
4. Click **Run**. Open **Dataset** for review rows and **Output** for the run summary and per-app counts.

For example, `866450515` and `https://apps.apple.com/us/app/forest-focus-for-productivity/id866450515` identify the same app. Use **either** `app` **or** `apps` in JSON input, not both. Duplicate IDs or URLs for the same app are processed once.

### Input examples

#### Collect reviews for one app

```json
{
  "app": "866450515",
  "country": "us",
  "maxReviews": 100
}
```

This requests up to 100 written reviews for Forest from the US storefront. The Actor automatically inspects up to 200 source reviews, then saves the 100 newest **found in that sample**. It may return fewer if fewer reviews are available.

#### Compare several apps

```json
{
  "apps": [
    "https://apps.apple.com/us/app/daylio-journal-mood-tracker/id1194023242",
    "1445651730"
  ],
  "country": "us",
  "maxReviews": 50
}
```

`maxReviews` applies **per app**. Two apps with `maxReviews: 50` can produce up to 100 Dataset rows. Every row has an `appId`, so you can group or compare the results.

#### Investigate recent one-star reviews

```json
{
  "app": "866450515",
  "country": "us",
  "maxReviews": 100,
  "starRating": 1,
  "sinceDate": "2026-10-01",
  "scanLimit": 500
}
```

This inspects up to 500 source reviews and saves up to 100 one-star reviews dated October 1, 2026 or later. The date is inclusive from midnight UTC. Apple does **not** provide a reliable global newest-first feed, so this filter applies only to the inspected sample and may return fewer reviews than requested.

#### Input fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `app` | string | None | One numeric App Store ID or `apps.apple.com` URL. Required when `apps` is omitted. |
| `apps` | array of strings | None | 1–100 IDs or App Store URLs. Required when `app` is omitted. |
| `country` | string | `"us"` | Two-letter storefront code, such as `"us"`, `"gb"`, `"au"`, or `"sg"`. It does not translate review text or verify reviewer location. |
| `maxReviews` | integer | `100` | Maximum saved reviews **per app**, from 1 to 500. |
| `scanLimit` | integer | Automatic | Optional advanced setting: inspect from `maxReviews` to 5,000 source reviews per app. When omitted, the limit is the greater of 200 and `maxReviews`. |
| `starRating` | integer | None | Optional advanced filter for exactly 1–5 stars. |
| `sinceDate` | string | None | Optional advanced inclusive UTC cutoff in `YYYY-MM-DD` format, applied within the inspected sample. |

#### Which inputs should you use?

| Goal | Input | Result |
| --- | --- | --- |
| Explore feedback for an app | `app`, `maxReviews` | Reviews sorted by date within the inspected sample |
| Compare competing apps | `apps: [...]` | One Dataset with an `appId` on each review |
| Investigate low ratings | `starRating: 1` or `2` | Only reviews with that exact rating in the sample |
| Check feedback since a release | `sinceDate: "YYYY-MM-DD"` | Matching sampled reviews on or after that UTC date |
| Broaden coverage | Increase `scanLimit` | More source reviews inspected; the run may take longer |

These are input combinations, not separate modes. Each run is independent; `sinceDate` does not remember previous runs.

### How review sampling works

Apple returns reviews in a relevance-based source order. The Actor inspects a bounded number of them, removes duplicates, applies your filters, sorts the matching sample by date, and saves up to `maxReviews` per app. The default inspection limit is **200 reviews per app**, or `maxReviews` if it is higher.

For example, `maxReviews: 50` with no `scanLimit` inspects up to 200 source reviews and saves up to 50 of the newest reviews **among those 200**. A larger `scanLimit` can find additional or newer matching reviews, but it cannot guarantee complete coverage of an app's review history. When Apple has fewer reviews available, the Actor saves only what it finds.

The effective `scanLimit`, `scannedCount`, `matchedCount`, and `successCount` appear in `OUTPUT`. A date filter scans the full selected sample; the Actor does not stop at an old review because newer reviews may appear later in Apple's relevance order. There is no `sortBy` input because Apple does not provide a reliable global newest or most-helpful ordering through this source.

### Output

Every saved review is **one item in the default Dataset**. The run summary is stored separately as `OUTPUT` in the default Key-Value Store; it does not contain the review rows.

**Example Dataset item** (illustrative values):

```json
{
  "reviewId": "14612345678",
  "appId": "866450515",
  "appUrl": "https://apps.apple.com/us/app/id866450515",
  "rating": 4,
  "title": "Helps me focus",
  "text": "The timer keeps me on track. I would like more reminder options.",
  "date": "2026-10-12T14:30:00.000Z",
  "reviewerName": "App user",
  "isEdited": false,
  "country": "us",
  "source": "apple-web-reviews",
  "scrapedAt": "2026-10-27T07:00:00.000Z"
}
```

| Dataset field | Description |
| --- | --- |
| `reviewId` | Apple's review ID, useful for deduplication across runs |
| `appId`, `appUrl` | Numeric app ID and link to its App Store page |
| `rating`, `title`, `text` | Star rating and written feedback; title or text can be `null` when unavailable |
| `date` | Review date returned by Apple, as a UTC timestamp |
| `reviewerName`, `isEdited` | Public reviewer name and edited flag, when available |
| `country` | Storefront requested in the input, not verified reviewer location |
| `source`, `scrapedAt` | Data source label and time the row was collected |

**Example `OUTPUT` summary** (shortened):

```json
{
  "summary": {
    "appIds": ["866450515"],
    "country": "us",
    "maxReviews": 100,
    "scanLimit": 200,
    "order": "newest_within_scanned_sample",
    "successCount": 100,
    "chargedCount": 100,
    "scannedCount": 200,
    "matchedCount": 200,
    "failedCount": 0,
    "stopReason": "max_reviews",
    "apps": [
      {
        "appId": "866450515",
        "status": "succeeded",
        "successCount": 100,
        "scannedCount": 200,
        "matchedCount": 200,
        "stopReason": "max_reviews"
      }
    ]
  }
}
```

`successCount` is the number of review rows saved. `chargedCount` is the number of `review-scraped` events charged for those rows. `failedCount` counts **apps**, not reviews. If one app in a batch fails, other apps can still return results; check `summary.apps` for each app's status and error.

| Stop reason | Meaning |
| --- | --- |
| `max_reviews` | The requested row limit was reached within the sample; the app may have more reviews. |
| `scan_limit` | The inspection limit was reached. |
| `source_exhausted` | Apple returned no further review page. |
| `no_reviews` | No written reviews were returned. |
| `no_matching_reviews` | Reviews were found, but none matched the selected filters. |
| `completed` | All apps in a multi-app run finished. |
| `partial_failure` | At least one app failed; successful rows from other apps were kept. |
| `spending_limit` | The run reached its event-charge limit; later apps may be skipped. |

### Pricing

Pay **$0.0001 per review saved** to the Dataset ($0.10 per 1,000 reviews). Review events are charged only for delivered rows. If an app fails or matches no reviews, it has no review-result charge; if a run ends after saving some rows, those delivered rows are still charged.

| Saved reviews | Review charges |
| ---: | ---: |
| 0 | $0 |
| 100 | $0.01 |
| 1,000 | $0.10 |
| 10,000 | $1.00 |

Apify also charges an **Actor Start event at $0.00005** and **platform usage**. Start and usage costs still apply when no reviews are saved. At more than 1 GB of allocated memory, Apify may charge more than one Start event. The table shows review charges only; see the [Pricing tab](https://apify.com/apizy/apple-app-store-reviews-scraper/pricing) for the complete current price.

### Notes

- Apple controls which public written reviews are available for each storefront. A star-rating total can be much larger than the number of written reviews the Actor can retrieve.
- `country` selects a storefront; it does not prove where the reviewer lives. Review text is not translated.
- The saved rows are sorted newest first **within the inspected sample**. They are not guaranteed to be the newest reviews across the entire App Store.
- Apple's review source does not provide developer replies, helpful-vote counts, or the reviewed app version, so these fields are not invented in the Dataset.
- Apps in a batch are processed sequentially. If one app is unavailable, other apps can still succeed; inspect `OUTPUT.summary.apps` for errors.
- For a large batch or a high `scanLimit`, choose a run timeout long enough to inspect all requested apps and pages.

### More Actors You Might Like

Built by the same Apizy team and backed by our transparent pricing philosophy: you can see which review rows were delivered, and failed or empty results have no review-result charge. Actor Start and platform usage are shown separately.

| Actor | What it helps you collect |
| --- | --- |
| [Google Play Reviews Scraper](https://apify.com/apizy/google-play-reviews-scraper) | Android app reviews, ratings, helpful votes, and developer replies |
| [Google Play Store Scraper](https://apify.com/apizy/google-play-store-scraper) | Android app search results, charts, and app details |
| [YouTube Channel Scraper V2](https://apify.com/apizy/youtube-channel-scraper-v2) | Channel stats, engagement, email, and social links |
| [YouTube Comment Scraper](https://apify.com/apizy/youtube-comment-scraper) | Comments, authors, likes, and replies from YouTube videos |

### Get in Touch

Have a question or need a custom scraping workflow? Email **apizy.studio@gmail.com**.

# Actor input Schema

## `app` (type: `string`):

One App Store URL or numeric app ID. Use either this field or Apps.

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

Up to 100 App Store URLs or numeric app IDs. Use either this field or App Store URL or app ID.

## `country` (type: `string`):

Two-letter App Store country code such as us, gb, au, or sg. Each country has its own review data; text is not translated.

## `maxReviews` (type: `integer`):

Maximum rows saved per app after filtering and sorting the scanned sample by date. This is a ceiling, not a guarantee of the newest reviews across the whole App Store.

## `scanLimit` (type: `integer`):

Optional. Leave blank to inspect at least 200 reviews automatically (or maxReviews if higher). Increase for a wider sample; more pages take longer.

## `starRating` (type: `integer`):

Optional: save only reviews with this rating from the scanned sample. Fewer rows may be returned than requested.

## `sinceDate` (type: `string`):

Optional inclusive UTC date (YYYY-MM-DD). Only matching reviews in the scanned sample are saved and charged. Apple's source is not chronological, so this does not cover all newer reviews.

## Actor input object example

```json
{
  "app": "866450515",
  "country": "us",
  "maxReviews": 5
}
```

# Actor output Schema

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

Dataset containing one item per review.

## `output` (type: `string`):

Input, per-app counts, source page counts, errors, and stop reason.

# 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 = {
    "app": "866450515",
    "maxReviews": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("apizy/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 = {
    "app": "866450515",
    "maxReviews": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("apizy/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 '{
  "app": "866450515",
  "maxReviews": 5
}' |
apify call apizy/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,apizy/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/takhTBkX4LBYDdtT2/builds/23AbhYj9qVpPJFVav/openapi.json
