# iOS App Store Reviews Scraper & iTunes Reviews API (`wintersworks/appstore-reviews-scraper`) Actor

Scrape iOS App Store reviews and app details from the Apple iTunes endpoints. Output: rating, title, text, date, version, topic tags. Rating, date and keyword filters. $0.08 per 1,000 reviews, $1 per 1,000 app details.

- **URL**: https://apify.com/wintersworks/appstore-reviews-scraper.md
- **Developed by:** [Winters Works](https://apify.com/wintersworks) (community)
- **Categories:** Developer tools, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Apple App Store Reviews Scraper: iOS Reviews and Ratings by Country, CSV/JSON, $0.08 per 1K

Pull Apple App Store reviews for any iOS app, across one country or every storefront, and get clean JSON, CSV or Excel back. **Reviews cost $0.08 per 1,000 ($0.00008 each). App details cost $1 per 1,000.** You pay only for items returned after your filters.

Independent tool by Winters Works. Apple and App Store are trademarks of Apple Inc.

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

Give it app IDs, App Store URLs or search terms, plus a list of countries. It reads Apple's public iTunes Lookup and Search endpoints and the public customer-reviews feed, then writes one dataset row per review. No login, no proxies, no browser.

Every review comes with:

- rating (1 to 5), title and full text
- date and the app version the reviewer was on
- author name and author profile link (when Apple provides one)
- helpful vote count
- country (storefront) and platform (`ios`)
- topic tags such as `crash`, `price`, `ads`, `login`, `performance`, `praise`
- a direct link to the app's review page

Optionally it also writes one `app-details` row per app and country: current price, average rating, rating count, genre, developer, version, release notes, minimum OS and more.

### Why use this one?

- **Many countries in one run.** Pass `["us","gb","de","fr","jp"]` and get one combined dataset. Or pass `["all"]` to try every App Store storefront (about 170). No need to start a separate run per country.
- **Filters that save money.** Minimum and maximum star rating, a keyword filter (all words must appear), and a `sinceDate` cutoff. Filtered-out reviews are never charged.
- **Topic tags.** Each review is tagged by simple keyword rules, so you can count complaints about crashes or pricing without reading everything. The tags are a rough guide, not sentiment analysis.
- **Low price per 1,000 reviews.** $0.08 per 1,000, with a spend limit you control.
- **A hard cap on cost.** `maxReviewsPerApp` limits each country and `maxReviewsTotalPerApp` limits the total per app, so an "all countries" run cannot get out of hand.

### How much does it cost?

Pricing is pay per event. There is no monthly rental and no minimum. You're never charged for failed or empty lookups, and the run's status message tells you why any input came back short (Apple's feed returned nothing for an app or country, Apple's RSS only exposes the latest ~500 reviews per country, a cap was reached, or the app wasn't found).

| Event | Price | Per 1,000 |
|---|---|---|
| Review returned | $0.00008 | $0.08 |
| App-details row | $0.001 | $1.00 |

Worked examples:

| What you pull | Items | Cost |
|---|---|---|
| 500 reviews, one app, one country | 500 | $0.04 |
| 1,000 reviews | 1,000 | $0.08 |
| 5 competitor apps x 200 reviews | 1,000 | $0.08 |
| 5,000 reviews x 10 countries | 50,000 | $4.00 |
| 10,000 reviews | 10,000 | $0.80 |
| 100 app-details rows | 100 | $0.10 |
| One app, `countries: ["all"]`, default total cap | up to 2,000 | up to $0.16 |

Apify's free plan includes roughly $5 of monthly platform credit, which at these prices covers tens of thousands of reviews. Platform usage (compute) is small for this actor, since it only makes lightweight HTTP requests. You can also set a maximum cost per run in the run options, and the actor stops cleanly when it reaches it.

### Quick start

1. Open the actor in Apify Console and click **Try for free** (or **Start**).
2. Paste one or more app IDs or App Store URLs into **Apps**. The app ID is the number after `id` in the URL: `https://apps.apple.com/us/app/facebook/id284882215` has ID `284882215`. Full URLs work too.
3. Pick countries, set **Max reviews per app**, and press **Start**. Results appear in the **Output** tab and can be downloaded as JSON, CSV, Excel, XML or HTML.

You can also find apps by name with **Search terms**. Each term is resolved through Apple's Search API and the top result is used (change **Apps per search term** to take more).

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `apps` | array | `["284882215"]` | App IDs or App Store URLs |
| `searchTerms` | array | none | Names to look up; top results become apps |
| `searchLimit` | integer | 1 | Apps taken per search term (1 to 25) |
| `countries` | array | `["us"]` | Two-letter storefront codes, or `["all"]` for every storefront |
| `maxReviewsPerApp` | integer | 100 | Cap per app and country (1 to 500) |
| `maxReviewsTotalPerApp` | integer | 2000 | Cap per app across all countries. Remaining countries are skipped once reached |
| `minRating` | integer | none | Only reviews with at least this many stars |
| `maxRating` | integer | none | Only reviews with at most this many stars |
| `sinceDate` | string | none | Only reviews on or after `YYYY-MM-DD` |
| `keyword` | string | none | Title or text must contain all these words |
| `includeAppDetails` | boolean | false | Also output one app-details row per app and country |

#### Example 1: one app, recent reviews

```json
{
  "apps": ["284882215"],
  "countries": ["us"],
  "maxReviewsPerApp": 200
}
```

#### Example 2: competitor sweep

```json
{
  "apps": ["284882215", "324684580", "310633997", "389801252", "835599320"],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 200,
  "includeAppDetails": true
}
```

#### Example 3: international complaints only

```json
{
  "apps": ["284882215"],
  "countries": ["us", "gb", "de", "fr", "br"],
  "maxRating": 2,
  "sinceDate": "2026-09-01",
  "maxReviewsPerApp": 100
}
```

#### Example 4: every storefront, with a spending cap

```json
{
  "apps": ["284882215"],
  "countries": ["all"],
  "maxReviewsPerApp": 50,
  "maxReviewsTotalPerApp": 1000
}
```

With `["all"]` the actor goes through the storefronts one at a time, biggest markets first (us, gb, ca, au, de, fr, jp and so on), and stops adding countries for an app once `maxReviewsTotalPerApp` is reached. Storefronts where the app is not sold are skipped quietly.

### Output

A review record:

```json
{
  "type": "review",
  "platform": "ios",
  "appId": "284882215",
  "appName": "Facebook",
  "country": "us",
  "reviewId": "14645259799",
  "title": "Too many ads",
  "text": "I can barely scroll without hitting another ad.",
  "rating": 1,
  "version": "582.0.0",
  "author": "ExampleUser",
  "authorUrl": "https://itunes.apple.com/us/reviews/id000000000",
  "date": "2026-10-09T10:11:58.000Z",
  "voteCount": 0,
  "topics": ["ads"],
  "url": "https://apps.apple.com/us/app/id284882215?see-all=reviews"
}
```

| Field | Meaning |
|---|---|
| `type` | `review` or `app-details` |
| `platform` | Always `ios` |
| `appId`, `appName` | App identifier and name |
| `country` | Storefront the review was posted in |
| `reviewId` | Apple's review ID |
| `title`, `text` | What the reviewer wrote, in the language written |
| `rating` | 1 to 5 stars |
| `version` | App version the review was written for |
| `author`, `authorUrl` | Reviewer display name and profile link when present |
| `date` | ISO timestamp of the review |
| `voteCount` | Number of "helpful" votes Apple reports |
| `topics` | Keyword-rule tags |
| `url` | Link to the app's reviews page |

App-details rows (`type: "app-details"`) include `bundleId`, `developer`, `genre`, `price`, `averageRating`, `ratingCount`, `averageRatingCurrentVersion`, `version`, `releaseNotes`, `releaseDate`, `minimumOsVersion`, `contentRating`, `fileSizeBytes`, `description`, `iconUrl` and `url`.

Fields by use case: ASO work mostly uses `text`, `title`, `country` and `rating`. Sentiment and churn work uses `rating`, `topics` and `voteCount`. Release QA uses `version`, `date` and `rating`.

### Use cases

#### How do I do App Store Optimization (ASO) research from reviews?

Reviews are the words real users use to describe an app. Pull a few hundred reviews for your app and for competitors, then look at the nouns and phrases that repeat: "widget", "offline mode", "sync", "family plan". Those are candidates for your subtitle, keyword field and screenshots. Run the same apps across several countries to see how the vocabulary changes by language. Use `keyword` to isolate reviews that mention a feature you are thinking about adding.

#### How do I track competitor app ratings over time?

Turn on `includeAppDetails` and schedule the actor weekly for a list of competitor IDs. Each run writes a snapshot with `averageRating`, `ratingCount` and the current `version`. Append the snapshots to a spreadsheet or database and you have a rating history. Reviews give you the color: set `sinceDate` to the last run and read only the new ones, or tag them by `topics` to see what changed after a competitor's release.

#### How do I find what users complain about after a release?

Run with `maxRating: 2` and a recent `sinceDate`. Group the results by `version` and count the `topics` tags. A version with a spike in `crash` or `login` reviews is a quick signal that something broke. Read the highest `voteCount` reviews first, since other users agreed with them. This works for your own app and for competitors, whose bad releases are your acquisition opportunity.

#### How do I compare app sentiment across countries?

Pass a list of countries and compare average `rating` and topic counts per `country`. A pricing complaint that shows up only in one storefront often points to a local price tier problem. Language-specific complaints usually mean a translation or payment-method gap. Note that `topics` tags are keyword rules in English, so non-English reviews are mostly untagged and are better read directly or processed with your own tools.

### How do I export App Store reviews to CSV?

Run the actor, open the **Output** tab, choose **Export**, and pick CSV or Excel. You can select which fields to include and whether to flatten the `topics` array. Through the API, call the dataset items endpoint with `format=csv`:

```
https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=csv&token=<YOUR_APIFY_TOKEN>
```

### Code examples

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("wintersworks/appstore-reviews-scraper").call(run_input={
    "apps": ["284882215"],
    "countries": ["us", "gb"],
    "maxReviewsPerApp": 100,
    "maxRating": 2,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["country"], item["rating"], item["title"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('wintersworks/appstore-reviews-scraper').call({
    apps: ['284882215'],
    countries: ['us', 'gb'],
    maxReviewsPerApp: 100,
    maxRating: 2,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'reviews');
```

#### curl

```bash
curl -X POST "https://api.apify.com/v2/acts/wintersworks~appstore-reviews-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"apps":["284882215"],"countries":["us"],"maxReviewsPerApp":50}'
```

The synchronous endpoint is handy for small runs. For larger ones, start a run and poll or use a webhook.

### Scheduling and webhooks

Open **Schedules** in Apify Console and create a schedule (daily, weekly, or any cron expression) for the actor with your saved input. For a monitoring job, set `sinceDate` to a recent date, or run weekly with `maxReviewsPerApp` set to something larger than your typical weekly volume and remove duplicates by `reviewId` downstream.

To react when a run finishes, add a webhook on the `ACTOR.RUN.SUCCEEDED` event pointing at your own URL, a Slack incoming webhook, or an automation tool. The webhook payload includes the run's dataset ID, so your receiver can fetch the new rows.

### Integrations and AI agents (MCP)

As with any Apify actor, the results can be sent onward with Apify's platform integrations: Make, n8n, Zapier, Google Sheets, Slack, Airtable, plus the REST API and the official JavaScript and Python clients. These are features of the Apify platform; set them up from the **Integrations** tab of the actor.

#### Use it from Claude, Cursor or other MCP clients

Apify hosts an MCP server that exposes actors as tools. Point your client at this actor with the URL below and an Apify API token.

Server URL: `https://mcp.apify.com?actors=wintersworks/appstore-reviews-scraper`

Config for Claude Desktop, Cursor or Claude Code (adjust to your client's format):

```json
{
  "mcpServers": {
    "appstore-reviews": {
      "url": "https://mcp.apify.com?actors=wintersworks/appstore-reviews-scraper",
      "headers": {
        "Authorization": "Bearer YOUR_APIFY_TOKEN"
      }
    }
  }
}
```

Example prompts:

1. "Pull the last 200 one-star and two-star reviews for app 284882215 in us and gb, then group the complaints by theme."
2. "Compare average rating and the most common complaint topics for these five app IDs in the us store, and tell me which one has the most crash complaints."
3. "Get this week's new reviews for app 324684580 in de, fr and es and summarize what users ask for."

### Known limitations

- Apple's public review feed exposes roughly the 500 most recent reviews per app per country (10 pages of 50). That limit comes from Apple, not from this actor. Totals depend on the app and the storefronts you choose.
- Reviews are returned most recent first. Other sort orders are not offered.
- Developer replies are not part of the public feed, so they are not included.
- Star ratings without written text are not included. Use the app-details row for overall rating counts.
- The feed is sometimes empty for an app, or empty for a while. When that happens the run still completes, logs a clear warning, and says so in the run's status message.
- Topic tags are English keyword rules, not AI sentiment analysis.
- Google Play is not covered. This actor handles the Apple App Store only.

### Troubleshooting

**The run finished with no reviews.** First check the warning in the log and the run status message. The usual causes: Apple's feed returned nothing for that app or country (sometimes temporary, so try again later), the app is not sold in that storefront, or your filters (rating, keyword, date) excluded everything. Turn on `includeAppDetails` to confirm the app ID resolves.

**Fewer reviews than I asked for.** Apple only exposes a recent window per country. Add more countries, or use `["all"]`.

**"App not found in storefront".** The app is not available in that country, or the ID is wrong. Check the number in the App Store URL.

### FAQ

#### What App Store review data can I extract?

Rating, title, text, date, app version, author name and link, helpful votes, country and topic tags for each review, plus optional app metadata such as price, genre, developer, average rating and release notes.

#### Can I scrape all countries at once?

Yes. Set `countries` to `["all"]` and the actor goes through every App Store storefront, skipping the ones where the app is not sold. It stops adding countries for an app once `maxReviewsTotalPerApp` is reached (2,000 by default), which keeps the bill predictable.

#### How many reviews can I get per app?

Apple's public feed exposes roughly the 500 most recent reviews per app per country. The total you get depends on the app and how many storefronts you include. Popular apps with many storefronts give you more than small ones.

#### Can I export App Store reviews to CSV or Excel?

Yes. Use the Export option on the Output tab or the dataset API with `format=csv` or `format=xlsx`.

#### Can I filter reviews by date?

Yes, with `sinceDate`. Because the feed is newest first, the actor stops paging as soon as it reaches older reviews, so you do not pay for them.

#### Can I get developer replies?

No. Developer responses are not in Apple's public feed.

#### Does it work for Google Play?

No. This actor covers the Apple App Store only.

#### Why did my run return no reviews?

Apple's feed is sometimes empty for a particular app, or empty temporarily. The actor logs a warning and sets the status message, and never fails the run for this. Retry later, check your filters, and use `includeAppDetails` to confirm the app exists.

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

The actor uses Apple's public iTunes endpoints and collects only review content that is publicly visible, without logging in. Legality depends on your jurisdiction and your use, so you are responsible for how you use the data, including privacy, copyright and Apple's terms. If you are unsure, ask a lawyer.

#### Which sort order do I get?

Most recent first. Other sort orders are not offered.

#### How fast is it, and are there rate limits?

Roughly 50 reviews per request, with a short polite delay between requests. A single app and country with 500 reviews takes about ten seconds. If Apple slows requests down, the actor retries with backoff.

#### Can I schedule it, and how much does it cost?

Yes, use Apify Schedules. Reviews are $0.08 per 1,000 and app details are $1 per 1,000. See the cost table above for examples.

#### Where do I get support?

Open an issue on the actor's page in Apify Console and we will reply. You can also email wintersworks.shop@gmail.com.

### Support

Built and maintained by Winters Works. Questions or feature requests: open an issue on the actor page or email wintersworks.shop@gmail.com.

### More from Winters Works

- [Bulk Email Verifier & MX Record Checker](https://apify.com/wintersworks/bulk-email-verifier-dns): clean an email list before you send. Syntax, MX lookup, disposable and role-address checks, no SMTP probing.
- [Greenhouse, Lever & Ashby Jobs API](https://apify.com/wintersworks/ats-job-board-feeds): every open role from company careers boards on 5 ATS platforms, normalized into one dataset.
- [Website Tech Stack & SEO Audit](https://apify.com/wintersworks/website-tech-stack-seo-audit): see what a list of sites runs on, plus SEO basics, security headers, SSL expiry and a 0-100 score.
- [ClinicalTrials.gov Scraper & Monitor](https://apify.com/wintersworks/clinical-trials-search-monitor): search trials by condition, drug, sponsor or location, and track what's new or updated between runs.

# Actor input Schema

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

Numeric app IDs (e.g. 284882215) or App Store URLs (https://apps.apple.com/us/app/facebook/id284882215).

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

Optional. Each term is resolved to apps via Apple's iTunes Search API (first country in the list).

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

How many top search results to take per term.

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

Two-letter App Store country codes, e.g. us, gb, de. Reviews are fetched per country. Use \["all"] to try every App Store storefront (about 175); the run stops fetching more countries for an app once maxReviewsTotalPerApp is reached, so cost stays bounded. Storefronts where the app is not sold are skipped.

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

Cap per app and country. Apple's feed exposes at most about 500 recent reviews per app per country.

## `maxReviewsTotalPerApp` (type: `integer`):

Total cap per app across all countries. Once reached, remaining countries are skipped. At $0.08 per 1,000 reviews, 2,000 means at most about $0.16 per app. Mainly useful with countries: \["all"].

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

Only reviews with at least this many stars (1-5).

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

Only reviews with at most this many stars (1-5).

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

Only reviews on/after this date (YYYY-MM-DD). Stops paging early because feed is newest-first.

## `keyword` (type: `string`):

Only reviews whose title or text contains ALL of these words (case-insensitive).

## `includeAppDetails` (type: `boolean`):

Also output one app-details item per app and country (price, rating, genre, developer, version, release notes). Charged as a separate event.

## Actor input object example

```json
{
  "apps": [
    "284882215"
  ],
  "searchLimit": 1,
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 20,
  "maxReviewsTotalPerApp": 2000,
  "includeAppDetails": false
}
```

# Actor output Schema

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

All result items from the run's default dataset.

# 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": [
        "284882215"
    ],
    "countries": [
        "us"
    ],
    "maxReviewsPerApp": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("wintersworks/appstore-reviews-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 = {
    "apps": ["284882215"],
    "countries": ["us"],
    "maxReviewsPerApp": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("wintersworks/appstore-reviews-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 '{
  "apps": [
    "284882215"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 20
}' |
apify call wintersworks/appstore-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wintersworks/appstore-reviews-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/hdRwIlUjnKNYe9HlI/builds/3jZqA42Gsj5Y0D0Px/openapi.json
