# App Store Reviews Scraper · iOS + Google Play, Any Country (`agentsgearbox/app-store-reviews-scraper`) Actor

App Store and Google Play reviews scraper for any app and country in one run: stars, title, text, date, version, helpful votes and developer replies, newest or most helpful first, star and date filters, since-last-run checkpoint, rating trend per app. $0.06 per 1,000; first 50 a month free.

- **URL**: https://apify.com/agentsgearbox/app-store-reviews-scraper.md
- **Developed by:** [AgentsGearbox](https://apify.com/agentsgearbox) (community)
- **Categories:** E-commerce, Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## App Store Reviews Scraper · iOS and Google Play, any country

Download the reviews of **any iOS or Android app from the App Store and Google Play in one run**: star rating, title,
text, date, app version, helpful votes and the developer's reply, for any store country, newest or most helpful first.
Give it App Store links or ids and Google Play package names in one list; the store is detected from each entry. Built
for daily monitoring: a date filter and a **since-last-run checkpoint per app, store and country** mean a scheduled run
fetches only the reviews you have not seen, and every app gets a free summary with the **average rating, a star
histogram and the version collecting the most one- and two-star reviews**. **$0.06 per 1,000 reviews**, no login, no
API key, nothing charged for errors, summaries or empty runs. The first 50 reviews each month are free for every account.

### Why this one

| | This actor |
|---|---|
| Price | $0.00006 per review ($0.06 per 1,000) and $0.00006 per optional app-details record, plus Apify's default $0.00005 start fee. No platform usage charged on top. |
| Both stores | One list of apps, one run, one output format and one checkpoint store across the App Store and Google Play; every row says which store and country it came from. |
| Any country | `countries: ["us", "gb", "de", "in"]` fetches every app once per storefront. App Store reviews are per country; Google Play reviews are per country and language. |
| Daily monitoring | `onlyNewSinceLastRun` stores the newest review date per app, store and country and stops there on the next run; `reviewedAfter` accepts `7d`, `12h` or a date. Quiet days cost only the start fee. |
| Rating trend | A free `summary` per app and country with the average rating and histogram of the reviews fetched, the version with the most low-star reviews, and why the run stopped. |
| Every field | Rating, title, text, date, app version, helpful votes (and vote count on the App Store), developer reply text and date (Google Play), reviewer name, review link. `minScore`/`maxScore` keep only the stars you want, uncharged. |
| App record | Optional: overall rating and rating count, price, version, release and update dates, genre, content rating, developer and icon; Google Play adds the histogram, install range and developer e-mail. |
| Reliability | Apple's public reviews feed and the iTunes lookup API, Google Play's own review endpoint, no browser, no proxies; an app that does not exist in a country returns an `error` record instead of failing the run. |

### What people use it for

- **Review monitoring on both stores**: every new review of your app each day, with one- and two-star ones routed to Slack, e-mail or a ticketing tool.
- **Release health**: reviews carry the app version, and the summary names the version collecting the most complaints, so you see what broke before the overall rating moves.
- **Competitor research across storefronts**: the same app list for the US, UK, German and Indian stores in one sheet.
- **Sentiment and topic analysis**: thousands of rated, dated and versioned reviews for an LLM or a classifier.
- **Agents**: one tool call for "what are people saying about app X everywhere this week", with a known price per result.

### Example tasks

Ready-made configurations you can open, copy and run as they are:

- [Latest 1-star reviews of an app on App Store and Google Play](https://apify.com/agentsgearbox/app-store-reviews-scraper/examples/latest-one-star-app-reviews-on-both-stores): one app on both stores, three country storefronts, one-star reviews from the last 30 days, checkpoint on for a daily schedule.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `apps` | array | required | App Store ids or URLs (`310633997`, `id310633997`, `https://apps.apple.com/us/app/whatsapp-messenger/id310633997`) and Google Play package names or URLs (`com.whatsapp`). Mix both in one list. |
| `countries` | array | `["us"]` | Two-letter store countries. Every app is fetched once per country. |
| `maxReviewsPerApp` | integer | 100 | Upper limit per app and country. The App Store feed stops at 500 (10 pages of 50). |
| `sort` | string | `newest` | `newest` (monitoring), `helpful` (most voted first) or `rating` (Google Play only). |
| `reviewedAfter` | string | – | ISO date (`2026-01-01`) or relative (`1d`, `12h`, `7d`, `30d`). With `newest` the run stops at the first older review. |
| `minScore` / `maxScore` | integer | – | Keep only reviews within this star range (1–5). Filtered reviews are not charged. |
| `onlyNewSinceLastRun` | boolean | false | Remembers the newest review date per app, store and country in a key-value store of your account and stops there next time. |
| `checkpointStoreName` | string | `app-reviews-state` | Name of that store; use one per monitoring job. |
| `includeAppDetails` | boolean | true | One `app` record per app and country with rating, counts, price, version, dates, genre and developer. |
| `language` | string | `en` | Language of the Google Play reviews (`en`, `de`, `it`…). The App Store feed has no language filter. |

```json
{
    "apps": ["https://apps.apple.com/us/app/whatsapp-messenger/id310633997", "com.whatsapp"],
    "countries": ["us", "gb"],
    "maxReviewsPerApp": 100,
    "sort": "newest",
    "reviewedAfter": "7d",
    "onlyNewSinceLastRun": true,
    "includeAppDetails": true
}
```

### Output

**`review`** (charged, $0.00006 each). Real rows, long fields shortened:

```json
{
    "type": "review", "store": "app-store", "appId": "310633997", "country": "us",
    "reviewId": "14673611888", "url": "https://apps.apple.com/us/app/id310633997?see-all=reviews",
    "userName": "Presh1$", "userUrl": "https://itunes.apple.com/us/reviews/id1980309752",
    "date": "2026-10-16T14:15:40.000Z", "score": 1, "title": "Complain",
    "text": "Why do they keep telling me to download official WhatsApp you didn't even allow me login my account",
    "appVersion": "26.40.77", "votes": 0, "voteCount": 0, "replyText": null, "replyDate": null, "language": null
}
```

```json
{
    "type": "review", "store": "google-play", "appId": "com.whatsapp", "country": "us",
    "reviewId": "e0f1bfb1-7961-4005-b303-10db9ad3a8df",
    "url": "https://play.google.com/store/apps/details?id=com.whatsapp&reviewId=e0f1bfb1-7961-4005-b303-10db9ad3a8df",
    "userName": "Akthar Khan", "userUrl": null, "date": "2026-10-16T22:31:41.569Z", "score": 1, "title": null,
    "text": "Net is too slow", "appVersion": null, "votes": 0, "voteCount": null, "replyText": null, "replyDate": null, "language": "en"
}
```

| Field | Meaning |
|---|---|
| `store`, `appId`, `country` | Where the review comes from: `app-store` with the numeric id, or `google-play` with the package name, and the storefront. |
| `score`, `title`, `text`, `date` | Stars 1–5, review title (App Store only), text, ISO timestamp. |
| `appVersion` | Version the reviewer had; Google Play omits it on some reviews. |
| `votes`, `voteCount` | Helpful votes: App Store `voteSum` and `voteCount`; Google Play "thumbs up" in `votes`. |
| `replyText`, `replyDate` | The developer's reply, Google Play only; Apple's public feed does not include responses. |
| `userName`, `userUrl` | Reviewer name and, on the App Store, the public reviewer page. |
| `language` | Google Play review language; `null` for App Store rows (the feed has no language filter). |

**`app`** (charged, $0.00006 each, one per app and country when `includeAppDetails` is on). App Store rows carry
`score`, `ratings`, `scoreCurrentVersion`, `ratingsCurrentVersion`, `price`, `currency`, `version`, `released`, `updated`,
`genre`, `genres`, `contentRating`, `minimumOs`, `sizeBytes`, `icon`, `languages`, `bundleId`, `developer`, `developerUrl`.
Google Play rows carry `score`, `ratings`, `reviews`, `histogram`, `installs`, `minInstalls`, `maxInstalls`, `price`,
`free`, `version`, `released`, `updated`, `genre`, `contentRating`, `icon`, `adSupported`, `offersIAP`, `developer`,
`developerEmail`, `developerUrl`.

**`summary`** (free, one per app and country at the end of the run):

```json
{
    "type": "summary", "store": "app-store", "appId": "310633997", "country": "us", "status": "COMPLETE",
    "reviewsScraped": 60, "reviewsFilteredOut": 0, "reviewsScanned": 100,
    "newestReviewDate": "2026-10-16T14:15:40.000Z", "oldestReviewDate": "2026-10-14T11:09:15.000Z",
    "averageScore": 3.85, "histogram": {"1": 15, "2": 1, "3": 1, "4": 4, "5": 39},
    "worstVersion": {"version": "26.40.77", "lowStarReviews": 14},
    "stoppedBy": "maxReviews", "checkpointUsed": null
}
```

`status` is `COMPLETE`, `PARTIAL` (stopped by your spending limit), `EMPTY` or `ERROR`; `stoppedBy` is `maxReviews`,
`reviewedAfter`, `checkpoint`, `endOfReviews`, `feedLimit` (the App Store feed's 500 newest reviews per country),
`chargeLimit`, `scanLimit` (a star filter matched nothing for thousands of Google Play reviews) or `error`.
`averageScore`, `histogram` and `worstVersion` describe the reviews fetched in this run, not the store's overall rating
(that is in the `app` record).

**`error`** (free): `{"type": "error", "store": "app-store", "appId": "999999999999", "country": "gb", "error": "app not found in this country's App Store"}`.

### Pricing and cost examples

**Try it free.** The first 50 reviews each calendar month are free for every Apify account, with nothing to enter: the actor keeps count in a small key-value store in your account (`free-slice-app-store-reviews-scraper`) and charges only from the 51th on. The free results are real results you keep; the counter resets on the first of each month.

| Job | Reviews | Cost |
|---|---|---|
| Newest 500 App Store reviews of one app in one country, with the app record | 500 + 1 | $0.03 |
| Daily monitor of 10 apps on both stores in 3 countries, about 40 new reviews a day, checkpoint on | 40 a day | $0.002 a day, under $0.10 a month |
| Competitor sheet: 20 apps × both stores × 5 countries × 100 reviews, with app records | 20,000 + 200 | $1.21 |
| Research dataset: 200 apps × 500 App Store reviews | 100,000 | $6.00 |

Platform compute is included in the per-item price. A run that finds nothing new costs only Apify's $0.00005 start fee.

**Discounts for paid Apify plans**, applied automatically to the buyer's plan: Bronze 10% off, Silver 25% off, Gold and enterprise tiers 40% off the prices above. Free-plan users pay the listed price.

### Scheduling: a daily complaints digest in two minutes

1. Create a task from this actor with your apps and countries, `minScore: 1`, `maxScore: 2`, `onlyNewSinceLastRun: true`.
2. Add a schedule (daily) and an integration (Slack, e-mail, Google Sheets, Make, n8n or a webhook) on the task.
3. The first run collects the current reviews (up to `maxReviewsPerApp`); from then on each run returns only new ones, and the `summary` rows tell you which version is collecting the complaints.

### Run it from your code

JavaScript:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('agentsgearbox/app-store-reviews-scraper').call({
    apps: ['https://apps.apple.com/us/app/whatsapp-messenger/id310633997', 'com.whatsapp'],
    countries: ['us', 'gb'], maxReviewsPerApp: 100, reviewedAfter: '7d',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((r) => r.type === 'review').length, 'reviews');
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('agentsgearbox/app-store-reviews-scraper').call(run_input={
    'apps': ['310633997', 'com.whatsapp'], 'countries': ['us'], 'maxReviewsPerApp': 100, 'minScore': 1, 'maxScore': 2,
})
for item in client.dataset(run['defaultDatasetId']).iterate_items():
    if item['type'] == 'review':
        print(item['store'], item['score'], item['text'][:80])
```

curl (synchronous, returns the dataset):

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

### For AI agents

Give your agent hands. Instead of opening store pages, getting blocked and reasoning over HTML, it calls this actor as a tool and gets verified reviews back as JSON, priced per result, from both stores in one call.

- **MCP, this actor only:** add `https://mcp.apify.com?tools=agentsgearbox/app-store-reviews-scraper` to Claude Desktop, Claude Code, Cursor or any MCP client (with your Apify token), then ask for "the one-star reviews of WhatsApp on both stores this week".

* **MCP, all agentsgearbox actors:** `https://mcp.apify.com?tools=agentsgearbox/telegram-channel-scraper,agentsgearbox/google-play-reviews-scraper,agentsgearbox/substack-scraper,agentsgearbox/google-news-scraper,agentsgearbox/brand-name-generator,agentsgearbox/ai-readiness-audit,agentsgearbox/company-lookup,agentsgearbox/app-intelligence,agentsgearbox/app-store-reviews-scraper`

- **No Apify account?** This actor is eligible for Apify's agentic payments: an agent can buy a spend-capped token through [agi.apify.com](https://agi.apify.com) (x402, MPP or Skyfire) and call the API with it.
- Prices are per result and known in advance, so the agent can set a spending limit; error records come back as data instead of failed runs.

### Reading the results

- Filter on `type` (`review`, `app`, `summary`, `error`) and `store`; every row carries `appId` and `country`.
- `summary.worstVersion` is the version with the most one- and two-star reviews among the reviews fetched in this run: the fastest signal that a release is going wrong.
- For a complete picture of an app's rating use the `app` record (`score`, `ratings`), not the summary's `averageScore`, which only describes the reviews you asked for.

### Limitations, stated plainly

- Apple's public feed serves the newest 500 reviews per country (10 pages of 50) and no developer responses; older reviews have no public source. The actor reports `stoppedBy: feedLimit` when it hits that wall.
- Apple's feed sometimes answers with an empty page for minutes at a time, for some storefronts and networks. The actor asks through up to six request paths, retries once after a pause and remembers the path that worked; if every path stays empty for an app that has ratings, you get a free `error` row saying so instead of a silent empty result. A scheduled run simply picks the reviews up next time.
- App Store reviews come in the language they were written in; there is no language filter on Apple's side. Google Play reviews are filtered by `language`.
- Google Play exposes an app version on most but not all reviews, so `appVersion` can be `null` there.
- Apple's APIs allow about 20 calls a minute per address; the actor paces itself, so a run over many apps and countries takes a few seconds per pair.
- Review text is the reviewer's; names are public screen names. Keep personal data in mind when you store or share the output.

### Troubleshooting

| Symptom | What is happening |
|---|---|
| `app not found in this country's App Store` | The id exists in another storefront only, or is not an app id. Use the id from the App Store URL (`…/id310633997`). |
| `app not found on Google Play in this country` | The package is not published in that country. Try another `countries` entry. |
| `"xx" is not a storefront` / `Google Play rejected country=…` | Use two-letter ISO codes (`us`, `gb`, `de`). |
| 0 reviews with the checkpoint on | Nothing new since the last run; the `summary` shows `stoppedBy: "checkpoint"`. |
| Fewer than 500 App Store reviews | The app has fewer reviews in that country, or your `maxReviewsPerApp` is lower. |

### More from agentsgearbox

- [Telegram Channel Scraper](https://apify.com/agentsgearbox/telegram-channel-scraper): public Telegram channels as JSON, no API key.
- [Google Play Reviews Scraper](https://apify.com/agentsgearbox/google-play-reviews-scraper): Google Play reviews with replies and versions, any market.
- [Substack Scraper](https://apify.com/agentsgearbox/substack-scraper): Substack posts with full text and comments, custom domains too.
- [Google News Scraper](https://apify.com/agentsgearbox/google-news-scraper): Google News with real publisher URLs and full text.
- [Brand & Business Name Generator](https://apify.com/agentsgearbox/brand-name-generator): brand names verified live on domains, handles and app stores.
- [AI Readiness Audit](https://apify.com/agentsgearbox/ai-readiness-audit): how well AI search engines and agents can read a site: crawler access, llms.txt, structured data, content without JavaScript, scored with fixes.
- [Company Lookup](https://apify.com/agentsgearbox/company-lookup): one row per domain with legal identity and VAT validation, contacts, socials, tech stack, open jobs, apps, news and Wikidata facts.
- [App Intelligence](https://apify.com/agentsgearbox/app-intelligence): App Store and Google Play in one run: search, top charts, full app details and each app's twin on the other store.

All of them are pay-per-event, run without a browser, and are compared with their alternatives on [agentsgearbox.com](https://agentsgearbox.com/actors/).

### Support

Issues tab on this actor's page, or support@agentsgearbox.com. Built by [agentsgearbox](https://agentsgearbox.com): tools that give AI agents verified results from the live web, priced per result.

# Actor input Schema

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

App Store ids or URLs (`310633997`, `id310633997`, `https://apps.apple.com/us/app/whatsapp-messenger/id310633997`) and Google Play package names or URLs (`com.whatsapp`). The store is detected from each entry; mix both in one list.

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

Two-letter store countries (`us`, `gb`, `de`, `it`, `in`, `br`…). Every app is fetched once per country; each row is stamped with its country. The App Store feed serves the newest 500 reviews per country.

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

Upper limit per app and country. The App Store feed stops at 500 (10 pages of 50); Google Play has no practical limit.

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

`newest` for monitoring (the run stops at the first review older than your filters), `helpful` for the most voted reviews first. On Google Play `rating` is also available.

## `reviewedAfter` (type: `string`):

ISO date (`2026-01-01`) or a relative value such as `1d`, `12h`, `7d`, `30d`. With sort = newest the run stops at the first older review, so you pay only for new ones.

## `minScore` (type: `integer`):

Keep only reviews with at least this rating (1–5). Filtered reviews are not charged.

## `maxScore` (type: `integer`):

Keep only reviews with at most this rating (1–5). Use `maxScore: 2` for complaint alerts.

## `onlyNewSinceLastRun` (type: `boolean`):

For daily monitoring. Remembers the newest review date per app, store and country in a key-value store of your account and stops there on the next run. Quiet days cost nothing beyond Apify's start fee.

## `checkpointStoreName` (type: `string`):

Key-value store that keeps the per-app checkpoints (created automatically in your account). Use different names for different monitoring jobs.

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

Also output one record per app and country with title, developer, overall rating and rating count, price, version and release date (App Store: iTunes lookup; Google Play: store page).

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

Two-letter language of the Google Play reviews (`en`, `de`, `it`…). The App Store feed has no language filter; reviews come in whatever language they were written.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.whatsapp"
  ],
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 100,
  "sort": "newest",
  "onlyNewSinceLastRun": false,
  "checkpointStoreName": "app-reviews-state",
  "includeAppDetails": true,
  "language": "en"
}
```

# Actor output Schema

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

Reviews and app detail records as JSON (one item per review or app).

# 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/whatsapp-messenger/id310633997",
        "com.whatsapp"
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("agentsgearbox/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": [
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
        "com.whatsapp",
    ],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("agentsgearbox/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": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.whatsapp"
  ],
  "countries": [
    "us"
  ]
}' |
apify call agentsgearbox/app-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

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