# Apple App Store Reviews Scraper - iOS App Reviews & Ratings (`tidytools/apple-app-store-reviews`) Actor

App Store scraper for iOS app reviews and app details from Apple's official public feeds, many countries. Star, date and keyword filters, new-review alerts, optional AI summary. $0.10/1,000 reviews.

- **URL**: https://apify.com/tidytools/apple-app-store-reviews.md
- **Developed by:** [Yukai Lin](https://apify.com/tidytools) (community)
- **Categories:** Marketing, AI, Automation
- **Features:** Limited permissions
- **Stats:** 5 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

**App Store reviews scraper for $0.10 per 1,000 reviews: iPhone and iPad app reviews, ratings and app details from Apple's own public feeds, many countries in one run, no login or API key. Filtered-out reviews and apps that are not found are free.**

#### Why this one

- **$0.10 per 1,000 reviews** ($0.08 on Business and higher), no start fee. The two most used App Store review Actors charge $0.10 (thewolves, whose Free plan is a demo of 5 runs a month and 10 items per run) and $1.44 plus $0.0175 per run (johnvc) per 1,000 reviews ([comparison](#switching-from-another-app-store-reviews-actor), checked 2 October 2026).
- **Filters before charging**: stars, date (`30 days`), keywords, excluded keywords and app versions. Filtered-out and duplicate reviews, apps that are not found and invalid lines are free, and every row says `charged: true/false`. Neither of those two Actors filters before charging.
- **Many countries and any input in one run**: App Store links, app ids, bundle ids or search terms, read in every country you list (they take one country per run).
- **Only new reviews since the last run** for daily monitoring and alerts, plus optional **app details** rows and an **AI summary** per app (top complaints, praises, feature requests, bug reports).
- **No login, no API key, no proxy**: Apple's public reviews feed and iTunes Lookup API. Honest limit: Apple serves at most 500 reviews per app and country ([details](#where-the-data-comes-from-and-apples-limits)).

#### Input (copy and paste)

```json
{
    "apps": [
        "https://apps.apple.com/us/app/instagram/id389801252",
        "310633997",
        "com.spotify.client",
        "ChatGPT",
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"
    ],
    "countries": ["us", "gb", "de"],
    "maxReviewsPerCountry": 100,
    "aiInsights": true
}
```

#### Output (real result, shortened)

That input (5 apps × 3 countries) returned 1,500 reviews ($0.15), 15 app details rows (free) and 5 AI insights ($0.10): **$0.25 in 68 seconds**. One review row:

```json
{
    "type": "review",
    "appId": "324684580",
    "appName": "Spotify: Music and Podcasts",
    "country": "us",
    "rating": 1,
    "title": "Hate the update",
    "text": "Hate it thanks.",
    "version": "9.1.86",
    "author": "Poleryeno",
    "date": "2026-09-28T13:07:21.000Z",
    "helpfulVotes": 0,
    "charged": true
}
```

All fields, app details and AI insights rows: [Output example](#output-example-review).

### How much does it cost?

Price per 1,000 events by Apify plan:

| Event | Free | Starter | Scale | Business and higher |
|---|---|---|---|---|
| Review | **$0.10** | **$0.10** | **$0.09** | **$0.08** |
| App details row (one app in one country) | free | free | free | free |
| AI insights (optional, per app) | $20 ($0.02 each) | $20 | $18 | $16 |

**No start fee.** Not charged: app details rows, reviews removed by your filters, duplicate reviews, reviews already seen with **Only new reviews**, apps or search terms that are not found, apps not available in a country, app/country pairs where Apple's feed is empty (`apple_feed_empty` rows), invalid input lines, and AI insights that fail or have fewer than 10 reviews to work with.

### Features

It returns **App Store customer reviews and app details** for any list of iPhone and iPad apps, in as many countries as you like, from **Apple's own public endpoints**: the customer reviews feed (RSS/JSON) and the iTunes Search and Lookup API. Paste app links, app ids, bundle ids or plain search terms; get one clean row per review and one row per app and country.

- 🍎 **Official public sources only**: no login, no private API tokens, no browser. The same feeds Apple publishes for developers and affiliates
- 🔗 **Any input**: `https://apps.apple.com/us/app/instagram/id389801252`, `389801252`, `id389801252`, `com.spotify.client`, or a search term such as `habit tracker` (first match or the top N). The same app pasted twice is read once
- 🌍 **Many countries in one run**: Apple keeps reviews per country store; list `us`, `gb`, `de`, `jp`… and every row says which store it came from
- ⭐ **Clean review rows**: `rating`, `title`, `text`, `version`, `date` (ISO, UTC), `author` (public display name, only when **Include reviewer display names** is on), `helpfulVotes`, `country`, `appName`, `reviewId`. The same fields on every row, every run
- 🎯 **Filters before charging**: minimum/maximum stars, reviews since a date (`2026-09-01` or `30 days`), keywords (any of), excluded keywords, app versions. Filtered-out reviews are free
- ↕️ **Sort**: most recent, most helpful, lowest or highest rating first, oldest first
- 📱 **App details**: developer, price, average rating and rating count (all versions and current version), version, release notes, release dates, category, age rating, size, languages, minimum iOS, icon and screenshot URLs, App Store link
- 🆕 **Only new reviews since the last run**: for daily monitoring. Reviews already seen are not output and not charged
- 🧠 **Optional AI insights per app**: a short summary plus top complaints, praises, feature requests and bug reports, each with an approximate count and an example quote (checked against the reviews: `exampleFound`)
- 🧾 **Honest about Apple's limit**: Apple's feed serves at most **500 reviews per app and country** (10 pages × 50). The Actor says so up front and in every run summary
- 💵 **$0.10 per 1,000 reviews**, app details rows free. No start fee

### Where the data comes from, and Apple's limits

| Data | Apple endpoint | Limit |
|---|---|---|
| Reviews | `https://itunes.apple.com/{country}/rss/customerreviews/page={1-10}/id={appId}/sortby={mostrecent or mosthelpful}/json` | 10 pages of 50 = **500 most recent (or most helpful) reviews per app and country**. Older reviews are not in the feed |
| App details, bundle id lookup | `https://itunes.apple.com/lookup?id=…&country=…` (up to 100 apps per call) | Apple asks for about **20 calls per minute** (subject to change) |
| Search terms | `https://itunes.apple.com/search?term=…&entity=software&country=…` | same as above |

What this means in practice:

- **At most 500 reviews per app and country.** This is the most common complaint about App Store review tools ("cannot get more than 200/450/500 reviews"). With 10 countries you can get up to 5,000 reviews of one app. For the full history of a big app you need Apple's own App Store Connect data (for your own apps) or a tool that uses Apple's private web API; this Actor deliberately does not.
- **Apple's feed has hiccups**: it often answers with an empty page for a page that does have reviews. The Actor asks again (with a fresh URL, a few at a time, up to 40 times by default) and reads each page it can get. In our test runs every page was read, with 2–35 requests per country for 2 pages; `SUMMARY.perApp[].perCountry` shows the pages read and requests made, and lists any page that stayed empty as `pagesMissing`.
- **Lookups and searches are spaced about 3 seconds apart** to follow Apple's rate guidance, so 100 search terms take about 5 minutes before reviews are read. App links and ids need no search.
- **No link to a single review**: Apple has no public page per review. Rows link to the app's reviews page (`reviewsUrl`).

### Who is it for?

- **App developers and product managers**: read what users say about your app and competitors, per version and country
- **ASO and app marketing teams**: ratings, rating counts, versions and release notes across countries; monitor new reviews daily
- **Customer support**: a daily feed of new 1- and 2-star reviews that mention "crash", "login" or "refund"
- **Market research**: compare apps in a category (top N search results for a keyword)
- **AI agents and analysts**: sentiment, feature requests and bug reports from real reviews

### Cost control and price comparison

#### Control your cost

- **What is charged:** each review returned and each AI insight produced. App details rows are free.
- **Max reviews per app and country** (up to 500, Apple's limit) and **Max reviews** for the whole run (default 10,000: at most $1 on the Free plan) cap the review charge.
- **Filters are applied before charging**, so "1–2 stars in the last 30 days" costs only for those reviews.
- **Only new reviews** makes daily schedules cheap: after the first run you pay only for reviews posted since the previous run.
- **Reviews only** mode skips the app details rows.
- At the start, the run logs its worst case (e.g. `Plan: 1500 reviews × $0.0001 + 5 AI insights × $0.02 = at most $0.25`) and warns when that is more than your **maximum charge per run**.
- When the maximum charge per run is reached, the run stops, keeps everything found so far, and says so. The `SUMMARY` record then has `status: "LIMIT_REACHED"` and `notProcessed` (up to 100 apps not processed).

**Worked example (real run, 30 September 2026, Free plan prices):** Instagram, WhatsApp, Spotify (bundle id), ChatGPT (search term) and Duolingo in the US, UK and German stores, 100 reviews per app and country, app details and AI insights on:

| What | Count | Cost |
|---|---|---|
| Reviews | 1,500 | $0.15 |
| App details rows | 15 | free |
| AI insights | 5 | $0.10 |
| **Total** | | **$0.25** (68 seconds) |

The same run without AI insights costs $0.15, the same as reviews only.

#### Switching from another App Store reviews Actor

You can paste the input you already use. The field names of the two most-used App Store review Actors on the Apify Store are read as ours, and the log says how each one was read:

| Their field | Read here as |
|---|---|
| `appIds`, `startUrls` (strings or `{ "url": ... }`), `urls`, `product_ids` | `apps` |
| `app_name`, `searchTerm` | `apps`, as a search term |
| `country` (one code) | `countries` (with no country given, the countries in your App Store links are used) |
| `maxItems` | `maxReviews` (whole run) |
| `max_reviews` (`0` = unlimited) | `maxReviewsPerCountry` (500 for unlimited) |
| `sort` / `reviewSort` (`mostrecent`, `mosthelpful`, `mostcritical`, `mostfavorable`) | `sortBy` (`mostRecent`, `mostHelpful`, `lowestRating`, `highestRating`) |
| `until` ("reviews newer than this date") | `sinceDate` |

Our own fields win when both are given. `customMapFunction` is ignored (no custom code runs here; use the filters and the export formats instead), and `country: "all"` is not supported (list the countries you need). Every app is read in every country of the run.

Example: this input, written for another Actor, runs here unchanged:

```json
{ "appIds": ["284882215", "408709785"], "startUrls": ["https://apps.apple.com/gb/app/instagram/id389801252"], "maxItems": 1000 }
```

How they compare (Free plan prices from the Apify Store API and each Actor's README, checked 2 October 2026):

| | This Actor | thewolves/appstore-reviews-scraper | johnvc/apple-app-store-reviews-api |
|---|---|---|---|
| Price per 1,000 reviews | $0.10 (less on higher plans) | $0.10 | $1.44 ($1.25 on paid plans) |
| Start fee per run | none | none | $0.0175 |
| Free plan | full use (Apify's free monthly credit) | demo mode: 5 runs a month, 10 items per run (their README) | no limit stated |
| Reviews per app and country | up to 500 (Apple's public feed) | up to 500 (Apple's limit, per their README) | up to about 1,250 on iOS (their README) |
| Errors, filtered-out and duplicate reviews | not charged (free error rows) | not stated | not stated |
| Filters before charging (stars, date, keywords, app version) | yes | no | no (sort by most critical or favorable) |
| Input | links, ids, bundle ids, search terms; many countries per run | app ids or links; one country per run | app ids or one app name; one country per run; iOS and macOS apps |
| Only new reviews since the last run | yes | no | no |
| App details rows (rating, rating count, version, price…) | yes (free, optional) | no | no (separate Actor) |
| AI summary of the reviews | optional ($0.02 per app) | no | no |

If you need more than 500 recent reviews of one app in one country, johnvc/apple-app-store-reviews-api reads deeper; for everything else this Actor costs the same or less.

For comparison (checked September 2026, Apple App Store review Actors on the Apify Store, Free plan prices): thewolves/appstore-reviews-scraper and theagents/appstore-reviews charge $0.0001 per result ($0.10 per 1,000); automation-lab/apple-app-store-scraper charges $0.00115 per review, $0.00345 per app and $0.005 per run start; johnvc/apple-app-store-reviews-api charges $0.00144 per review plus $0.0175 per run; sourabhbgp/apple-app-store-scraper charges $0.002 per row. Tools that promise thousands of reviews per country use Apple's private web API rather than the public feed.

### How to use it

1. Enter your **apps**, one per line: App Store links, app ids, bundle ids or search terms.
2. Enter the **countries** (two-letter codes). Left empty, the countries of your App Store links are used (`apps.apple.com/gb/...` reads the UK store), or `us` for ids and names.
3. Choose **What to return**: app details + reviews, reviews only, or app details only.
4. Optional: set **Max reviews per app and country**, filters (stars, since, keywords, versions) and the sort order.
5. Optional: turn on **AI insights** and/or **Only new reviews since the last run** (then schedule the Actor daily).
6. Click **Start**. The **Reviews**, **App details** and **AI insights** tables are in the Output tab; export as CSV, Excel or JSON, or call the Actor from the API.

#### Input example

```json
{
    "apps": [
        "https://apps.apple.com/us/app/instagram/id389801252",
        "310633997",
        "com.spotify.client",
        "ChatGPT",
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"
    ],
    "countries": ["us", "gb", "de"],
    "mode": "both",
    "maxReviewsPerCountry": 100,
    "aiInsights": true
}
```

Complaints only, last two weeks, most recent first:

```json
{ "apps": ["389801252"], "countries": ["us"], "mode": "reviews", "maxRating": 2, "sinceDate": "14 days", "keywords": ["bug", "crash", "glitch"] }
```

(A real run of that input on Instagram read all 500 reviews Apple serves in the US store and returned the 9 that matched; the 491 others were free.)

#### Output example: review

Real row from the run above:

```json
{
    "type": "review",
    "input": "com.spotify.client",
    "inputIndex": 2,
    "success": true,
    "reviewId": "14603311144",
    "appId": "324684580",
    "appName": "Spotify: Music and Podcasts",
    "country": "us",
    "rating": 1,
    "title": "Hate the update",
    "text": "Hate it thanks.",
    "version": "9.1.86",
    "date": "2026-09-28T13:07:21.000Z",
    "helpfulVotes": 0,
    "totalVotes": 0,
    "reviewsUrl": "https://apps.apple.com/us/app/id324684580?see-all=reviews",
    "charged": true,
    "scrapedAt": "2026-09-30T06:04:24.099Z"
}
```

With **Only new reviews**, rows also have `changeType: "new"`.

#### Output example: app details

Real row (lists and long texts shortened):

```json
{
    "type": "app",
    "input": "com.spotify.client",
    "success": true,
    "matchedBy": "bundle",
    "appId": "324684580",
    "bundleId": "com.spotify.client",
    "appName": "Spotify: Music and Podcasts",
    "developer": "Spotify",
    "developerUrl": "https://apps.apple.com/us/developer/spotify/id324684583",
    "sellerWebsite": "https://www.spotify.com/",
    "country": "us",
    "price": 0,
    "currency": "USD",
    "formattedPrice": "Free",
    "averageRating": 4.773,
    "ratingCount": 42342256,
    "averageRatingCurrentVersion": 4.773,
    "ratingCountCurrentVersion": 42342256,
    "version": "9.1.86",
    "currentVersionReleaseDate": "2026-09-23T17:49:27Z",
    "releaseNotes": "We’re always making changes and improvements to Spotify. To make sure you don’t miss a thing, just keep your Updates turned on.",
    "releaseDate": "2011-07-14T11:22:37Z",
    "description": "With the Spotify app, you can explore an extensive library of music and podcasts for free. …",
    "primaryGenre": "Music",
    "genres": ["Music", "Entertainment"],
    "contentRating": "12+",
    "minimumOsVersion": "16.1",
    "fileSizeMB": 296.9,
    "languages": ["AF", "AM", "…"],
    "iconUrl": "https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/…/512x512bb.jpg",
    "screenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/PurpleSource211/v4/…/392x696bb.png", "…"],
    "appUrl": "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580",
    "reviewsUrl": "https://apps.apple.com/us/app/id324684580?see-all=reviews",
    "charged": true
}
```

Search-term rows also have `searchTerm` and `searchRank`. Other fields: `developerId`, `seller`, `advisories`, `fileSizeBytes`, `supportedDevicesCount`, `features`, `isGameCenterEnabled`, `ipadScreenshotUrls`.

#### Output example: AI insights

Real row for Spotify (300 reviews in the run; the AI reads up to about 30,000 characters, here 159 reviews with every star rating represented). Lists shortened:

```json
{
    "type": "insights",
    "appName": "Spotify: Music and Podcasts",
    "countries": ["us", "gb", "de"],
    "reviewsInRun": 300,
    "reviewsAnalyzed": 159,
    "ratingsAnalyzed": { "1": 44, "2": 16, "3": 31, "4": 24, "5": 44 },
    "averageRatingInRun": 3.9,
    "overallSentiment": "negative",
    "summary": "Users are frustrated with excessive ads, premium ad issues, and price increases. They also report app freezing, post-update functionality issues, and podcast functionality problems. Despite these issues, many praise the music library, content variety, offline access, and user experience.",
    "complaints": [
        { "topic": "Excessive Advertising", "approxMentions": 15, "example": "Too many ads. When you don’t have premium, you basically cannot use the app.", "exampleFound": true },
        { "topic": "Premium Ad Issues", "approxMentions": 10, "example": "Premium = No adds, not a little less but more intrusive adds.", "exampleFound": true }
    ],
    "praises": [{ "topic": "Offline Access", "approxMentions": 6, "example": "Always there. Thanks Spotify for keeping the music going offline out in the back woods!", "exampleFound": true }],
    "featureRequests": [{ "topic": "Playlist Management Improvements", "approxMentions": 5, "example": "Allow us to add to a playlist by hold the plus instead of it going straight to liked music", "exampleFound": true }],
    "bugReports": [{ "topic": "App Freezing/Freezing Issues", "approxMentions": 5, "example": "The app freezes when I go between APP on my iPad.", "exampleFound": true }],
    "charged": true
}
```

`approxMentions` is the AI's estimate, not an exact count. `exampleFound` is `true` when the quote appears word for word in one of the reviews; `false` means the AI paraphrased it (about a third of the quotes in our test run). Use **Insights language** for a summary in another language. The summary is written by an open model on Cloudflare Workers AI (Qwen3 30B, with Llama 4 Scout as a second try when the first answer is not usable); an insight that still fails is returned as a free error row.

#### Errors (not charged)

Every input that cannot be used gets a row with `success: false`, an `errorType` and an `error` ending in "(not charged)":

```json
{ "type": "input", "input": "https://play.google.com/store/apps/details?id=x", "field": "apps", "success": false, "errorType": "invalid_input", "error": "\"https://play.google.com/store/apps/details?id=x\": play.google.com is not an App Store link (apps.apple.com/.../id123) (not charged)", "charged": false }
```

`errorType` is `invalid_input` (a line or country code that cannot be used), `not_found` (no such app or bundle id, a search with no results, or an app not available in a country), `blocked` (Apple kept refusing requests), `http_error`/`network`/`timeout` (the reviews feed could not be confirmed when requests failed, even if other retries returned empty pages), `apple_feed_empty` (all attempted feed pages returned no reviews after retries, with no request errors), or `no_text` (AI insights skipped: fewer than 10 reviews). Both feed error and empty-feed rows are free. An `apple_feed_empty` row includes `ratingCountInStore` for context; star ratings do not prove that written reviews exist in the feed.

The `SUMMARY` record (key-value store) has `status` (`SUCCESS`, `PARTIAL_RESULTS`, `FAILED`, `NO_RESULTS`, `LIMIT_REACHED`), totals (`reviewsOutput`, `detailsOutput`, `insightsOutput`, `reviewsFilteredOut`, `duplicatesSkipped`), `feed` (requests, rate-limited answers, pause time) and `perApp[].perCountry` (pages read, `requests`, `failedRequests`, `rateLimited`, reviews fetched, matched and returned, and a `note` such as "no new reviews since the last run").

### Integrations

- **Schedules**: run daily with **Only new reviews** for a new-reviews feed; add a 1–2 star filter for a complaints alert.
- **API and webhooks**: start runs and read the dataset from any language; use a webhook to get notified when a run finishes.
- **Exports**: CSV, Excel, JSON, XML and HTML from the dataset.
- **Apify integrations**: send results to Google Sheets, Slack, Zapier, Make, n8n and others from the Integrations tab.

#### Use with AI agents (MCP)

Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/apple-app-store-reviews) to Claude, Cursor or any MCP client, then ask e.g. "What do UK users complain about in the latest Duolingo reviews? Show the top issues with examples."

```json
{ "apps": ["570060128"], "countries": ["gb"], "mode": "reviews", "maxReviewsPerCountry": 200, "maxRating": 3, "aiInsights": true }
```

Failed items are not charged and carry an `errorType`.

### Tips and limitations

- **500 reviews per app and country is Apple's limit** for the public feed (see above). Add countries to get more reviews of the same app.
- **Apple's feed can lag behind the App Store page.** In late September 2026 the newest review in the feed was 1 to 2.5 days old for every app we checked. When the newest review read in a run is more than 48 hours old, the run says so (`SUMMARY.feedLagWarning`, `newestReviewInFeed`); with **Only new reviews** the late reviews simply appear in a later run. `SUMMARY.perCountry` gives the same per country: `newestReviewInFeed`, `feedLagHours` (age of the newest review over all apps of the run), `feedLagWarning` (over 48 hours), and how many apps had reviews or an empty feed. A quiet app with few reviews makes the lag look bigger than it is, so compare countries with apps that get reviews every day.
- **Search terms** are searched in the first country of your list; use **Search results per term** for the top N. App links and ids are more precise.
- **Bundle ids**: a dotted token like `com.spotify.client` or `notion.id` is looked up as a bundle id first and searched as a term if no app has it. A search hit is accepted only when its name contains the whole token (or it is `name.tld` and the app's name starts with `name`): a bundle id that does not exist gives a free `not_found` row instead of an unrelated app.
- **Invalid input**: lines that are not apps (links of other sites such as Google Play, with or without `https://`; punctuation only such as `!!!`; numbers longer than 12 digits) and country codes that do not exist get a free `invalid_input` row and the rest of the run goes on. Any other text is a search term, and its top hit is read and charged, so check your spelling. A Google Play package name such as `com.instagram.android` is looked up as an App Store bundle id and, when nothing matches, ends as a free `not_found` row. A "Reviews since" value that is not a date, or a country list with no valid code, stops the run before anything is read (free), because reading unfiltered or other-country reviews would not be what you asked for.
- **Country matters**: an app's name, price, rating and reviews differ per store; an app that is not sold in a country gets a free `not_found` row for that country.
- **Sorting by rating or oldest** reads all 500 recent reviews first (a few seconds more); newest-first and most-helpful stop as soon as they have enough.
- **Dates** are converted to UTC. Reviews have no language field; the text is in the reviewer's language.
- **Only new reviews** remembers review ids per app and country for each monitor name. Use a different monitor name for a different app list.
- If a run reports many rate-limited requests (`SUMMARY.feed.rateLimited`), lower **Feed requests in parallel** in Advanced settings.

### Terms and responsible use

- The Actor uses only Apple's public endpoints listed above, with no login. Apple's Search API documentation (checked September 2026) says the API is limited to approximately 20 calls per minute; the Actor spaces its lookups and searches accordingly and backs off when Apple answers "rate limited".
- Apple's terms for promotional content from these APIs (app icons, screenshots and other artwork) allow using it to promote the store content, next to a link or badge to the App Store; Apple may ask for it to be removed. Keep that in mind before republishing icons or screenshots.
- Reviews are written by App Store users. By default no reviewer information is returned; with **Include reviewer display names** on, only the public display name is added (no profile link or id), which can identify a person, so keep it only when you need it. Use reviews for analysis, research and product work; if you quote them publicly, attribute them to the App Store and do not present them as your own content.

### FAQ

**Does the Actor collect usage data?** The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

**Why do I get at most 500 reviews per country?** Apple's public reviews feed serves only the 500 most recent (or most helpful) reviews per app and country. The Actor does not use Apple's private web API.

**Why did I get fewer reviews than I asked for?** Check your filters (`SUMMARY.reviewsFilteredOut`), **Max reviews**, and `SUMMARY.perApp[].perCountry`: small apps have few written reviews in some countries, and a page that stayed empty after all retries is listed in `pagesMissing`.

**Is the average rating the same as the reviews?** No. `averageRating` and `ratingCount` count all star ratings, most of which have no written review; the reviews feed contains written reviews only.

**Does it support Google Play?** No, only the Apple App Store. A Google Play link gives a free `invalid_input` row and the run ends normally; nothing is charged.

**My run finished with no rows. Why?** No review matched your filters (for example a "Reviews since" date in the future, or a keyword nobody used), or no new review exists since the last run. Nothing is charged; `SUMMARY.perApp[].note` says which case it was and `reviewsFilteredOut` counts the reviews your filters removed.

**Can I run it on a schedule?** Yes. Turn on **Only new reviews since the last run**, set a monitor name, and create a daily schedule in Apify Console.

**What are the limits?** Apple's feed serves up to 500 reviews per app and country; add countries to get more of the same app. **Max reviews** caps the whole run (default 10,000, up to 1,000,000), and Apify's *Maximum cost per run* stops the run cleanly, keeping what was found.

**How fast is it?** The 5-app, 3-country run above (1,500 reviews, 15 app details rows, 5 AI insights) took 68 seconds. App lookups and search terms are spaced about 3 seconds apart to follow Apple's rate guidance, so 100 search terms add about 5 minutes; app links and ids need no search.

**Is it legal to scrape App Store reviews?** The Actor reads only Apple's public reviews feed and the iTunes Search and Lookup API, with no login, follows Apple's published rate guidance, and returns only the reviewer's public display name. Check how you may reuse the data in [Terms and responsible use](#terms-and-responsible-use). This is not legal advice.

**Does it work with the API, webhooks, Make, n8n or Zapier?** Yes. Start runs from the Apify API, a schedule or a webhook, send results to Google Sheets, Slack, Make, n8n or Zapier from the Integrations tab ([details](#integrations)), and use it from AI agents through [MCP](#use-with-ai-agents-mcp).

Found this useful? A short review on the Store helps other users find it.

# Actor input Schema

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

Main input: the run needs at least one line here. One app per line, any mix of: an App Store link (https://apps.apple.com/us/app/instagram/id389801252), a numeric app id (389801252 or id389801252), a bundle id (com.burbn.instagram) or a search term (e.g. habit tracker — the top result, or the top N with "Search results per term"). Prefix with id:, bundle: or search: to force one kind. Invalid lines and apps that are not found get an error row and are not charged.

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

Two-letter country codes, e.g. us, gb, de, fr, jp, br, in. Reviews and app details are read from each country's store (Apple keeps reviews per country). Search terms are searched in the first country. Left empty: the countries of your App Store links (apps.apple.com/gb/...), or us when the apps have no link.

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

App details are one row per app and country; reviews are one row per review. Values: both = App details + reviews; reviews = Reviews only; details = App details only (name, developer, price, rating, rating count, version, release notes, size, languages, screenshots…).

## `includeReviewerNames` (type: `boolean`):

Off (default): the reviewer's public display name (author) is left out of the rows; ratings, titles, texts and dates are the same. On: author is added to every review row. The name is a public App Store display name, often a pseudonym, but it can identify a person.

## `maxReviewsPerCountry` (type: `integer`):

Apple's public reviews feed serves at most 500 reviews per app and country (10 pages of 50, most recent or most helpful first). Counted after your filters.

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

Stop after this many reviews in total. You pay only for reviews returned: 10,000 reviews cost at most $1 on the Free plan.

## `sortBy` (type: `string`):

Which reviews Apple serves (newest or most helpful) and the order of the output rows. Values: mostRecent = Most recent first (Apple's newest-first feed); mostHelpful = Most helpful first (Apple's most-helpful feed); lowestRating = Lowest rating first (reads all 500 recent reviews, then sorts); highestRating = Highest rating first (reads all 500 recent reviews, then sorts); oldest = Oldest first (of the 500 most recent).

## `searchResultsPerTerm` (type: `integer`):

For search-term lines: take the top N apps of the App Store search (1 = first match only).

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

Keep reviews with at least this many stars. Filtered-out reviews are not charged.

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

Keep reviews with at most this many stars, e.g. 2 for complaints only.

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

A date (2026-09-01) or a period (7 days, 2 weeks, 3 months). Older reviews are skipped and not charged; with the newest-first order, reading stops at the first older page.

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

Keep reviews whose title or text contains at least one of these words or phrases (case-insensitive), e.g. crash, subscription, dark mode.

## `excludeKeywords` (type: `array`):

Drop reviews whose title or text contains any of these.

## `appVersions` (type: `array`):

Keep reviews written for these app versions only, e.g. 448.0.0, or 448 for every 448.x version.

## `aiInsights` (type: `boolean`):

One extra row per app: an AI summary of the reviews returned in this run, with top praises, complaints, feature requests and bug reports (each with an example quote). Charged per app ($0.02 on the Free plan) only when the summary is produced; needs at least 10 reviews.

## `insightsLanguage` (type: `string`):

Language of the AI summary, e.g. German or Japanese. Default: English. Example quotes stay in the reviewers' words.

## `onlyNewReviews` (type: `boolean`):

Remember the reviews of every app and country and return only reviews that were not there on the previous run of the same monitor (the first run returns everything and becomes the baseline). Reviews already seen are not output and not charged. Ideal for daily schedules.

## `monitorName` (type: `string`):

Runs with the same name are compared with each other (letters, digits, dashes). Use different names for different app lists. Default: "default".

## `dedupeReviews` (type: `boolean`):

Apple's feed can shift while it is read (new reviews push older ones to the next page), so the same review may appear twice. Duplicates are removed by review id and never charged.

## `emptyPageRetries` (type: `integer`):

Apple's reviews feed often answers with an empty page for a page that has reviews. Each empty page is asked again up to this many times (with a fresh URL so a cached empty answer is not reused). Higher = more complete, a bit slower.

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

How many apps are processed at the same time. App lookups and searches are always spaced about 3 seconds apart, as Apple asks (about 20 calls per minute).

## `feedConcurrency` (type: `integer`):

How many reviews-feed requests run at the same time across all apps. When Apple answers "rate limited" (HTTP 403/429), every request pauses together and retries later (not charged). Lower it if runs report many rate-limited requests (SUMMARY.feed).

## `appTimeoutSecs` (type: `integer`):

An app that takes longer gets a timeout error row (not charged) so one slow app cannot hold the run.

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

Only used for requests sent from Apify's network (all requests of this Actor). Apify proxy usage is billed to your Apify account. Not needed normally.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281",
    "com.spotify.client"
  ],
  "countries": [
    "us",
    "gb"
  ],
  "mode": "both",
  "includeReviewerNames": false,
  "maxReviewsPerCountry": 20,
  "maxReviews": 10000,
  "sortBy": "mostRecent",
  "searchResultsPerTerm": 1,
  "minRating": 1,
  "maxRating": 5,
  "aiInsights": false,
  "onlyNewReviews": false,
  "dedupeReviews": true,
  "emptyPageRetries": 40,
  "maxConcurrency": 3,
  "feedConcurrency": 4,
  "appTimeoutSecs": 900
}
```

# Actor output Schema

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

No description

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

No description

## `apps` (type: `string`):

No description

## `insights` (type: `string`):

No description

## `summary` (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 = {
    "apps": [
        "https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281",
        "com.spotify.client"
    ],
    "countries": [
        "us",
        "gb"
    ],
    "maxReviewsPerCountry": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidytools/apple-app-store-reviews").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/notion-notes-tasks-ai/id1232780281",
        "com.spotify.client",
    ],
    "countries": [
        "us",
        "gb",
    ],
    "maxReviewsPerCountry": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("tidytools/apple-app-store-reviews").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/notion-notes-tasks-ai/id1232780281",
    "com.spotify.client"
  ],
  "countries": [
    "us",
    "gb"
  ],
  "maxReviewsPerCountry": 20
}' |
apify call tidytools/apple-app-store-reviews --silent --output-dataset

```

## MCP server setup

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

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/Z9MXLhY9FvkLVvdB2/builds/cDq0IUfCBr6qhJfVX/openapi.json
