# App Store Reviews Scraper – iOS Apps, Search & Top Charts (`openharvest/app-store-scraper`) Actor

App Store reviews scraper for the Apple App Store (iOS): user reviews, app details, keyword search results, all apps of a developer and top charts (free, paid, grossing, new, iPad) for any country and genre. Fast HTTP-only, no browser, pay only per result.

- **URL**: https://apify.com/openharvest/app-store-scraper.md
- **Developed by:** [Enes Bulanık](https://apify.com/openharvest) (community)
- **Categories:** Marketing, Lead generation, Developer tools
- **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 results

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?

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 Reviews Scraper – iOS Apps, Search & Top Charts

App Store reviews scraper for the Apple App Store (iOS): user reviews, app details, keyword search results, all apps of a developer and top charts (free, paid, grossing, new, iPad) for any country and genre. HTTP requests only, no browser, pay only per result.

It uses Apple's own public JSON endpoints (iTunes Search & Lookup API, the App Store reviews API that apps.apple.com uses, and App Store chart feeds), with no headless browser. Measured on 2026-10-08: 3,000 Spotify reviews (US) in about 4 minutes, 600 reviews of Instagram + TikTok (UK) in 21 seconds, or a 100-app genre chart with full details in 5 seconds.

- 5 modes: `appDetails`, `reviews`, `search`, `developer`, `topCharts`
- Any App Store country (`us`, `gb`, `de`, `tr`, `jp`, ...): prices, currency, charts and reviews are localized
- **Thousands of reviews per app and country** (up to 50,000 per run and app), newest or most helpful first, with a star-rating filter and the **developer's reply**
- **App Privacy labels** ("Data Used to Track You", "Data Linked to You", "Data Not Linked to You" with data categories, data types and purposes) and **version history** (version, release date, release notes), no Apple token needed
- Input by App Store ID, App Store URL **or bundle ID** (`com.spotify.client`)
- Same field names as our **Google Play Scraper**, so you can merge iOS and Android data in one table
- Automatic retries with exponential backoff, polite concurrency, free error rows for bad inputs
- Pay only for results: **$2 per 1,000 apps**, **$0.30 per 1,000 reviews**, **+$1 per 1,000 apps** for privacy labels / version history

### What data do you get?

| App fields | Review fields |
|---|---|
| `appId`, `bundleId`, `title`, `url`, `developer`, `developerId`, `developerUrl`, `developerWebsite`, `sellerName` | `reviewId`, `appId`, `userName` |
| `score`, `ratings`, `currentVersionScore`, `currentVersionRatings` | `score` (1–5 stars), `title`, `text` |
| `price`, `currency`, `priceText`, `free` | `date`, `isEdited` |
| `genre`, `genreId`, `genres`, `contentRating`, `advisories` | `replyText`, `replyDate` (developer's reply, same names as the Google Play Scraper) |
| `released`, `updated`, `version`, `size` (bytes), `minimumOsVersion` | `country`, `sort` (`newest` / `mostHelpful`) |
| `description`, `releaseNotes`, `icon`, `screenshots`, `ipadScreenshots` | `version`, `voteCount`, `voteSum`: kept for compatibility, `null` (see FAQ) |
| `supportedDevices`, `languages`, `features`, `gameCenterEnabled`, `country` | |

List modes add context fields: `rank` and `searchTerm` (search), `developerQuery` (developer), `collection` and `category` (top charts).

**Optional extras (App details mode):**

| Input | Output field | What you get |
|---|---|---|
| `includePrivacyLabels: true` | `privacy` | The App Privacy label from the app page: `dataUsedToTrackYou`, `dataLinkedToYou`, `dataNotLinkedToYou` (each with `categories` \[`category`, `categoryId`, `dataTypes`] and `purposes` \[`purpose`, `purposeId`, `categories`]), plus `detailsProvided`, `dataNotCollected`, `managePrivacyChoicesUrl`. A section is `null` when the app does not have it. |
| `includeVersionHistory: true` | `versionHistory` | Array of `{ version, releaseDate, releaseNotes }`, newest first (Apple shows the last 25 versions). |

If Apple has no data or the request fails, the app row is still returned with `privacy`/`versionHistory` set to `null` and an `extrasError` message.

### What can you use the App Store Scraper for?

- **App Store Optimization (ASO):** track ratings, rating counts, descriptions, release notes and update frequency of your app and your competitors.
- **Review & sentiment analysis:** export thousands of reviews per app and country (with developer replies), find bugs, feature requests and complaints, and feed them into an LLM or BI tool.
- **Market research:** find every app for a keyword (e.g. `vpn`, `habit tracker`) and compare prices, ratings and genres.
- **Top charts monitoring:** schedule daily runs of Top free / paid / grossing per genre and country.
- **Competitor portfolios:** list all apps of a developer with versions, sizes and release dates.
- **Privacy & compliance research:** compare which data apps collect, link to users or use for tracking (App Privacy labels), e.g. across all top-chart apps of a category.
- **Release tracking:** analyze update cadence and release notes from the version history.
- **Cross-platform analysis:** combine with the Google Play Scraper (same field names) to compare iOS and Android.

### How to use it

1. Click **Try for free**.
2. Pick **What to scrape** (mode).
3. Fill in the field for that mode (app IDs, keywords, developers, or chart + genre).
4. Optionally set country, language and limits.
5. Click **Start** and download your data as JSON, CSV, Excel or via API.

| Mode | Required input | What you get |
|---|---|---|
| `appDetails` | `appIds` (App Store IDs, URLs or bundle IDs) | Full app details. Optionally reviews (`includeReviews`), privacy labels (`includePrivacyLabels`) and version history (`includeVersionHistory`). |
| `reviews` | `appIds` | Up to `maxReviews` reviews per app and country (max 50,000). |
| `search` | `searchTerms` | Apps matching each keyword (rank included, up to ~200 per keyword). |
| `developer` | `developerIds` (developer ID, URL or name) | All apps published by the developer. |
| `topCharts` | `collection` + `category` | Top free / paid / grossing / new apps chart (up to 100 apps, ~110 for new apps), with full details. |

### Input example

```json
{
    "mode": "reviews",
    "appIds": [
        "324684580",
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
        "com.burbn.instagram"
    ],
    "maxReviews": 1000,
    "reviewsSort": "newestAndHelpful",
    "reviewsRating": "all",
    "country": "us"
}
```

More examples:

```json
{ "mode": "search", "searchTerms": ["vpn", "photo editor"], "maxItems": 100, "country": "gb" }
```

```json
{ "mode": "topCharts", "collection": "TOP_GROSSING", "category": "GAME_PUZZLE", "maxItems": 100, "country": "tr" }
```

```json
{ "mode": "developer", "developerIds": ["324684583", "Google"], "maxItems": 200, "country": "jp", "language": "ja" }
```

```json
{ "mode": "appDetails", "appIds": ["324684580", "310633997"], "includePrivacyLabels": true, "includeVersionHistory": true, "country": "gb" }
```

### Output example

Every item has a `type` field: `"app"`, `"review"` or `"error"`. Real output (shortened):

**App item** (top chart, Turkey)

```json
{
  "type": "app",
  "collection": "TOP_GROSSING",
  "category": "GAME_PUZZLE",
  "rank": 1,
  "appId": "1482155847",
  "bundleId": "com.dreamgames.royalmatch",
  "title": "Royal Match",
  "url": "https://apps.apple.com/tr/app/royal-match/id1482155847",
  "developer": "Dream Games",
  "developerId": "1482155846",
  "developerUrl": "https://apps.apple.com/tr/developer/dream-games/id1482155846",
  "sellerName": "Dream Games Dijital Teknolojiler A.S.",
  "developerWebsite": "https://www.dreamgames.com",
  "score": 4.63884,
  "ratings": 245462,
  "price": 0,
  "currency": "TRY",
  "priceText": "Free",
  "free": true,
  "genre": "Games",
  "genreId": "6014",
  "genres": ["Games", "Casual", "Puzzle"],
  "released": "2020-07-21T07:00:00.000Z",
  "updated": "2026-09-28T07:08:56.000Z",
  "version": "38911",
  "size": 334434304,
  "minimumOsVersion": "15.0",
  "contentRating": "12+",
  "description": "King Robert needs your help to restore Royal Castle’s former glory. Break the obstacles and combine amazing power-ups...",
  "releaseNotes": "Are you ready for an amazing new update?\n\n• Get ready for amazing 100 NEW LEVELS! ...",
  "icon": "https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/24/de/aa/24deaa83-7e15-c811-cc29-5f8dca26bbf9/AppIcon-0-0-1x_U007emarketing-0-8-0-85-220.png/512x512bb.jpg",
  "screenshots": ["https://is1-ssl.mzstatic.com/image/thumb/PurpleSource211/v4/8f/ab/b1/8fabb162-ffe6-f98d-16d0-5c1fb627ff3f/044647dc-8211-4c71-9173-a01259dec485_RM_app-store-image-5.5inch-1.png/392x696bb.png"],
  "supportedDevices": ["iPhone5s", "iPadAir", "iPadAirCellular", "iPadMiniRetina"],
  "languages": ["AR", "EN", "FR", "DE", "IT", "JA"],
  "features": ["iosUniversal"],
  "country": "tr",
  "scrapedAt": "2026-10-07T19:14:14.048Z"
}
```

**Privacy labels and version history** (`includePrivacyLabels` + `includeVersionHistory`, Things 3, US; app fields omitted)

```json
{
  "type": "app",
  "appId": "904237743",
  "title": "Things 3",
  "version": "3.24.2",
  "privacy": {
    "detailsProvided": true,
    "dataNotCollected": false,
    "dataUsedToTrackYou": null,
    "dataLinkedToYou": {
      "title": "Data Linked to You",
      "description": "The following data, which may be collected and linked to your identity, may be used for the following purposes:",
      "categories": [{ "category": "User Content", "categoryId": "USER_CONTENT", "dataTypes": ["Other User Content"] }],
      "purposes": [{
        "purpose": "App Functionality",
        "purposeId": "APP_FUNCTIONALITY",
        "categories": [{ "category": "User Content", "categoryId": "USER_CONTENT", "dataTypes": ["Other User Content"] }]
      }]
    },
    "dataNotLinkedToYou": {
      "title": "Data Not Linked to You",
      "description": "The following data, which may be collected but is not linked to your identity, may be used for the following purposes:",
      "categories": [{ "category": "Diagnostics", "categoryId": "DIAGNOSTICS", "dataTypes": ["Other Diagnostic Data"] }],
      "purposes": [{
        "purpose": "App Functionality",
        "purposeId": "APP_FUNCTIONALITY",
        "categories": [{ "category": "Diagnostics", "categoryId": "DIAGNOSTICS", "dataTypes": ["Other Diagnostic Data"] }]
      }]
    },
    "managePrivacyChoicesUrl": null
  },
  "versionHistory": [
    { "version": "3.24.2", "releaseDate": "2026-09-22T11:02:19.000Z", "releaseNotes": "• Tweaked the appearance of to-dos shown by Siri on iOS 27. ..." },
    { "version": "3.24.1", "releaseDate": "2026-09-14T22:29:40.000Z", "releaseNotes": "Things is ready for iOS 27 and watchOS 27, ..." }
  ]
}
```

For tracking data (`dataUsedToTrackYou`, e.g. Spotify: Contact Info, Identifiers, Usage Data) Apple lists categories only, so `purposes` is empty.

**Review item** (TikTok, UK, with developer reply; reviewer name shortened)

```json
{
  "type": "review",
  "reviewId": "14633693838",
  "appId": "835599320",
  "userName": "chantel g.",
  "score": 4,
  "title": "Needs to allow deleting messages of both ends",
  "text": "Tiktok is good but the only thing that needs upgrading is allowing to delete messages of both ends or when blocking or deleting a conversation the chats delete for both users",
  "date": "2026-10-06T09:19:26.000Z",
  "version": null,
  "voteCount": null,
  "voteSum": null,
  "isEdited": false,
  "replyText": "Hi, thanks for your feedback!\nWe'll be sure to share your suggestion with our team for consideration. We appreciate your input, and we're always working to improve the TikTok experience!",
  "replyDate": "2026-10-07T13:00:11.000Z",
  "country": "gb",
  "sort": "newest",
  "scrapedAt": "2026-10-08T08:32:08.942Z"
}
```

In App details mode with `includeReviews`, review rows also carry `appTitle`.

**Error item (free)**

```json
{
  "type": "error",
  "target": "reviews 999999999",
  "errorCode": "NOT_FOUND",
  "error": "App 999999999 not found in the DE App Store.",
  "country": "de"
}
```

Possible `errorCode` values: `INVALID_INPUT`, `NOT_FOUND`, `BAD_REQUEST` (e.g. a country without an App Store), `SCRAPE_FAILED`. Error rows are never charged.

The **Output** tab has ready-made views: **Overview**, **Apps**, **Privacy labels & version history** and **Reviews**. A `RUN_SUMMARY` record in the key-value store lists counts and every target that failed.

### Pricing

This Actor uses **pay-per-event** pricing. You pay only for results that land in your dataset:

| Event | Price | Per 1,000 |
|---|---|---|
| `app-result`: one app pushed to the dataset (any mode) | $0.002 | **$2.00** |
| `review-result`: one review pushed to the dataset | $0.0003 | **$0.30** |
| `app-extras`: privacy labels and/or version history for one app (charged **once per app**, even with both options on) | $0.001 | **$1.00** |
| Error rows (invalid input, app not found...) | free | free |

`app-extras` is only charged when Apple returned data (published privacy details or at least one version). If the developer has not published privacy details and there is no version history, or the request failed, you pay only for the app row.

Examples:

- 1 app + 20 reviews (prefilled input) ≈ **$0.008**
- 100 apps with privacy labels + version history ≈ **$0.30** ($0.20 apps + $0.10 extras)
- 1,000 reviews of one app ≈ **$0.30**
- Top 100 grossing games in 5 countries (500 apps, full details) ≈ **$1.00**

Platform usage (compute) is included. If you set a **maximum cost per run**, the Actor stops cleanly as soon as that limit is reached and keeps everything scraped up to that point.

### Use with AI agents (MCP)

This Actor works as a tool for AI agents through the [Apify MCP server](https://mcp.apify.com) (Claude, ChatGPT, Cursor, n8n and other MCP clients). Add `apify/mcp` with this Actor enabled and ask, for example, *"Get the 200 newest 1-star reviews of Spotify in the UK App Store and summarize the main complaints."* The agent calls the Actor with an input like:

```json
{
  "mode": "reviews",
  "appIds": ["324684580"],
  "country": "gb",
  "reviewsSort": "newest",
  "reviewsRating": "1",
  "maxReviews": 200
}
```

Or *"Which of these apps track users across other companies' apps, and what changed in their last updates?"*:

```json
{
  "mode": "appDetails",
  "appIds": ["324684580", "310633997", "389801252"],
  "country": "us",
  "includePrivacyLabels": true,
  "includeVersionHistory": true
}
```

The agent then reads `privacy.dataUsedToTrackYou.categories` (null = no tracking) and `versionHistory[].releaseNotes`.

Field names match the Google Play Scraper, so an agent can compare iOS and Android results without mapping fields.

### FAQ

**How many reviews can I get per app?**
As many written reviews as Apple has for that country, up to `maxReviews` (max 50,000 per app and run). Reviews come from the same public reviews API the apps.apple.com "Ratings & Reviews" page uses (20 per request). In our tests (2026-10-08) Spotify US could be paged back more than 150,000 reviews (about 2 years), and runs collected 200–3,000 reviews per app in the US, UK, Germany and Turkey without hitting any limit. Smaller apps simply have fewer written reviews. Reviews are written per storefront, so run the Actor for more countries (e.g. `us`, `gb`, `ca`, `au`) to collect more.

**How fast is it?**
Apple's reviews API answers many requests with "API capacity exceeded" (HTTP 429): 43–62% of requests in our test runs. The Actor retries them automatically (short exponential backoff with jitter, `Retry-After` honored, a new proxy session per retry if you enable a proxy), so you still get every page. Measured: 200 reviews per app in 20–30 s, 500 reviews of 2 apps in 96 s, 3,000 reviews of one app in 251 s (7–29 reviews per second overall). 1- and 5-star filters use Apple's own filtered lists and are just as fast; 2–4-star filters must scan more reviews.

**Why are `version`, `voteCount` and `voteSum` null?**
Apple's current reviews API does not return the app version or helpful-vote counts. The legacy customer-reviews RSS feed did, but since 2026 it returns no reviews for most apps and countries, so it is only used as an automatic fallback when the reviews API keeps failing (the fields are filled then, max 500 reviews per sort order). The fields are kept so existing integrations do not break.

**Why do I get fewer reviews than the app's rating count?**
Most App Store ratings are stars without text. Only written reviews are available.

**Can I use bundle IDs instead of App Store IDs?**
Yes. `com.spotify.client`, `324684580`, `id324684580` and `https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580` all work.

**How big are the top charts?**
Apple publishes up to 100 apps per chart and genre (about 110 for the "new apps" charts). Every chart entry is enriched with full app details (rating, rating count, version, size, description...) at no extra cost.

**Can I scrape another country or language?**
Yes. Set `country` (e.g. `de`, `tr`, `jp`, `br`). Prices, currency, charts, availability and reviews follow that storefront. `language` (e.g. `en`, `ja`) changes app texts when the developer provides that localization; leave it empty to get the storefront's default language.

**What is the rating `score`?**
The average star rating across all ratings in the selected country (`ratings` is the number of ratings). `currentVersionScore`/`currentVersionRatings` are for the current version.

**Where do the privacy labels and version history come from? Do I need an Apple token?**
From the same public catalog endpoint the apps.apple.com web page uses (`apps.apple.com/api/apps/v1/catalog/{country}/apps/{id}`). No login or bearer token is needed. One request per app returns both extras. Apple often answers "API capacity exceeded" (HTTP 429) on this endpoint, so the Actor requests one app at a time and retries automatically. Expect roughly 1–5 seconds per app when extras are enabled. Labels are in the storefront's language. Set `language` to a full locale such as `en-GB` to get them in another language the storefront supports.

**Why is `privacy` null or `detailsProvided` false?**
`detailsProvided: false` means the developer has not published App Privacy details (Apple shows "No Details Provided"). `dataNotCollected: true` means the developer says no data is collected. `privacy: null` with an `extrasError` means Apple did not answer after all retries; the app row is still saved and `app-extras` is not charged.

**How many versions are in `versionHistory`?**
Apple shows the latest 25 versions, the same as the "Version History" list on the app page.

**Do I need a proxy?**
Usually not. All test runs above used no proxy. For very large or frequent runs, enable Apify Proxy in the input; each retry then uses a fresh IP.

**Can I integrate it with my tools?**
Yes. Use the Apify API, webhooks, or integrations (Make, Zapier, n8n, Google Sheets, Slack, Airbyte, LangChain, MCP...). You can also schedule runs to monitor charts or reviews every day.

### Is it legal to scrape the App Store?

This Actor only extracts **publicly available data** that Apple publishes without login through its public endpoints and feeds. It does not access private accounts. To limit personal data, **only the reviewer's public display name is kept**; no reviewer profile links or other identifiers are collected. Reviews may still contain personal data, so make sure your use complies with GDPR/CCPA and other applicable laws and with Apple's terms. If you are unsure, consult a lawyer. Read more in Apify's blog post [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

### Related actors

- Google Play Scraper – Apps, Reviews, Search & Top Charts (sibling Actor with the same field names)
- Chrome Web Store Scraper – Extensions, Users, Ratings & Reviews
- Shopify App Store Scraper – Apps, Pricing Plans & App Reviews

### Support

Found a bug or need a feature (e.g. in-app purchases, similar apps)? Open an issue in the **Issues** tab.

# Actor input Schema

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

<b>App details</b> – full details for App Store IDs, URLs or bundle IDs (optionally with reviews).<br><b>Reviews</b> – user reviews for apps.<br><b>Search</b> – apps matching keywords.<br><b>Developer</b> – all apps of a developer.<br><b>Top charts</b> – top free / paid / grossing / new apps, optionally in one genre.

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

Used by <b>App details</b> and <b>Reviews</b> modes. Enter numeric App Store IDs (e.g. <code>324684580</code>), App Store URLs like <code>https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580</code>, or bundle IDs (e.g. <code>com.spotify.client</code>).

## `includeReviews` (type: `boolean`):

In <b>App details</b> mode, also scrape up to <i>Max reviews per app</i> reviews for every app.

## `includePrivacyLabels` (type: `boolean`):

In <b>App details</b> mode, add a <code>privacy</code> object with the app's App Privacy label: <i>Data Used to Track You</i>, <i>Data Linked to You</i> and <i>Data Not Linked to You</i>, each with data categories, data types and purposes. Charged once per app with the <code>app-extras</code> event (together with version history).

## `includeVersionHistory` (type: `boolean`):

In <b>App details</b> mode, add a <code>versionHistory</code> array (<code>version</code>, <code>releaseDate</code>, <code>releaseNotes</code>, newest first; Apple shows up to the last 25 versions). Charged once per app with the <code>app-extras</code> event (together with privacy labels).

## `searchTerms` (type: `array`):

Used by <b>Search</b> mode. One keyword per line, e.g. <code>vpn</code>, <code>photo editor</code>. The App Store returns up to ~200 apps per keyword.

## `searchPrice` (type: `string`):

Used by <b>Search</b> mode. Keep only free or only paid apps.

## `developerIds` (type: `array`):

Used by <b>Developer</b> mode. Numeric developer ID (e.g. <code>324684583</code>), developer page URL (e.g. <code>https://apps.apple.com/us/developer/spotify/id324684583</code>) or developer name exactly as shown on the App Store (e.g. <code>Spotify</code>).

## `collection` (type: `string`):

Used by <b>Top charts</b> mode. Apple publishes up to 100 apps per chart (new-app charts ~110).

## `category` (type: `string`):

Used by <b>Top charts</b> mode. <code>APPLICATION</code> = all apps, <code>GAME</code> = all games.

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

Maximum number of app results per search keyword, per developer, or for the top chart.

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

Maximum number of reviews per app and country (Reviews mode, or App details mode with reviews enabled). There is no fixed Apple cap: popular apps have tens of thousands of written reviews per country (we paged Spotify US back more than 150,000 reviews). Expect roughly 7–29 reviews per second (Apple rate-limits this API; the Actor retries automatically).

## `reviewsSort` (type: `string`):

Which reviews to scrape. <b>Newest first</b> is best for monitoring and large exports. <b>Most helpful</b> is Apple's default order on the app page. <b>Newest + most helpful</b> reads the newest list first, then fills up with most helpful reviews not seen yet (de-duplicated).

## `reviewsRating` (type: `string`):

Only keep reviews with this star rating. 1-star and 5-star reviews (newest first) come from Apple's own filtered lists, so they are as fast as unfiltered. 2-, 3- and 4-star reviews are filtered from the newest/most helpful lists; at most 15× <i>Max reviews per app</i> reviews are scanned.

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

Two-letter ISO country code of the App Store to scrape, e.g. <code>us</code>, <code>gb</code>, <code>de</code>, <code>tr</code>, <code>jp</code>. Affects prices, availability, charts and reviews (reviews are per country).

## `language` (type: `string`):

Optional language for app texts (title, description, release notes), e.g. <code>en</code>, <code>de</code>, <code>ja</code>, <code>pt-BR</code>. Leave empty to get the storefront's default language. Only works if the developer provides that localization. Privacy labels need a locale the storefront supports, e.g. <code>en-GB</code> for <code>de</code>.

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

Optional. Apple's public endpoints work without a proxy; the reviews API answers many requests with HTTP 429 and the Actor retries them automatically. With Apify Proxy every retry uses a new session (IP), which may help for very large review exports.

## Actor input object example

```json
{
  "mode": "appDetails",
  "appIds": [
    "324684580",
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.burbn.instagram"
  ],
  "includeReviews": true,
  "includePrivacyLabels": false,
  "includeVersionHistory": false,
  "searchTerms": [
    "vpn",
    "habit tracker"
  ],
  "searchPrice": "all",
  "developerIds": [
    "324684583",
    "https://apps.apple.com/us/developer/google-llc/id281956209",
    "Spotify"
  ],
  "collection": "TOP_FREE",
  "category": "APPLICATION",
  "maxItems": 50,
  "maxReviews": 20,
  "reviewsSort": "newest",
  "reviewsRating": "all",
  "country": "us",
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the default dataset (JSON, CSV, Excel and more via the dataset export).

## `files` (type: `string`):

Records saved in the default key-value store, e.g. the run summary.

# 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 = {
    "mode": "appDetails",
    "appIds": [
        "324684580"
    ],
    "includeReviews": true,
    "maxItems": 50,
    "maxReviews": 20,
    "country": "us",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/app-store-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "appDetails",
    "appIds": ["324684580"],
    "includeReviews": True,
    "maxItems": 50,
    "maxReviews": 20,
    "country": "us",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("openharvest/app-store-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "appDetails",
  "appIds": [
    "324684580"
  ],
  "includeReviews": true,
  "maxItems": 50,
  "maxReviews": 20,
  "country": "us",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call openharvest/app-store-scraper --silent --output-dataset

```

## MCP server setup

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

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VhYriqJiGO9kVkGEB/builds/IA5NsUjuKc1s4Ksba/openapi.json
