# App Store Ratings & Reviews Monitor – iOS & Mac, All Countries (`tinlark/app-store-ratings-reviews-monitor`) Actor

Track Apple App Store ratings and reviews for your apps and competitors in any country. Rating snapshots, latest reviews (no reviewer names) and monitor mode: rating, version and new-review changes since your last run. Public Apple endpoints, no login, no proxy.

- **URL**: https://apify.com/tinlark/app-store-ratings-reviews-monitor.md
- **Developed by:** [Tinlark](https://apify.com/tinlark) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## App Store Ratings & Reviews Monitor – iOS & Mac, All Countries

Track Apple App Store ratings and reviews for your own apps and your competitors', in as many countries as you like. Give the Actor app ids, App Store links or bundle ids and a list of countries. It returns one rating snapshot per app and country, or the latest customer reviews. In **monitor** mode it returns only what changed since your last run: rating change, rating-count change, new version, price change and new reviews. Put it on a daily schedule and it becomes an alert feed.

The Actor reads Apple's public iTunes Lookup API and Apple's public customer reviews feed. It needs no login and no browser. Reviewer names are never output.

### What you can do with it

- **App Store rating tracker by country.** The same app can have a 4.7 rating in the US and a 4.2 in Brazil. One run gives you every country side by side: average rating, rating count, rating and count for the current version, version, release notes, price, seller, genres, content rating, minimum OS version and file size.
- **Competitor monitor.** Switch on `monitor` mode with a *State name*. The first run records a baseline and costs nothing. Every later run returns a row only for apps that changed, with `ratingDelta`, `ratingCountDelta`, `previousVersion` and the new reviews.
- **Latest reviews.** The newest customer reviews per app and country, with rating, title, text, app version, date and helpfulness votes. Filter by star rating (for example 1 and 2 stars only) or by date.
- **Find apps by keyword.** Enter a search term such as `habit tracker` and the Actor adds the top results (iPhone and iPad apps, Mac apps, or both).
- **iOS and Mac.** Both kinds of apps work. Other Apple store items (music, books, podcasts) are skipped.

### Who it is for

Product and growth teams that benchmark their app against competitors, app-store-optimization (ASO) and market-research analysts, support teams that want to hear about new 1-star reviews quickly, investors and journalists who follow app ratings, and developers who build dashboards.

### Input

| Field | What it does |
|---|---|
| `apps` | One entry per app: an App Store id (`389801252`), an App Store link (`https://apps.apple.com/us/app/instagram/id389801252`) or a bundle id (`com.burbn.instagram`). Up to 2,000 per run. |
| `searchTerm` | Optional. Adds the top search results to `apps`. The search runs in the first country of your list. |
| `searchPlatform`, `searchLimit` | Search in iPhone/iPad apps, Mac apps or both; number of results per store (default 5). |
| `countries` | Two-letter storefront codes (`us`, `gb`, `de`, `jp`, ...). Write `all` for every storefront (about 175). |
| `mode` | `snapshot` (default), `reviews` or `monitor`. |
| `maxReviewsPerAppCountry` | Reviews and monitor modes. 1 to 500, default 50. |
| `reviewSort` | Reviews mode: `recent` (default) or `helpful`. |
| `sinceDate` | Keep only reviews written or edited on or after this date. |
| `minRating`, `maxRating` | Keep only reviews with a star rating in this range. |
| `maxItems` | Stop after this many billable rows (snapshots and reviews). Default 1,000. |
| `stateKey` | Monitor mode. A name such as `daily-competitors`. Required for monitor mode. Use the same name on every scheduled run and a different one for each watch list. |
| `trackReviews` | Monitor mode. Turn off to watch only rating, rating count, version and price. This uses far fewer calls to Apple. |
| `emitUnchanged` | Monitor mode. Also return a row for apps that did not change. |

The prefilled input is two apps in three countries in `snapshot` mode.

#### Example: compare two apps in three countries

```json
{
  "apps": ["570060128", "324684580"],
  "countries": ["us", "gb", "de"],
  "mode": "snapshot"
}
```

#### Example: the latest unhappy reviews

```json
{
  "apps": ["https://apps.apple.com/us/app/instagram/id389801252"],
  "countries": ["us", "gb"],
  "mode": "reviews",
  "maxRating": 2,
  "maxReviewsPerAppCountry": 100
}
```

#### Example: daily competitor monitor

```json
{
  "apps": ["com.burbn.instagram", "com.zhiliaoapp.musically"],
  "countries": ["us", "gb", "de", "br"],
  "mode": "monitor",
  "stateKey": "daily-competitors",
  "maxRating": 2
}
```

### Monitor mode

Monitor mode is built for schedules. It keeps one small record per app and country in a named key-value store, `appstore-state-<stateKey>`, in your account.

- **First run:** records a baseline for each app and country and returns it as a row with `status: "baseline"`. Baseline rows are free. No review rows are returned, so you are not handed the backlog.
- **Later runs:** compares today's Apple data with the record. An app and country with no change returns no row and costs nothing (turn on `emitUnchanged` to see them anyway).
- **Changed apps** return one snapshot row with `status: "changed"` and a `changes` list made of `rating-changed`, `rating-count-changed`, `new-version`, `price-changed` and `new-reviews`, plus `ratingDelta`, `ratingCountDelta`, `previousAverageUserRating`, `previousUserRatingCount`, `previousVersion`, `previousPrice` and `newReviewCount`. The new reviews follow as review rows.
- **Reviews are reported once.** A review is "new" when it is not in the record and is newer than the oldest review seen at the baseline. If a rating or date filter removes a new review, it is still marked as seen. If a run stops early (for example at `maxItems` or the maximum cost per run), the rest is delivered by the next run and nothing is lost.
- **Gaps in Apple's feed.** Apple's review feed sometimes answers with an empty page for an app that has reviews. The Actor reads an empty page again several times. If the feed is still empty at the baseline, the review baseline is taken silently on a later run instead of recording an empty one, so old reviews are not reported as new.
- To watch a different list, use a different `stateKey`. To start over, delete the key-value store `appstore-state-<stateKey>` in the Apify Console.

Schedule it with Apify Schedules (for example every day at 08:00) and connect a webhook, Slack, e-mail or Zapier to the run to turn the changed rows into alerts.

### Output

Results go to the default dataset. Download them as JSON, CSV, Excel or XML, or read them through the API. The *Snapshots*, *Reviews*, *Monitor changes* and *Problems* views show the main fields. A run summary (rows, errors, number of calls to Apple, duration) is saved under the `SUMMARY` key of the run's key-value store.

#### App snapshot row (real output, trimmed)

```json
{
  "recordType": "app-snapshot",
  "appId": "570060128",
  "bundleId": "com.duolingo.DuolingoMobile",
  "name": "Duolingo: Language Lessons",
  "seller": "Duolingo, Inc",
  "platform": "ios",
  "country": "us",
  "price": 0,
  "currency": "USD",
  "version": "7.142.0",
  "currentVersionReleaseDate": "2026-09-28T17:42:01Z",
  "averageUserRating": 4.72301,
  "userRatingCount": 5483098,
  "averageRatingCurrentVersion": 4.72301,
  "ratingCountCurrentVersion": 5483098,
  "genres": ["Education", "Social Networking"],
  "contentRating": "4+",
  "minOsVersion": "17.0",
  "appUrl": "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
  "checkedAt": "2026-10-03T08:28:21Z",
  "source": "Data from Apple's public iTunes Lookup API"
}
```

#### Monitor row for a changed app (output of a test run, trimmed)

```json
{
  "recordType": "app-snapshot",
  "appId": "570060128",
  "name": "Duolingo: Language Lessons",
  "country": "us",
  "version": "7.142.0",
  "averageUserRating": 4.72301,
  "userRatingCount": 5483098,
  "status": "changed",
  "changes": ["rating-changed", "rating-count-changed", "new-version", "new-reviews"],
  "ratingDelta": 0.02301,
  "ratingCountDelta": 1000,
  "previousAverageUserRating": 4.7,
  "previousUserRatingCount": 5482098,
  "previousVersion": "7.141.0",
  "newReviewCount": 3,
  "previousCheckedAt": "2026-10-03T08:40:10Z"
}
```

#### Review row (real output, trimmed)

```json
{
  "recordType": "review",
  "reviewId": "14616169567",
  "appId": "389801252",
  "country": "gb",
  "rating": 2,
  "title": "Bad app",
  "text": "Can’t lie insta has fallen off I can’t log into my account even tho it’s still active this has become a issue with insta and snap chat",
  "appVersion": "448.0.0",
  "updatedAt": "2026-10-01T19:44:49Z",
  "voteSum": 0,
  "voteCount": 0,
  "authorHash": "1f834db26537546a",
  "checkedAt": "2026-10-03T08:43:23Z",
  "source": "Data from Apple's public customer reviews feed"
}
```

#### Field notes

- Ratings are the average and count that Apple shows for each storefront. `averageRatingCurrentVersion` and `ratingCountCurrentVersion` are Apple's figures for the current version only and are empty when Apple does not publish them.
- `authorHash` is a stable pseudonym (a hash) of the reviewer's Apple identifier. The same reviewer gets the same hash across runs, so you can de-duplicate or spot repeat reviewers, but the name and the identifier are not in the output.
- `updatedAt` is when the review was written or last edited, in UTC.
- Every row has a `source` field that names the Apple endpoint it came from. Rows contain facts only: no artwork, screenshots or app descriptions.
- Rows with `recordType: "error"` are free. They say which input could not be read, and why.

### Pricing

**Free during launch (until 31 October 2026).** You pay only Apify's own platform usage for your runs.

From 1 November 2026: pay per event, $3 per 1,000 app snapshots and $0.80 per 1,000 reviews.

| Event | Planned price from 1 November 2026 | When it will be charged |
|---|---|---|
| App snapshot row | $3.00 per 1,000 ($0.003 each) | Each app and country row in `snapshot` mode, and each changed (or, with `emitUnchanged`, each) app row in `monitor` mode |
| Review | $0.80 per 1,000 ($0.0008 each) | Each review row |

Not charged: error rows, the baseline rows of a monitor run, and apps that did not change in monitor mode. Example at the planned prices: a daily monitor of 20 apps in 5 countries where about 10 app and country pairs change per day and bring 15 new reviews costs about $0.04 a day. Set *Maximum cost per run* in the run options to cap spending; the Actor stops cleanly when the cap is reached.

### Limits and honest notes

- **About 500 most recent reviews per app and country.** Apple's public review feed serves 10 pages of 50 reviews. Older reviews cannot be read, so this Actor is for monitoring and benchmarking, not for full historical review exports. Only reviews with written text appear in the feed, so the number of reviews can be well below the rating count.
- **iOS and Mac apps only.** Music, books, podcasts and other Apple store items are not covered.
- **Pace.** Apple states about 20 calls a minute per endpoint. The Actor keeps to that and has no switch to go faster. A lookup call covers up to 100 apps in one country, a review call returns 50 reviews. Examples: 2 apps in 3 countries (snapshot) finishes in about 10 seconds; 100 reviews for each of 10 apps in one country takes about 1 to 2 minutes; all 175 storefronts for a few apps takes several minutes.
- **Apple's feed is sometimes empty.** The review feed occasionally returns an empty page for an app that has reviews. The Actor retries, but if you get an error row saying that no reviews came back, run it again a little later.
- **Countries.** An app that is not sold in a country returns an error row for that country, or nothing when you ask for `all` countries.
- **Release notes and ratings reflect what Apple shows today.** There is no rating history before your first run. Monitor mode builds the history from the day you start it.

### Data source, terms and your responsibility

All data comes from two public Apple endpoints: the iTunes Lookup and Search API (`itunes.apple.com/lookup`, `itunes.apple.com/search`) and the customer reviews feed (`itunes.apple.com/{country}/rss/customerreviews`). The Actor identifies itself with a `TinlarkBot` User-Agent and keeps below Apple's stated call rate. It does not log in, does not use private APIs and does not download artwork, screenshots or previews.

Reviews are written by Apple customers. The Actor never outputs reviewer names; the pseudonymous `authorHash` is meant for de-duplication only. Review text can contain personal information that a reviewer chose to write: treat it with care, and check the terms of Apple's APIs and the laws that apply to you (for example data protection law and the rules for republishing reviews) before you reuse the data. Apple's terms for these APIs ask for attribution, which is why each row carries a `source` field.

This Actor is not affiliated with, endorsed by or sponsored by Apple Inc. App Store and iTunes are trademarks of Apple Inc.

### FAQ

**Does it need a proxy or a login?** No. Apple's endpoints are public and the Actor uses plain HTTP requests.

**Why can I only get about 500 reviews?** That is all Apple's public feed shows: 10 pages of 50 per app and country, newest first. For history, run monitor mode on a schedule from today onwards.

**How do I get an alert when someone writes a 1-star review?** Use `monitor` mode with `maxRating: 2` (or 1), a `stateKey`, and a daily schedule. The Actor returns only new reviews with that rating. Attach a webhook or an Apify integration to the run to be notified.

**What is the difference between `snapshot` and `monitor`?** `snapshot` returns the current state of every app and country on every run. `monitor` remembers the last run and returns only changes, with the differences calculated for you.

**Why did my app return an error row?** Typical reasons: the bundle id has a typo, the id belongs to something other than an iOS or Mac app, or the app is not sold in that country. The `error` field says which.

**Are reviewer names included?** No, never. There is no option for it.

**Can I schedule it?** Yes. Use Apify Schedules with a fixed `stateKey` for monitor mode.

**How do I use it from code or an AI agent?** Call it through the Apify API or any Apify client library, or through Apify's MCP server. The input and output schemas are defined, so the fields are self-describing.

**Disclaimers and legality: can I use this data?** This Actor reads only publicly available data from Apple's public iTunes Lookup API and customer reviews feed, at the rate Apple states. It does not bypass logins or technical protections. You are responsible for how you use the output and for complying with Apple's terms, copyright and data protection law (such as the GDPR) in your country. Reviewer names are not collected. Reviews and app texts belong to their authors and publishers. The Actor is provided as is, without a warranty of completeness: Apple decides what its feeds contain, and they can change or be temporarily empty. Nothing here is legal advice.

### Related Tinlark Actors

- [Domain Tech Stack, Contacts & SEO Profiler](https://apify.com/tinlark/domain-intelligence-profiler): the technologies, business contacts and SEO basics of the website of the company behind an app.
- [ATS Jobs Scraper](https://apify.com/tinlark/ats-jobs-hiring-signals): the open jobs and hiring signals of the same company, read from its public job board.

### Changelog

- 2026-10-03: added the Related Tinlark Actors section.

### Support

Something wrong or missing? Open an issue on this Actor's Issues tab with your input (the app id and the country) and what you expected.

# Actor input Schema

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

One entry per app: an App Store id (389801252), an App Store link (https://apps.apple.com/us/app/instagram/id389801252) or a bundle id (com.burbn.instagram). iOS and Mac apps. Leave empty if you use a search term.

## `searchTerm` (type: `string`):

Find apps by name or keyword and add the top results to the list above. The search runs in the first country of your list.

## `searchPlatform` (type: `string`):

Which store the search term looks in.

## `searchLimit` (type: `integer`):

How many search results to add (per store).

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

Two-letter App Store storefront codes such as us, gb, de, jp, fr, br. Write all for every storefront (about 175). Apple allows about 20 calls a minute per endpoint, so all countries for a few apps takes several minutes.

## `mode` (type: `string`):

snapshot: one row per app and country with rating, rating count, version and price. reviews: the latest customer reviews. monitor: what changed since the last run (rating, rating count, version, price, new reviews); the first run only records a free baseline. Needs a State name.

## `maxReviewsPerAppCountry` (type: `integer`):

Reviews and monitor modes. Apple's public feed shows at most the 500 most recent reviews per app and country, 50 per call.

## `reviewSort` (type: `string`):

Reviews mode only. recent: newest first. helpful: most helpful first (within the same 500-review window). Monitor mode always reads the newest reviews.

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

Keep only reviews written or last edited on or after this date, for example 2026-09-01.

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

Reviews and monitor modes. 1 keeps everything.

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

Reviews and monitor modes. Set to 2 to watch for unhappy customers only.

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

Stops the run once this many billable rows (app snapshots and reviews) were produced.

## `stateKey` (type: `string`):

Monitor mode. Lowercase letters, digits and hyphens. Saves what was seen in a named storage so later runs report only the changes. Use the same name on every scheduled run, and a different name for each watch list.

## `trackReviews` (type: `boolean`):

Monitor mode. Turn off to watch only rating, rating count, version and price. That uses far fewer calls to Apple.

## `emitUnchanged` (type: `boolean`):

Monitor mode. By default an app and country with no change since the last run returns no row (and costs nothing). Turn on to get a row for every app and country on every run.

## Actor input object example

```json
{
  "apps": [
    "389801252",
    "https://apps.apple.com/us/app/instagram/id389801252",
    "com.burbn.instagram"
  ],
  "searchPlatform": "ios",
  "searchLimit": 5,
  "countries": [
    "us",
    "gb",
    "de"
  ],
  "mode": "snapshot",
  "maxReviewsPerAppCountry": 50,
  "reviewSort": "recent",
  "minRating": 1,
  "maxRating": 5,
  "maxItems": 1000,
  "trackReviews": true,
  "emitUnchanged": false
}
```

# Actor output Schema

## `snapshots` (type: `string`):

One row per app and country, with change fields in monitor mode.

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

Customer reviews, newest first within each app and country.

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

Apps whose rating, rating count, version, price or reviews changed since the last run.

## `errors` (type: `string`):

Inputs that could not be read, with the reason.

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

Counts, errors and call totals.

# 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": [
        "570060128",
        "324684580"
    ],
    "countries": [
        "us",
        "gb",
        "de"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinlark/app-store-ratings-reviews-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 = {
    "apps": [
        "570060128",
        "324684580",
    ],
    "countries": [
        "us",
        "gb",
        "de",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("tinlark/app-store-ratings-reviews-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 '{
  "apps": [
    "570060128",
    "324684580"
  ],
  "countries": [
    "us",
    "gb",
    "de"
  ]
}' |
apify call tinlark/app-store-ratings-reviews-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tinlark/app-store-ratings-reviews-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/a461k0K9023iXiGtb/builds/CHj3HMIFgcNGyOZMM/openapi.json
