# App Store Reviews Scraper & Change Monitor (`luminar/app-store-reviews-change-monitor`) Actor

Export Apple App Store reviews with ratings, review text, app versions and country coverage. Track new and updated feedback with stable keys for repeatable exports.

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

## Pricing

from $0.08 / 1,000 review delivereds

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

Turn App Store feedback into a review export you can use for release analysis, product research and customer support. Keep the original text, compare countries and follow newly observed or edited reviews over time.

- Export ratings, titles, full review text, app versions and helpfulness votes.
- Check multiple apps and countries with clear coverage for every target.
- Add **NEW** and **UPDATED** records to repeat runs, with stable keys for spreadsheets and automation.

### 🚀 Start in 60 seconds

1. Leave the default Spotify app and US storefront to try 100 reviews, or paste your own App Store URL, numeric ID or bundle ID.
2. Choose **Export current reviews** and press **Start**.
3. Open the results Dataset, then export JSON, CSV or Excel. The `recordType` column identifies reviews, changes and coverage rows.

```json
{"apps":["324684580"],"countries":["us"],"maxReviewsPerApp":100,"maxReviews":100}
```

This default costs **$0.0125 when 100 reviews are delivered for one verified app-country pair**. A verified empty check costs $0.005. An unavailable or unverified target has no check fee. Set the run's maximum total charge for a spending cap.

### 🎯 Choose the right workflow

| Your task | Workflow | Result |
|---|---|---|
| Analyze current feedback | Export current reviews | Current review rows and coverage |
| Watch releases or competitors | Track new and updated reviews | Current reviews plus included NEW and UPDATED records |

The first run creates a baseline for your watch. Later runs compare current review observations with that baseline.

For monitoring, keep the same watch name, apps, countries, sort order, filters and limits between runs. A changed scope starts a separate baseline. **Create baseline without change records** still exports and bills the current reviews; it only suppresses the first batch of NEW records.

### 📦 What you get

Each review includes `stableId`, `reviewId`, `appId`, `country`, `rating`, `title`, `text`, `date`, `version`, `userName`, `userUrl`, `reviewUrl`, `voteCount` and `voteSum`. App name, developer and bundle ID are added when published and available. Secondary fields can be empty.

Change rows include `changeKind`, `changeId`, the current review and `previousContentHash`. Use `stableId` to maintain one row per review and `changeId` to deduplicate a delivered change event. NEW means newly observed in this watch; it does not guarantee that the review was just published. UPDATED means its text, title, rating, associated app version or date changed.

Coverage rows show the target, checked and delivered counts, status and a short explanation. They are included without an additional row charge. `parentId` retains the source review identity and does not imply a developer-response thread.

![App Store review output sample](https://api.apify.com/v2/key-value-stores/DJgPR6wwS2tIaLDQW/records/app_store_reviews--d4efd2dbfef6526474a7-output.png)

### 🎛️ Input guide

| Input | Purpose |
|---|---|
| `apps` | 1–50 numeric IDs, App Store URLs or bundle IDs |
| `countries` | 1–20 two-letter storefront codes; applies to every app, including pasted URLs |
| `sort` | `mostRecent` or `mostHelpful`; order is within each app-country pair |
| `maxReviewsPerApp` | 1–500 reviews per app and country |
| `maxReviews` | 1–25,000 current reviews for the whole run |
| `since` | Optional ISO date; exclude older reviews before delivery |
| `minRating`, `maxRating` | Include a range of star ratings from 1 to 5 |
| `includeAppMetadata` | Include app name, developer and bundle ID when available |
| `workflow` | `export` or `monitor` |
| `firstRunBehavior` | `emit_current_as_new` or `seed_only` |
| `stateNamespace` | Your watch name; up to 25,000 retained review identities |
| `maxBuyerChargeUsd` | Maximum charge you allow; the requested maximum must fit before collection starts |
| `maxRuntimeSecs` | 10–60 seconds for collection, followed by time to save results |

For critical recent feedback, set a date and `maxRating: 2`. Reviews excluded by filters have no per-review charge; the verified app-country check is still charged. For a broader export, raise both review limits and the spending cap.

### 💰 Pricing

All Apify plan tiers use the same price:

- **$0.005 per verified app-country check**, including verified checks that return no matching reviews.
- **$0.000075 per current review delivered** ($0.075 per 1,000 reviews).
- Monitoring change records and coverage rows are included.

| Complete run | Buyer charge |
|---|---:|
| 1 app, 1 country, no matching reviews | $0.005 |
| 1 app, 1 country, 100 reviews | $0.0125 |
| 1 app, 1 country, 300 reviews | $0.0275 |
| 1 app, 1 country, 500 reviews | $0.0425 |
| 10 apps, 1 country, 500 reviews each | $0.425 |

Formula: `0.005 × verified app-country checks + 0.000075 × current reviews delivered`.

Unchanged reviews are checked and returned on repeat monitoring runs, so they retain the normal review charge. Only the additional change records are free. Charges do not include extra platform-usage pass-through. A run that cannot verify any requested target has no Actor event charge. A partial run charges only verified targets and delivered reviews.

### ✅ Coverage you can trust

The public review window is limited to **up to 500 available reviews per app per country**. That window can differ between countries and sort orders. It is not a lifetime archive. Check the returned coverage before interpreting a count.

- **COMPLETE**: the checked available review window ended.
- **FILTERED**: the checked window ended and rating or date filters excluded reviews.
- **EMPTY\_CONFIRMED**: a valid review window contained no matching reviews.
- **CAPPED**: a requested limit or the source review window was reached.
- **PARTIAL**: some useful results were verified, but collection was incomplete.
- **BLOCKED / FAILED / NOT\_VISITED**: the requested target was not successfully checked.

Missing reviews are **never marked deleted**. An older review may simply fall outside the available window. Incomplete targets preserve prior monitoring observations. Delivery confirmation comes before the saved watch advances; an uncertain interrupted delivery stops for recovery rather than silently skipping or rebilling records.

### 🔌 API and automation

Start this Actor through the Apify API with the same JSON input. Retrieve its default Dataset, then filter `recordType` for reviews, changes or coverage. The output also links to a run summary.

```javascript
const run = await client.actor('luminar/app-store-reviews-change-monitor').call({
  workflow: 'monitor', apps: ['324684580'], countries: ['us'],
  stateNamespace: 'release-watch', maxReviewsPerApp: 100, maxReviews: 100
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Send review rows to your spreadsheet using `stableId` as an update key. Send NEW and UPDATED records to your existing alert workflow using `changeId`. Schedule serial runs after checking your first useful export. Monitoring uses a named persistent storage in your account and therefore requires full Actor permissions. It does not need an Apple account.

### ⚠️ Not yet supported

No complete historical archive beyond the available public review window, app discovery by keyword, developer responses, review deletion inference, automatic sentiment scores or review posting. Large inputs can be capped by the collection time or output-size limit; 25,000 is an output ceiling, not a promise that every live run reaches it. US recent reviews and GB helpful reviews are the initial live verification targets; other valid storefront codes depend on Apple's availability and are reported individually.

Do not overlap monitoring runs. Keep a watch below 25,000 remembered review identities; start a new watch name when you need a new baseline. Review text is returned as published. This Actor does not infer reviewer identities, contact details or private account information.

### ❓ FAQ and support

**Can I monitor my competitors?** Yes, provide their public App Store IDs or URLs. No Apple login is needed.

**Why are there fewer reviews than the app's rating count?** Ratings without written reviews and reviews outside the available country window are not returned. A filter or limit can further reduce the output.

**Does a zero-result check cost anything?** A verified app-country check costs $0.005 even when filters leave no reviews. An unavailable or unverified target is free.

**Does monitoring charge only for changes?** It charges for the current reviews checked and delivered. The additional NEW and UPDATED records are included.

**How do I report a problem?** Open an Actor issue with the run ID, app ID, country and expected result. Avoid sharing account secrets. For interrupted monitoring delivery, keep the original run so its saved acknowledgement can be checked.

This independent tool is not affiliated with or endorsed by Apple Inc. App Store and Apple are trademarks of Apple Inc.

# Actor input Schema

## `workflow` (type: `string`):

Export reviews once, or keep a named watch that adds change records on repeat runs.

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

One app per line. Example: 324684580, https://apps.apple.com/us/app/spotify/id324684580, or com.spotify.client. Up to 50 apps.

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

Two-letter country codes, for example us, gb, de. This list applies to every app, including pasted URLs. Up to 20 countries.

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

Choose the review order within each app and country. Monitoring works within the selected review window.

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

Up to 500 available reviews for each app and country. This is a source window, not a full historical archive.

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

Total review limit across all apps and countries. Start with 100; raise it for larger exports.

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

Optional ISO date, for example 2026-09-01. Older reviews are excluded before delivery. Leave blank for the available window.

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

Lowest rating to include, from 1 to 5. Filtered-out reviews are not billed.

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

Highest rating to include. Set 1 or 2 to focus on critical feedback.

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

Adds published app name, developer and bundle ID when available. Missing metadata stays empty; review identity remains available.

## `firstRunBehavior` (type: `string`):

Both options export and bill current checked reviews. This setting only changes whether the first run also returns NEW change records.

## `stateNamespace` (type: `string`):

Keep this name and the same apps, countries, sort, filters and limits on repeat runs. Use a new name to start a separate watch. Up to 25,000 remembered reviews.

## `maxBuyerChargeUsd` (type: `number`):

The run checks that your budget can cover the requested app-country checks and review limit before collection. Also set Apify maximum total charge.

## `maxRuntimeSecs` (type: `integer`):

Limits review collection to 10–60 seconds, with additional time reserved for saving results. Large runs may report partial or capped coverage.

## Actor input object example

```json
{
  "workflow": "export",
  "apps": [
    "324684580"
  ],
  "countries": [
    "us"
  ],
  "sort": "mostRecent",
  "maxReviewsPerApp": 100,
  "maxReviews": 100,
  "since": "",
  "minRating": 1,
  "maxRating": 5,
  "includeAppMetadata": true,
  "firstRunBehavior": "emit_current_as_new",
  "stateNamespace": "default",
  "maxBuyerChargeUsd": 1,
  "maxRuntimeSecs": 60
}
```

# Actor output Schema

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

The default Dataset contains review, change and coverage records.

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

Summary of verified reviews, included changes, expected charge and each requested target.

# 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 = {
    "workflow": "export",
    "apps": [
        "324684580"
    ],
    "countries": [
        "us"
    ],
    "sort": "mostRecent",
    "maxReviewsPerApp": 100,
    "maxReviews": 100,
    "since": "",
    "minRating": 1,
    "maxRating": 5,
    "includeAppMetadata": true,
    "firstRunBehavior": "emit_current_as_new",
    "stateNamespace": "default",
    "maxBuyerChargeUsd": 1,
    "maxRuntimeSecs": 60
};

// Run the Actor and wait for it to finish
const run = await client.actor("luminar/app-store-reviews-change-monitor").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 = {
    "workflow": "export",
    "apps": ["324684580"],
    "countries": ["us"],
    "sort": "mostRecent",
    "maxReviewsPerApp": 100,
    "maxReviews": 100,
    "since": "",
    "minRating": 1,
    "maxRating": 5,
    "includeAppMetadata": True,
    "firstRunBehavior": "emit_current_as_new",
    "stateNamespace": "default",
    "maxBuyerChargeUsd": 1,
    "maxRuntimeSecs": 60,
}

# Run the Actor and wait for it to finish
run = client.actor("luminar/app-store-reviews-change-monitor").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 '{
  "workflow": "export",
  "apps": [
    "324684580"
  ],
  "countries": [
    "us"
  ],
  "sort": "mostRecent",
  "maxReviewsPerApp": 100,
  "maxReviews": 100,
  "since": "",
  "minRating": 1,
  "maxRating": 5,
  "includeAppMetadata": true,
  "firstRunBehavior": "emit_current_as_new",
  "stateNamespace": "default",
  "maxBuyerChargeUsd": 1,
  "maxRuntimeSecs": 60
}' |
apify call luminar/app-store-reviews-change-monitor --silent --output-dataset

```

## MCP server setup

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

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/UFaTpmXZivB4cdWaf/builds/Y6AehBYQmleP6JcdB/openapi.json
