# App Store Reviews Scraper | Full History, Dev Replies, $0.50/1K (`kesar_chen/app-store-reviews-scraper`) Actor

Full review history of any iOS app in 184 country stores: rating histogram, version numbers, optional developer replies, incremental runs. MCP-ready. Pay per review, no start fee.

- **URL**: https://apify.com/kesar_chen/app-store-reviews-scraper.md
- **Developed by:** [Kesar Chen](https://apify.com/kesar_chen) (community)
- **Categories:** Developer tools, AI
- **Security:** Limited permissions
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 review scrapeds

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

## App Store Reviews Scraper

Pull the **full review history** of any iOS app, in any of the 184 country stores, as clean JSON. Not the newest 500: the whole history as far as Apple still serves it, newest first and filterable by date, rating and keyword, with a 1–5 star histogram, optional developer replies, and an incremental mode that returns only what is new since your last run. **$0.50 per 1,000 reviews, no start fee**: a 30,000-review app costs about $15 once, and a daily watch on 10 competitors in 3 countries runs about $3 a month.

### Why this one

- **Deep and date-sortable at the same time.** Most deep review pulls come back in relevance order and cannot be sliced by date. This one walks the full history newest-first, so `sinceDate: "12 months"` means exactly that, and `maxRating: 2` with `keywords: ["crash"]` returns only the rows you will read.
- **Only new reviews on every scheduled run.** Turn on `incremental` and the Actor remembers what it has already returned per app and country. Your dataset never needs deduping and you never pay twice for the same review.
- **You always know how deep it got.** Every summary row carries `coverageDepth` and `holes`, every review row carries a `source` level, and the sources are probed at the start of each run and monitored daily. A quiet change upstream degrades the output and says so; it never masquerades as "no more reviews".

### Who uses it

- **Product and support teams** pull `maxRating: 2` for the last 90 days of their own and competing apps and read the complaints, with `appVersion` on the newest ones.
- **ASO and growth** compare `ratingHistogram` across storefronts to see where a 4.4 is "mostly 5s" and where it is "mostly 3s", and track the 12-month negative share in the summary row.
- **Research and VoC pipelines** get stable `reviewId`s, ISO dates and one fixed schema across all 184 countries, ready for NLP without cleaning.
- **AI agents** call it through MCP and read the field descriptions from the dataset schema, so a prompt like "summarize this month's complaints" needs no glue code.

### Speed

Measured on the Apify platform on 2026-10-24: the complete history of a 2,800-review app in under 5 seconds, 15,000 reviews in 16 seconds. A 100,000-review history takes a couple of minutes. The optional developer-reply lookup is the slow part, roughly 1,000 reviews per 5 to 15 minutes per app and country, which is why it is off by default and billed separately.

### Use it from Claude, Cursor, or any MCP client

This Actor is a tool on the hosted [Apify MCP server](https://mcp.apify.com/). MCP (Model Context Protocol) is the standard that lets AI assistants call external tools. Add this URL as an MCP server in your client:

```
https://mcp.apify.com/?tools=actors,docs,kesar_chen/app-store-reviews-scraper
```

For Claude Desktop, put this in `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=actors,docs,kesar_chen/app-store-reviews-scraper",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

For Claude Code, one command:

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=actors,docs,kesar_chen/app-store-reviews-scraper" --header "Authorization: Bearer YOUR_APIFY_TOKEN"
```

For Cursor, the same `url` and `headers` block goes into `.cursor/mcp.json` under `mcpServers`. Any other MCP client that supports remote HTTP servers works the same way.

Then ask things like:

- "Pull all 1- and 2-star reviews of app 284882215 in the US from the last 6 months and group the complaints."
- "Compare the rating histograms of these three competitor apps in US, UK and Japan."
- "Every morning, fetch new reviews for my competitors and tell me if anything mentions crashes."
- "Get the 1-star reviews of app 1511601750 from the last 3 months with developer replies, and tell me which complaints the developer never answered."

Each review row and each summary row carries field descriptions in the dataset schema, so agents understand the data without guessing. Review text is user-generated content: tell your agent to treat `body` as data, never as instructions.

### Run it in the Apify Console

1. Open the Actor, paste an App Store URL, numeric app ID or bundle id into **Apps**, and pick the **Countries** you care about.
2. Optionally set **Only reviews since** (`12 months`, `30 days`, `2026-01-01`) or **Max reviews per app per country**, and turn on **Include developer responses** if you need replies. Set a maximum cost per run under **Run options** if you want a hard budget.
3. Click **Start**. When the run finishes, open the **Storage** tab: the **Reviews** view holds one row per review, the **Summary** view one row per app and country with totals and the histogram. Export as JSON, CSV or Excel, or read it through the API.

To run it on a schedule, save the input as a Task and attach a Schedule, see [Scheduling and integrations](#scheduling-and-integrations) below.

### What you get that newest-500 tools do not

| | This Actor | Typical newest-500 review scraper |
|---|---|---|
| Reviews per app per country | Full history (see limits below) | 500 |
| Rating histogram (1–5 star counts) | Yes, per country | No |
| Total number of written reviews | Yes | No |
| App version on review | Newest ~500 per country | Newest ~500 per country |
| Sort by recent / helpful / favorable / critical | Yes | Recent and helpful only |
| Incremental runs (only new reviews) | Yes, built in | Dedupe yourself |
| Last-N-months negative-review stats | Yes, in the summary row | No |
| Developer replies | Optional, per review | No |
| Filter by rating, date range, keywords, has-reply | Yes, before billing | Rating only, if at all |
| All 184 storefronts in one run | Yes, `countries: ["all"]` | Some |
| Login, cookies, API keys | None | None |

### Pricing

Pay per event, no subscription, no start fee. You only pay for what the run produces.

| Event | Price |
|---|---|
| Review scraped | $0.50 per 1,000 reviews |
| App summary (one per app per country, with histogram) | $0.002 |
| Developer response checked (optional, per review looked up) | $0.50 per 1,000 reviews |

Turning on developer responses doubles the per-review price, because every review has to be looked up separately and that lookup is slow. You pay per review checked, whether or not it has a reply, so narrow the scope with `sinceDate`, `maxReviewsPerApp` or incremental mode.

Apify platform usage is included in those prices. What typical jobs cost:

| Scenario | Reviews | Cost |
|---|---|---|
| Try it: one app, one country, newest 500 | 500 | about $0.25 |
| One competitor, full US history | 30,000 | about $15 |
| 10 competitors × 3 countries, daily incremental, ~20 new reviews per app per day | ~600 a day | about $3 a month |
| Same, with developer replies checked | ~600 a day | about $6 a month |

The monthly platform credit included in Apify's free plan covers several thousand reviews here, enough to validate the output on your own apps before paying anything. Paid Apify plans get a lower per-review price, shown on the Actor page.

Set a maximum budget per run in the Apify Console. When it is reached the run stops cleanly: reviews already pushed are kept and charged, nothing else is, and the summary row records how deep the run got. In incremental mode the saved state is only updated after an app × country completes, so a budget stop never loses data.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `apps` | list | required | Numeric App ID (`284882215`), App Store URL, bundle id (`com.facebook.Facebook`), or `search:keyword` (see `searchResultsPerKeyword`) |
| `countries` | list | `["us"]` | Two-letter store codes, or `["all"]` for every storefront. Each country is a separate store with its own reviews |
| `sinceDate` | text | empty | `2026-01-01` or relative like `12 months`, `30 days`. Applied with `sort = recent` |
| `sort` | select | `recent` | `recent`, `helpful`, `favorable`, `critical` |
| `maxReviewsPerApp` | integer | `3000` | Per app per country. `0` = everything Apple still serves |
| `untilDate` | text | empty | Upper bound, same formats as `sinceDate`. Combine both for a window |
| `minRating` / `maxRating` | integer | `1` / `5` | Keep only reviews in this star range. `maxRating: 2` for complaints only |
| `keywords` | list | `[]` | Keep only reviews whose title or text contains one of these words |
| `developerResponseFilter` | select | `all` | `with` or `without` a developer reply. Needs `includeDeveloperResponses` |
| `searchResultsPerKeyword` | integer | `1` | How many apps each `search:keyword` expands to |
| `summaryWindowMonths` | integer | `12` | Summary row counts 1–2 star reviews in this window. `0` turns it off |
| `incremental` | boolean | `false` | Remember seen reviews per app × country and output only new ones on later runs |
| `stateStoreName` | text | `appstore-reviews-state` | Named key-value store for incremental state. Named stores never expire. If a store with this name was created by another Actor, the run logs a warning and uses `<name>-<actor id>` instead |
| `includeDeveloperResponses` | boolean | `false` | Look up the developer reply for every review of the run. Slow and charged per review checked, see Pricing |
| `maxDeveloperResponseChecks` | integer | `1000` | Per app per country, caps how deep the reply lookup goes. `0` = no cap |
| `notifyWebhookUrl` | text | empty | Slack, Discord, Feishu or any HTTPS webhook; see Alerts |
| `notifyMaxRating` | integer | `2` | Only reviews at or below this rating are posted |
| `notifyMaxItems` | integer | `10` | Reviews per message; the rest are counted |
| `notifyEvenIfEmpty` | boolean | `false` | Post a message even when nothing matched |
| `includeReviewerName` | boolean | `false` | Off by default so your dataset carries no personal data |
| `pageSize` | integer | `3000` | Advanced tuning. Leave the default unless support asks you to change it |

Minimal example:

```json
{
  "apps": ["284882215", "https://apps.apple.com/us/app/instagram/id389801252"],
  "countries": ["us", "gb"],
  "sinceDate": "12 months",
  "maxReviewsPerApp": 0
}
```

Daily competitor monitor (save as a Task, attach a Schedule):

```json
{
  "apps": ["6504559449", "6475700817", "6451083449"],
  "countries": ["us", "gb", "jp", "de"],
  "sort": "recent",
  "maxReviewsPerApp": 0,
  "incremental": true,
  "stateStoreName": "my-competitors"
}
```

### Output

One row per review plus one summary row per app × country. Both go to the default dataset; use the `type` field or the two dataset views (Reviews, Summary) to tell them apart.

Review row:

```json
{
  "type": "review",
  "reviewId": "14649743823",
  "appId": "284882215",
  "bundleId": "com.facebook.Facebook",
  "appName": "Facebook",
  "country": "us",
  "storefrontId": 143441,
  "rating": 2,
  "title": "Crashes since last update",
  "body": "The app closes every time I open messages.",
  "appVersion": "512.0",
  "createdAt": "2026-10-10T13:18:51Z",
  "isEdited": false,
  "voteCount": 3,
  "voteSum": 2,
  "reviewerName": null,
  "reviewerUrl": null,
  "developerResponse": null,
  "developerResponseChecked": false,
  "source": "full",
  "isNew": true,
  "scrapedAt": "2026-10-24T04:41:52Z"
}
```

With `includeDeveloperResponses` on, a review that the developer answered looks like this (other fields unchanged):

```json
{
  "type": "review",
  "reviewId": "14698116552",
  "rating": 5,
  "title": "Finally a password manager I trust",
  "developerResponse": {
    "body": "Thanks for the 5-star review! We're glad 1Password gives you confidence in keeping your information secure.",
    "respondedAt": "2026-10-14T00:56:39Z",
    "responseId": "67246055"
  },
  "developerResponseChecked": true
}
```

`developerResponseChecked: true` with `developerResponse: null` means the review was looked up and has no reply. `developerResponseChecked: false` means it was not looked up, because the option was off, the budget ran out, or the reply source did not list that review.

Summary row:

```json
{
  "type": "summary",
  "appId": "6504559449",
  "appName": "PicTrace: AR Drawing & Sketch",
  "sellerName": "Example Studio",
  "currentVersion": "3.4.1",
  "country": "us",
  "totalReviews": 1039,
  "ratingCount": 59712,
  "ratingHistogram": [4912, 1602, 3105, 7891, 42202],
  "ratingAverage": 4.4,
  "reviewsScraped": 1039,
  "coverageDepth": 1039,
  "coverageNote": "500 reviews tagged with app version (version info exists for the newest ~500 reviews only)",
  "holes": [],
  "window": {
    "months": 12,
    "from": "2025-10-24T00:00:00Z",
    "reviews": 719,
    "negative": 393,
    "negativeShare": 54.7,
    "note": "sample 719"
  },
  "developerResponsesChecked": null,
  "developerResponsesFound": null,
  "source": "full",
  "scrapedAt": "2026-10-24T04:41:52Z"
}
```

`negativeShare` is only given when the window has at least 20 reviews. Below that you get the counts and a note, because a percentage of 7 reviews is noise. `ratingCount` is star ratings, `totalReviews` is written reviews; the first is usually 20 to 50 times larger than the second.

### How deep does it go?

For most apps: to the first review ever written in that country. For the very largest apps (hundreds of thousands of reviews in one country) Apple stops serving the oldest part of the history; for the biggest US apps the reachable depth is a few hundred thousand reviews. The summary row's `coverageDepth` tells you exactly how far the run got, and `holes` lists any ranges Apple would not return. Treat `coverageDepth` as the truth, not `totalReviews`.

If Apple changes something on its side, the Actor detects it at the start of the run and degrades automatically instead of failing. Every row carries a `source` field that tells you the coverage level: `full` is normal; `secondary` means the full history was still collected but more slowly and without vote counts; `limited` means only the newest 500 reviews could be collected. The summary row says the same. Nothing breaks downstream; you just get less speed or less depth until things return to normal.

### Limitations

- `appVersion` is only known for the newest ~500 reviews per country. Older reviews have `appVersion: null`.
- Developer-response lookup is slow by nature, roughly 1,000 reviews per 5 to 15 minutes per app and country. `developerResponseChecked: false` means the review was not looked up, not that it has no reply. For very large apps replies cannot be looked up beyond the newest several tens of thousands of reviews.
- `sinceDate` and incremental mode rely on `sort = recent`. With other sorts they are ignored and a warning is logged.
- Written reviews are far fewer than star ratings. An app with 60,000 ratings may have 1,000 written reviews. That is Apple's data, not a scraping gap.
- All 184 App Store storefronts are supported. For nine tiny storefronts (ad, bd, cf, et, gn, li, mc, ps, ws) Apple only exposes the newest 500 reviews, so rows there have `source: "limited"` and `storefrontId: null`.
- Reviews are per country store. A review written in the UK store never appears in the US store.

### Alerts: post new low-rated reviews to Slack, Discord or Feishu

Fill `notifyWebhookUrl` with a Slack incoming webhook, a Discord channel webhook, a Feishu/Lark custom bot webhook, or any HTTPS endpoint, turn on `incremental`, and attach a Schedule. After each app × country the Actor posts the reviews written in that run that are at or below `notifyMaxRating` (default 2), with the star rating, date, version where known, whether the developer already replied, and a link to the store page. Nothing is posted when nothing matched, unless `notifyEvenIfEmpty` is on. Unknown hosts receive a JSON body with the same fields, so Make, n8n, Zapier or your own service can take it from there. There is no extra charge for notifications.

An n8n template that does the same with room for translation or routing is in the [templates folder](https://github.com/ClaymanTwinkle/AppStoreReviewsActor/tree/main/templates).

### Scheduling and integrations

Save your input as a [Task](https://docs.apify.com/platform/actors/running/tasks), attach a [Schedule](https://docs.apify.com/platform/schedules) (`0 7 * * *` for daily at 07:00 in your timezone), and turn on `incremental`. Each run then returns only new reviews, which you can push to Slack, Google Sheets, Make, Zapier, n8n or any webhook through [Apify integrations](https://docs.apify.com/platform/integrations). Watch `ACTOR.RUN.FAILED` to get alerted if something goes wrong.

API example:

```bash
curl -X POST "https://api.apify.com/v2/acts/kesar_chen~app-store-reviews-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"apps":["284882215"],"countries":["us"],"sinceDate":"30 days","maxReviewsPerApp":0}'
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("kesar_chen/app-store-reviews-scraper").call(run_input={
    "apps": ["284882215"], "countries": ["us"], "sinceDate": "30 days", "maxReviewsPerApp": 0,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "review" and item["rating"] <= 2:
        print(item["createdAt"], item["title"])
```

### FAQ

**Why do other tools stop at 500 reviews per country?**
They rely on a public feed that stops at 500 per country. This Actor uses public, login-free store data that goes much deeper, and adds the app version wherever Apple exposes it, which is the newest ~500 reviews per country.

**How long does a run take?**
Seconds for most apps: a complete 2,800-review history in under 5 seconds, 15,000 reviews in 16 seconds, a 100,000-review history in a couple of minutes (measured on the Apify platform, 2026-10-24). Developer-reply lookup is the exception, see Speed above.

**Is there a free way to test it?**
Yes. Run it on your own app with `maxReviewsPerApp: 500`: that is about $0.25, well inside the monthly credit of Apify's free plan. The summary row tells you how many written reviews exist, so you know what a full pull would cost before you run it.

**Is it legal to scrape App Store reviews?**
Collecting publicly available data is generally considered legal in the US and most of the EU. This Actor accesses only public store data, uses no login, account, cookie or API key, and bypasses no access control. Review text and reviewer names are user-generated content and may be personal data under GDPR or CCPA; reviewer names are therefore off by default. How you store and use the output, and whether it fits the terms of the services involved, is your responsibility. Apify's overview: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**How is this different from the App Store Connect API?**
App Store Connect only returns reviews for apps you own. This Actor works for any app, which is what you need for competitor analysis.

**Why is the developer-response option slow, and why do I pay per review checked?**
Replies are not delivered together with the reviews; each review has to be looked up separately, and Apple only allows that at a slow pace. Every review of the run is looked up, and most reviews have no reply, so charging per reply found would make the price unpredictable for you and the work unpaid for us. Charging per review checked keeps it simple: turn it on, pay double per review, and narrow the scope with `sinceDate`, `maxReviewsPerApp` or incremental mode.

**Do filtered-out reviews cost anything?**
No. Rating, date, keyword and reply filters run before rows are written, and you are charged per row written. The only exception is `developerResponseFilter`: to know whether a review has a reply it has to be looked up first, so every review still counts as one check. Filters do not change the summary row's window statistics, which always describe all reviews read in the window, otherwise `maxRating: 2` would report a 100% negative share.

**What happens when my budget runs out mid-run?**
The run stops cleanly. Reviews already saved are kept, the summary row records the depth reached, and in incremental mode the state is only written for app × country pairs that finished. Raise the budget and run again.

**Can I get all countries at once?**
List the storefront codes you want in `countries`. Apps with zero ratings in a country are skipped automatically, so listing many countries is cheap.

**Why is `negativeShare` null?**
The window had fewer than 20 reviews. You still get the counts.

**Can AI agents use this?**
Yes, through the Apify MCP server (top of this page). Field descriptions are in the dataset schema so agents can read the output without guesswork.

**Is this affiliated with Apple?**
No. This is an independent tool and is not endorsed by or affiliated with Apple Inc.

### See also

[Google Play Reviews Scraper](https://apify.com/kesar_chen/google-play-reviews-scraper) and [Steam Reviews Scraper](https://apify.com/kesar_chen/steam-reviews-scraper): the same schema, filters and incremental mode for Android apps and Steam games, so one pipeline can watch all three stores.

[Hiring Signals Monitor](https://apify.com/kesar_chen/hiring-signals-monitor): job opened / closed events and a hiring summary per company from public job boards, for watching competitors' teams the same way you watch their reviews.

### Support

Bugs, missing fields, or a storefront you need: open an issue on the Issues tab. Reports go to a human.

# Actor input Schema

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

One per line: numeric App ID (284882215), App Store URL (https://apps.apple.com/us/app/facebook/id284882215), bundle id (com.facebook.Facebook), or `search:keyword` to take the first search hit.

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

Two-letter storefront codes (us, gb, jp, de ...), or \["all"] for every one of the 184 storefronts (those where the app has no ratings are skipped). Reviews are per storefront; each country is scraped separately.

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

Absolute date (2026-01-01) or relative (12 months, 30 days). Only applied with sort = recent. Empty = no limit.

## `sort` (type: `string`):

Order in which Apple returns reviews. Use recent for monitoring and date filters.

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

0 = go as deep as Apple's index allows (hundreds of thousands for big apps).

## `summaryWindowMonths` (type: `integer`):

The summary row counts 1-2 star reviews in the last N months. Percentages are only given when the sample has at least 20 reviews. 0 = off.

## `incremental` (type: `boolean`):

Remembers which reviews it has seen per app and country in a named key-value store, and outputs only new ones on later runs. Requires sort = recent.

## `stateStoreName` (type: `string`):

Named key-value store that keeps the incremental state. Named stores never expire.

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

Keep only reviews with at least this many stars. Filtered-out reviews are not written and not charged. With sort = favorable the run stops early once ratings fall below this.

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

Keep only reviews with at most this many stars. 1-2 for complaint monitoring. With sort = critical the run stops early once ratings rise above this.

## `untilDate` (type: `string`):

Upper bound on the review date, same formats as 'Only reviews since' (2026-03-01, 30 days). Combine both to pick a window, for example the two weeks after a release.

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

Keep only reviews whose title or text contains at least one of these words, case-insensitive. Empty = no filter.

## `developerResponseFilter` (type: `string`):

Needs 'Include developer responses' on. Every review is still looked up (and charged as a check); only the matching ones are written.

## `searchResultsPerKeyword` (type: `integer`):

How many apps a 'search:keyword' entry in Apps expands to, ordered by App Store relevance.

## `includeDeveloperResponses` (type: `boolean`):

Look up the developer reply for each review of this run and attach it. Slow: expect roughly 1,000 reviews per 5 to 15 minutes per app and country. Charged per review checked (same price as a review), not per reply found. Narrow the scope with sinceDate, maxReviewsPerApp or incremental mode.

## `maxDeveloperResponseChecks` (type: `integer`):

Per app per country, only with includeDeveloperResponses. Caps how deep the reply lookup goes; the rest of the run is unaffected. 0 = no cap.

## `notifyWebhookUrl` (type: `string`):

Paste a Slack incoming webhook, a Discord channel webhook, a Feishu/Lark custom bot webhook, or any HTTPS endpoint. After each app × country the Actor posts the reviews written in this run that are at or below the rating threshold. With incremental mode on, that means only new low-rated reviews. Unknown hosts receive a JSON body.

## `notifyMaxRating` (type: `integer`):

Only reviews with this many stars or fewer are posted. 5 = post everything written.

## `notifyMaxItems` (type: `integer`):

The rest are summarised as a count; all of them are in the dataset.

## `notifyEvenIfEmpty` (type: `boolean`):

Off = silence when there is nothing at or below the threshold.

## `includeReviewerName` (type: `boolean`):

Off by default to keep personal data out of your dataset.

## `pageSize` (type: `integer`):

Advanced tuning. Leave the default unless support asks you to change it.

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

Leave on scrape.

## `requests` (type: `integer`):

Probe only.

## `concurrency` (type: `integer`):

Probe only.

## `cacheBust` (type: `boolean`):

Probe only.

## `startOffset` (type: `integer`):

Probe only.

## `testRss` (type: `boolean`):

Probe only.

## `testProxy` (type: `boolean`):

Probe only.

## `appId` (type: `string`):

Probe only.

## `storefront` (type: `string`):

Probe only.

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

Probe only.

## Actor input object example

```json
{
  "apps": [
    "6478019368"
  ],
  "countries": [
    "us"
  ],
  "sinceDate": "12 months",
  "sort": "recent",
  "maxReviewsPerApp": 3000,
  "summaryWindowMonths": 12,
  "incremental": false,
  "stateStoreName": "appstore-reviews-state",
  "minRating": 1,
  "maxRating": 5,
  "untilDate": "",
  "keywords": [],
  "developerResponseFilter": "all",
  "searchResultsPerKeyword": 1,
  "includeDeveloperResponses": false,
  "maxDeveloperResponseChecks": 1000,
  "notifyMaxRating": 2,
  "notifyMaxItems": 10,
  "notifyEvenIfEmpty": false,
  "includeReviewerName": false,
  "pageSize": 3000,
  "mode": "scrape",
  "requests": 60,
  "concurrency": 1,
  "cacheBust": false,
  "startOffset": 0,
  "testRss": true,
  "testProxy": true,
  "appId": "284882215",
  "storefront": "143441-1,29",
  "country": "us"
}
```

# Actor output Schema

## `results` (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": [
        "6478019368"
    ],
    "sinceDate": "12 months",
    "untilDate": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("kesar_chen/app-store-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": ["6478019368"],
    "sinceDate": "12 months",
    "untilDate": "",
}

# Run the Actor and wait for it to finish
run = client.actor("kesar_chen/app-store-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": [
    "6478019368"
  ],
  "sinceDate": "12 months",
  "untilDate": ""
}' |
apify call kesar_chen/app-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

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