# App Store & Google Play Reviews Scraper (`sam_i_am_not/app-reviews-scraper`) Actor

Reviews from Apple's App Store and Google Play in one dataset with one schema: rating, title, text, date, app version, helpful votes and developer replies. Paste app IDs or store URLs, pick countries or a language, filter by stars or date.

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

## Pricing

from $0.08 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## App Store & Google Play Reviews Scraper

**Get app reviews from Apple's App Store and Google Play in one run, in one table: rating, title, text, date, app version, helpful votes and the developer's reply.** Paste app IDs or store URLs from either store, mixed. Pick App Store countries and a Google Play language, filter by stars or date, and download JSON, CSV or Excel. No login, no browser, no API keys. A few hundred reviews take a few seconds.

Built for product managers, app developers, ASO and market-research teams, and AI agents that need to know what users say about an app and its competitors.

### What you get

One row per review, with the same columns for both stores:

| Field | App Store | Google Play |
|---|---|---|
| `rating` (1-5), `text`, `date`, `userName`, `appVersion` | ✓ | ✓ |
| `title` | ✓ | null (Play reviews have no title) |
| `helpfulCount` | helpful votes | thumbs-up count |
| `voteCount` (all votes) | ✓ | null |
| `replyText`, `replyDate` (developer reply) | null (Apple's feed doesn't include replies) | ✓ |
| `userImageUrl` / `userProfileUrl` | profile link | avatar |
| `reviewUrl` | null | ✓ |
| `country` / `language` | country | language |

Every row also has `store` (`appStore` or `googlePlay`), `appId`, `appUrl`, `reviewId` and `scrapedAt`.

Options:

- **Sort:** newest first, or the store's own order ("Most helpful" on the App Store, "Most relevant" on Google Play)
- **Stars:** e.g. only 1- and 2-star reviews, to read complaints
- **Reviews since:** only reviews from a date on. With newest-first sorting the run stops as soon as it reaches older reviews, so a daily scheduled run that collects only new reviews costs almost nothing
- **App Store countries:** each country has its own reviews. Add several to get more of them
- **Google Play language:** Google Play groups reviews by the language they're written in

### How to use it

1. Add apps, one per line. App Store: `284882215`, `id284882215` or `https://apps.apple.com/us/app/facebook/id284882215`. Google Play: `com.spotify.music` or `https://play.google.com/store/apps/details?id=com.spotify.music`.
2. Set **Max reviews per app**, and optionally sort, countries, language, stars and a start date.
3. Click **Start**. Download results from the Output tab as JSON, CSV, Excel or HTML, or fetch them through the API.

#### Input example

```json
{
    "apps": ["310633997", "com.whatsapp", "https://apps.apple.com/gb/app/telegram-messenger/id686449807", "org.telegram.messenger"],
    "maxReviewsPerApp": 300,
    "countries": ["us", "gb", "ca"],
    "language": "en",
    "stars": ["1", "2"],
    "reviewsSince": "2026-10-01"
}
```

### Output

Real output, one review from each store:

```json
[
    {
        "store": "googlePlay",
        "appId": "com.spotify.music",
        "appUrl": "https://play.google.com/store/apps/details?id=com.spotify.music",
        "country": null,
        "language": "en",
        "reviewId": "752659ef-19f9-4479-815d-15cac801ed84",
        "rating": 4,
        "title": null,
        "text": "good songs but has adds",
        "date": "2026-10-30T01:55:06.000Z",
        "userName": "Dima",
        "userImageUrl": "https://play-lh.googleusercontent.com/a/ACg8ocL9wnhBPHYoyUyyeRBFACE8HskXDOEhU96AnJDJDuD9WNrdeg=mo",
        "userProfileUrl": null,
        "appVersion": "9.1.92.3058",
        "helpfulCount": 0,
        "voteCount": null,
        "replyText": "Hi. Thanks for sharing this. We hear you and we'll pass your feedback along to the Ads team. For an ad-free experience, we'd recommend checking out our Premium plans at spotify.com/premium. If you've never had Premium before, you should be eligible for our trial.",
        "replyDate": "2026-10-30T16:35:46.000Z",
        "reviewUrl": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=752659ef-19f9-4479-815d-15cac801ed84",
        "scrapedAt": "2026-10-31T01:56:29.610Z"
    },
    {
        "store": "appStore",
        "appId": "284882215",
        "appUrl": "https://apps.apple.com/us/app/id284882215",
        "country": "us",
        "language": null,
        "reviewId": "14726791143",
        "rating": 5,
        "title": "Gracias por todo",
        "text": "Humilde siempre",
        "date": "2026-10-29T19:04:29.000Z",
        "userName": "Petenero gallo",
        "userImageUrl": null,
        "userProfileUrl": "https://itunes.apple.com/us/reviews/id1978260122",
        "appVersion": "585.0.0",
        "helpfulCount": 0,
        "voteCount": 0,
        "replyText": null,
        "replyDate": null,
        "reviewUrl": null,
        "scrapedAt": "2026-10-31T01:56:29.610Z"
    }
]
```

A run summary (apps succeeded and failed, the reasons, warnings and charged events) is saved as `OUTPUT` in the run's key-value store.

### Pricing

You pay per **review** delivered. The price is in the Pricing tab above.

- 1,000 reviews cost about $0.10 on paid Apify plans.
- **No charge** for apps that fail, or for reviews your star and date filters leave out.
- **No start fee** beyond Apify's standard $0.00005 per run.
- Platform usage is included.
- Set **Max cost per run** in the run options, and the Actor stops cleanly when it gets there, delivering exactly what fits.

### Why use this instead of…

- **Two separate scrapers:** one run, one schema, one export for both stores, so comparing your iOS and Android ratings, or your app against a competitor's, is a single table.
- **Your own script:** Apple's feed has quirks (its CDN sometimes serves an empty page for an app that has reviews; this Actor asks again past the cache), and Google Play's review endpoint is undocumented. A live test runs against both stores every day, so changes are caught early.

### Use with AI agents (MCP)

This Actor works as a tool through the [Apify MCP server](https://mcp.apify.com), so Claude, ChatGPT, Cursor and other MCP clients can call it directly. Typical agent calls:

```json
{ "apps": ["com.duolingo"], "stars": ["1", "2"], "maxReviewsPerApp": 50 }
```

```json
{ "apps": ["570060128", "com.duolingo"], "reviewsSince": "2026-10-01", "maxReviewsPerApp": 200 }
```

You can also call it from code with the Apify API or the `apify-client` package for JavaScript and Python.

### FAQ

**Why do I get at most 500 App Store reviews per app?** Apple's public review feed serves the latest 500 reviews per app and country (10 pages of 50). Add more countries for more reviews. Google Play has no such cap.

**Why doesn't the country setting change Google Play results?** Google Play shows the same reviews in every country and groups them by language instead. Use **Google Play language**.

**Why is a reply date earlier than its review date?** On Google Play, `date` is when the review was last edited. If the user edited it after the developer replied, the reply is older.

**Why are the newest Google Play reviews from about a day ago?** Google Play publishes reviews with a delay of roughly a day.

**Does it get app details (installs, rating histogram)?** Not yet. Open an issue if you need them.

**Is this allowed?** It reads the public reviews any visitor sees on the store pages, without logging in. Reviews include reviewers' public display names; if you store or publish them, the data-protection rules that apply to you (such as GDPR) still apply.

**Does the Actor send anything back to the developer?** At the end of each run it sends us a small usage record: how many of each billable event the run was charged, the prices it was charged at, your pricing tier, whether your plan is paid, and a one-way hash of your user ID. That's how we see which Actors are worth maintaining, because Apify doesn't share this with developers. Your input, your results and your account details are never sent.

**Something broke or looks wrong?** Open an issue on the Issues tab. Issues get a response within 48 hours.

# Changelog

This Actor's version history is a separate document: https://apify.com/sam_i_am_not/app-reviews-scraper/changelog.md

# Actor input Schema

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

One app per line, from either store. App Store: the numeric ID ("284882215", "id284882215") or the apps.apple.com URL. Google Play: the package name ("com.spotify.music") or the play.google.com URL.

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

Stop after this many reviews per app (per app and country for the App Store). 0 = no limit. Apple's feed holds at most 500 reviews per app and country; Google Play has no cap, so popular apps can have millions.

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

Newest first, or the store's own relevance order ("Most helpful" on the App Store, "Most relevant" on Google Play).

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

Two-letter country codes ("us", "gb", "de"). Each App Store country has its own reviews, so more countries means more reviews. Doesn't affect Google Play, which groups reviews by language instead. Default: us.

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

Language code ("en", "de", "pt-BR"). Google Play returns the reviews written in this language. Doesn't affect the App Store.

## `stars` (type: `array`):

Only return reviews with these ratings, e.g. 1 and 2 for complaints. Leave empty for all. Only matching reviews are charged.

## `reviewsSince` (type: `string`):

YYYY-MM-DD. Only reviews posted or edited on or after this day (UTC). With "Newest" sorting the run stops paging once it reaches older reviews, which makes scheduled runs that pick up only new reviews cheap.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.whatsapp"
  ],
  "maxReviewsPerApp": 100,
  "sort": "newest",
  "countries": [
    "us"
  ],
  "language": "en",
  "reviewsSince": "2026-01-01"
}
```

# Actor output Schema

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

One row per review, from both stores.

## `summary` (type: `string`):

Counts of succeeded and failed apps, failure reasons, warnings and charged events.

# 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",
        "com.spotify.music"
    ],
    "maxReviewsPerApp": 100,
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sam_i_am_not/app-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",
        "com.spotify.music",
    ],
    "maxReviewsPerApp": 100,
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("sam_i_am_not/app-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",
    "com.spotify.music"
  ],
  "maxReviewsPerApp": 100,
  "countries": [
    "us"
  ]
}' |
apify call sam_i_am_not/app-reviews-scraper --silent --output-dataset

```

## MCP server setup

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