# Apple App Store Review Delta API (`ursog/apple-app-store-review-delta-api`) Actor

- **URL**: https://apify.com/ursog/apple-app-store-review-delta-api.md
- **Developed by:** [andre donda de sa](https://apify.com/ursog) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 app-country monitor checkeds

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 Review Delta API

Monitor public Apple App Store review feeds and receive only meaningful changes. The first successful run saves a free baseline. Later runs emit and bill only reviews that are new, updated, or removed from the bounded feed snapshot.

This is a monitoring product, not a historical review scraper. It uses public Apple review feeds onlyÃ¢â‚¬â€no App Store Connect, account, browser, proxy, Google Play, AI, sentiment analysis, or app-name discovery.

### Quick start

1. Paste one or more public App Store URLs or numeric Apple App IDs.
2. Optionally add two-letter country codes such as `us`, `gb`, `br`, or `jp`.
3. Keep the monitor key unchanged on scheduled runs.
4. Run the Actor. The first run creates a baseline and intentionally reports no existing review as new.
5. Schedule the same input. Later runs return only review changes.

Minimal input:

```json
{
  "appStoreUrls": ["https://apps.apple.com/us/app/instagram/id389801252"],
  "monitorKey": "instagram-reviews"
}
```

When countries are omitted, the Actor uses country codes from App Store URLs. ID-only inputs default to the US storefront.

### Example change

```json
{
  "recordType": "change",
  "changeType": "updated",
  "appId": "389801252",
  "country": "us",
  "reviewId": "14411751307",
  "title": "Works after the update",
  "rating": 5,
  "version": "442.0.0",
  "reviewTextHash": "sha256...",
  "previousReview": {
    "rating": 3,
    "version": "441.0.0"
  },
  "currentReview": {
    "rating": 5,
    "version": "442.0.0"
  },
  "changes": [
    { "field": "rating", "previous": 3, "current": 5 },
    { "field": "version", "previous": "441.0.0", "current": "442.0.0" }
  ]
}
```

Every change has a deterministic event ID, stable review identity, public source URL, and observation timestamp.

### Pricing

Provisional Store pricing is **$0.002 per review change**.

A review change is one:

- new review;
- updated review; or
- review removed from the observed bounded feed.

The following are not charged:

- baseline reviews;
- unchanged historical reviews;
- empty feeds;
- duplicate inputs or duplicate changes;
- retries;
- diagnostics;
- blocked or failed monitors.

Pricing is proposed but has not been applied. The Actor has not been deployed or published.

### Inputs

| Input | Default | Purpose |
|---|---:|---|
| `appStoreUrls` | `[]` | Public `apps.apple.com` application URLs |
| `appIds` | `[]` | Numeric Apple App IDs |
| `countries` | inferred, otherwise `us` | Storefront country codes applied to every app |
| `monitorKey` | `default` | Persistent state namespace; keep unchanged between runs |
| `maxAppCountryMonitors` | `25` | Maximum app Ãƒâ€” country combinations; hard maximum 100 |
| `maxPagesPerMonitor` | `2` | Apple review pages per app-country; hard maximum 10 |
| `maxConcurrency` | `5` | Concurrent app-country acquisitions |
| `requestTimeoutSecs` | `10` | Complete request and body-stream timeout |
| `maxRequestRetries` | `1` | Temporary-failure retries |
| `maxResponseBytes` | `500000` | Streaming byte limit per Apple page |

Apple currently returns up to 50 reviews per page and rejects pages above 10. Defaults therefore observe up to 100 reviews per app-country monitor while keeping normal runs fast.

### Output

The dataset has three views:

- **Review changes** Ã¢â‚¬â€ billable new, updated, and removed-from-observed-feed events.
- **Baselines** Ã¢â‚¬â€ free first-run setup records.
- **Warnings and failures** Ã¢â‚¬â€ blocked, failed, or processing outcomes.

Tracked fields are review ID, rating, app version, country, review date, and a one-way normalized review-text hash. Reviewer names, review titles, and review text are not retained or emitted. Updated records include both previous and current values. Missing source values remain `null`.

The `OUTPUT` key-value-store record contains the normalized input, status, baseline and change totals, charge count, retries, limits, errors, dataset URL, and the removal-semantics warning.

### Status meanings

- `complete`: every requested monitor succeeded and at least one current review was observed.
- `empty`: every requested monitor succeeded but the bounded feeds contained no reviews.
- `partial`: usable work completed but one or more source or processing paths failed.
- `blocked`: no trustworthy monitor completed because Apple access was blocked.

A blocked or malformed source is never reported as a successful empty result.

### Important limitations

- AppleÃ¢â‚¬â„¢s public customer-review feed is a legacy public surface, not the authenticated App Store Connect API and not a modern availability-guaranteed contract.
- The feed is storefront-specific. The same app can have different reviews in different countries.
- Apple exposes a rolling bounded window, not guaranteed complete review history.
- `removed_from_observed_feed` does **not** prove deletion or retraction. Newer reviews can push older reviews outside the monitored window.
- Empty output cannot prove that a numeric App ID is valid; Apple returns an empty feed shape for some invalid or review-free IDs.
- The Actor does not return or infer sentiment, keywords, summaries, app names, or private data.
- If Apple later requires accounts, proxies, browser automation, or private endpoints, this product must stop rather than silently bypass access controls.

### Public-data boundary

Only HTTPS requests to `itunes.apple.com/<country>/rss/customerreviews/...` are constructed. Inputs cannot provide arbitrary source hosts. The Actor does not access App Store Connect, authenticated endpoints, developer responses, private reviews, or restricted content.

### FAQ

#### Why did the first run return a baseline instead of changes?

The Actor must first learn what is already visible. Existing reviews are saved for comparison and are neither reported nor billed as changes.

#### Why can a review be Ã¢â‚¬Å“removed from observed feedÃ¢â‚¬Â even if it still exists?

Apple exposes a rolling window. A review can fall outside the selected page depth when newer reviews arrive. The Actor deliberately avoids claiming deletion.

#### Will changing the number of pages create removals or new reviews?

It can change the observed window. Use a new monitor key when changing page depth or country semantics if you want a clean baseline.

#### Are review texts returned?

This monitoring contract tracks a normalized SHA-256 text hash. It detects text changes without copying review bodies into the persistent monitoring dataset.

#### Does it use proxies?

No. Direct public HTTP only. Blocked access produces an explicit blocked or partial outcome.

### Support

For a reproducible issue, provide the run URL, normalized input with secrets removed, app ID, country, and observed diagnostic code. Do not provide Apple credentials; the Actor cannot use them.

See [CHANGELOG.md](CHANGELOG.md) for release history.

### Who this Actor is for

Operations, monitoring, research, and data teams that need monitor public apple app store review feeds and charge only for checks and material changes. It is designed for scheduled Apify, API, webhook, integration, and MCP-compatible workflowsÃ¢â‚¬â€not for unsupported professional conclusions.

### Input reference

- `appStoreUrls`: Public apps.apple.com URLs, such as https://apps.apple.com/us/app/instagram/id389801252.
- `appIds`: Numeric IDs from App Store URLs. You may combine these with URLs.
- `countries`: Two-letter codes such as us, gb, br, or jp. If omitted, URL countries are inferred; App IDs without a URL use us.
- `monitorKey`: A stable name for this group, such as ios-competitors.
- `maxAppCountryMonitors`: Default maximum is 25. Up to 100 requires advanced mode.
- `enableAdvancedLimit`: Enable only after validating a smaller recurring run.
- `maxPagesPerMonitor`: Apple currently exposes up to 50 reviews per page and 10 pages. Two pages keeps normal monitoring fast while observing up to 100 reviews.
- `maxConcurrency`: Keep the default unless private validation proves a reason to change it.
- `requestTimeoutSecs`: Covers the complete HTTP transaction, including response streaming.
- `maxRequestRetries`: Retries only timeouts, rate limits, and temporary server errors.
- `maxResponseBytes`: Streaming limit. A response is aborted as soon as this bound is exceeded.

Representative input (replace placeholders and use only sources you are authorized to access):

```json
{
  "appStoreUrls": [],
  "appIds": [],
  "countries": [],
  "monitorKey": "default",
  "maxAppCountryMonitors": 25,
  "enableAdvancedLimit": false,
  "maxPagesPerMonitor": 2,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 10,
  "maxRequestRetries": 1,
  "maxResponseBytes": 500000
}
```

### Output reference

- `recordType`: Structured output field.
- `eventId`: Structured output field.
- `stableId`: Structured output field.
- `monitorId`: Structured output field.
- `appId`: Structured output field.
- `country`: Structured output field.
- `changeType`: Structured output field.
- `reviewId`: Structured output field.
- `rating`: Structured output field.
- `version`: Structured output field.
- `reviewDate`: Structured output field.
- `reviewTextHash`: Structured output field.
- `previousReview`: Structured output field.
- `currentReview`: Structured output field.
- `changes`: Structured output field.
- `reviewsInBaseline`: Structured output field.
- `message`: Structured output field.
- `code`: Structured output field.
- `retryable`: Structured output field.
- `appStoreUrl`: Structured output field.
- `sourceUrl`: Structured output field.
- `observedAt`: Structured output field.

The first complete run creates an expected baseline where the product uses state. Later comparable runs emit only the documented observations or changes. Dataset records retain deterministic identity and source evidence where the contract requires it.

### Limitations and known semantics

- Only the documented source, input forms, fields, identities, and completeness rules are supported.
- An empty, partial, blocked, timed-out, or malformed upstream response is never silently reported as a successful empty result.
- Absence or removal is reported only with the exact observational wording and completeness evidence documented by this Actor; it is not proof of a real-world deletion or status unless the source explicitly says so.
- Upstream publication schedules, schemas, coverage, terms, and availability can change.

### Errors and troubleshooting

Check the run status and OUTPUT summary before consuming Dataset rows. For invalid input, correct the named field. For retryable source failures, preserve the monitor key/state and retry later. For schema or completeness failures, do not reset state or infer changes; report the run ID and non-secret diagnostics to support.

### API, integrations, and MCP

Run the Actor through the Apify API, Schedule, webhook, or supported integration. Read structured records from the default Dataset and the run summary from the default Key-value store. MCP/agent consumers must preserve source, status, uncertainty, and limitation fields and must not convert observational outputs into unsupported claims.

### Privacy and legal notes

Submit only data necessary for the documented workflow and only sources you are authorized to access. Do not include credentials, sensitive personal data, or private URLs unless the Actor explicitly documents secure support for them. Outputs are factual automation evidence, not legal, financial, safety, employment, regulatory, or compliance advice. You remain responsible for source rights, downstream use, retention, and professional review.

# Changelog

This Actor's version history is a separate document: https://apify.com/ursog/apple-app-store-review-delta-api/changelog.md

# Actor input Schema

## `appStoreUrls` (type: `array`):

Public apps.apple.com URLs, such as https://apps.apple.com/us/app/instagram/id389801252.

## `appIds` (type: `array`):

Numeric IDs from App Store URLs. You may combine these with URLs.

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

Two-letter codes such as us, gb, br, or jp. If omitted, URL countries are inferred; App IDs without a URL use us.

## `monitorKey` (type: `string`):

A stable name for this group, such as ios-competitors.

## `maxAppCountryMonitors` (type: `integer`):

Default maximum is 25. Up to 100 requires advanced mode.

## `enableAdvancedLimit` (type: `boolean`):

Enable only after validating a smaller recurring run.

## `maxPagesPerMonitor` (type: `integer`):

Apple currently exposes up to 50 reviews per page and 10 pages. Two pages keeps normal monitoring fast while observing up to 100 reviews.

## `maxConcurrency` (type: `integer`):

Keep the default unless private validation proves a reason to change it.

## `requestTimeoutSecs` (type: `integer`):

Covers the complete HTTP transaction, including response streaming.

## `maxRequestRetries` (type: `integer`):

Retries only timeouts, rate limits, and temporary server errors.

## `maxResponseBytes` (type: `integer`):

Streaming limit. A response is aborted as soon as this bound is exceeded.

## Actor input object example

```json
{
  "appStoreUrls": [],
  "appIds": [],
  "countries": [],
  "monitorKey": "default",
  "maxAppCountryMonitors": 25,
  "enableAdvancedLimit": false,
  "maxPagesPerMonitor": 2,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 10,
  "maxRequestRetries": 1,
  "maxResponseBytes": 500000
}
```

# Actor output Schema

## `changes` (type: `string`):

No description

## `baselines` (type: `string`):

No description

## `diagnostics` (type: `string`):

No description

## `runSummary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("ursog/apple-app-store-review-delta-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("ursog/apple-app-store-review-delta-api").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 '{}' |
apify call ursog/apple-app-store-review-delta-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ursog/apple-app-store-review-delta-api"
        }
    }
}
```

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/cYsYlndp4OfqjKqah/builds/FUZ8DUaOjzEKd7DO0/openapi.json
