# App Store & Google Play Reviews Scraper (`brii3343/app-store-google-play-reviews-scraper`) Actor

App Store and Google Play reviews in one run, same fields for both: rating, title, text, date, app version, likes, developer reply. Mix app links or IDs, many countries, newest or most relevant, date and star filters. 48/48 checked against store pages. $0.10 per 1,000 reviews.

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

## Pricing

from $0.10 / 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.

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 — both stores, one format

Scrape app reviews from the **Apple App Store and Google Play in one run**, with **the same fields for both stores**: rating, title, text, date, app version, likes, developer reply. Paste store links or app ids (mixed), pick countries, and get every review you need for monitoring, research or AI analysis. No login, no browser, no proxy to set up.

#### Why this Actor

- **Two stores, one dataset.** Put the iPhone and the Android version of an app in the same run and get one table, ready for a spreadsheet, a dashboard or an LLM.
- **Deep on Google Play.** Up to 1,000 reviews per request: 10,000 WhatsApp reviews in about 10 seconds, all distinct.
- **Checked against the real store pages.** 48 reviews shown on 9 Google Play and App Store pages (7 apps) compared field by field (text, stars, date, author, title, developer reply): 48 of 48 identical.
- **Built for monitoring.** *Reviews since* reads newest first and stops at your date, so a daily run only pays for the new reviews. Filter by star rating to collect complaints only.
- **Reliable.** Direct connection, automatic retries, and Apify Proxy only if a store ever blocks the run. Apple's review feed sometimes answers with an empty cached page: the Actor detects it and asks again, so you don't get "no reviews" for an app that has them.
- **Fair price:** $0.10 per 1,000 reviews, for both stores. Filtered-out reviews and error rows are free.

#### Use cases

- **App developers and product teams**: follow what users say after each release, per app version and per country.
- **Customer support**: collect 1- and 2-star reviews every day, with the developer's reply (Google Play).
- **Competitor research**: compare ratings and complaints of competing apps on iOS and Android.
- **AI and NLP**: sentiment analysis, topic clustering, feature requests, training data in 50+ countries and languages.
- **Agencies and ASO tools**: review monitoring for many client apps in one scheduled run.

#### Input

| Field | Description |
|---|---|
| Apps | App Store and Google Play apps, mixed, one per line: store links, Apple ids (`310633997`) or package names (`com.whatsapp`). |
| Countries | Two-letter codes (`us`, `gb`, `de`, `jp`…). Every app is scraped in every country. |
| Language (Google Play) | Empty = the main language of each country; or a code such as `en`, `es`, `pt-BR`. |
| Sort | Newest (default), Most relevant (the store page's order), Highest rating first (Google Play). |
| Max reviews per app and country | Default 100; 0 = all available. |
| Reviews since | Only reviews from this date on (newest first, stops at the date). |
| Star ratings | Keep only these ratings, e.g. 1 and 2 stars. |

Example:

```json
{
  "apps": [
    "https://play.google.com/store/apps/details?id=com.spotify.music",
    "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
  ],
  "countries": ["us", "gb"],
  "sort": "newest",
  "maxReviewsPerApp": 500,
  "ratings": ["1", "2"]
}
```

#### Output

One item per review, same fields for both stores (real examples):

```json
{
  "store": "google_play",
  "appId": "com.spotify.music",
  "country": "us",
  "language": "en",
  "appName": "Spotify: Music and Podcasts",
  "developer": "Spotify AB",
  "appRating": 4.35,
  "appRatingCount": 36389831,
  "reviewId": "2ead2b93-abd6-4680-b28a-b522b89dceea",
  "userName": "Kayleigh Rhodes",
  "rating": 2,
  "title": null,
  "text": "No widgets are working. I have to open the app to pause at any time. Very frustrating. If it's not one thing, it's another with this app.",
  "date": "2025-07-29T13:09:58.697Z",
  "appVersion": "9.0.64.608",
  "thumbsUp": 272,
  "developerReply": "Hey there! We understand your concern about the app. We'd love to get some more info about this. If you have the time, give our Customer Service a shout. ...",
  "developerReplyDate": "2025-07-29T16:01:04.058Z",
  "reviewUrl": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=2ead2b93-abd6-4680-b28a-b522b89dceea&hl=en&gl=us",
  "position": 332
}
```

```json
{
  "store": "app_store",
  "appId": "310633997",
  "country": "us",
  "appName": "WhatsApp Messenger",
  "developer": "WhatsApp Inc.",
  "appRating": 4.68,
  "appRatingCount": 18676128,
  "reviewId": "14599540909",
  "userName": "hhhhmmmmmzzzzdddd",
  "rating": 2,
  "title": "WORST APP EVER",
  "text": "I honestly don’t know wht people use this app instead of telegram. It is in one word TERRIBLE.",
  "date": "2026-09-27T13:27:40.000Z",
  "appVersion": "26.37.76",
  "voteSum": 0,
  "voteCount": 0,
  "position": 3
}
```

| Field | Meaning |
|---|---|
| `store` | `google_play` or `app_store`. |
| `appId`, `appName`, `developer`, `appRating`, `appRatingCount` | The app, its average rating and number of ratings in that store and country. |
| `rating`, `title`, `text`, `date` | The review (title: App Store only). Dates in UTC. |
| `appVersion` | App version the review was written for. |
| `thumbsUp` | Google Play "helpful" votes. `voteSum` / `voteCount`: App Store helpful votes. |
| `developerReply`, `developerReplyDate` | The developer's answer (Google Play). |
| `userName`, `userImage` | Reviewer name and picture (picture: Google Play). |
| `source`, `position`, `scrapedAt` | What you entered, the review's rank in the run for that app and country, and when it was scraped. |

Rows with a `status` are not reviews and are **not charged**:

| Status | Meaning |
|---|---|
| `not_found` | The app does not exist in that country's store. |
| `no_results` | The app has no written reviews, or none match your filters. |
| `invalid_input` | Not an App Store or Google Play app, or not a country code. |
| `error` | The store kept failing (rare); reviews saved before the error are kept. |

#### Tested (September 2026, on the Apify platform)

| Test | Result |
|---|---|
| Default input (WhatsApp, both stores, 20 each) | 40 reviews in about 2 seconds |
| Reviews shown on 9 store pages (7 apps) vs the Actor's output | 48 / 48 identical (Google Play 18, App Store 30) |
| Developer replies vs the Google Play page | 3 / 3 identical |
| Depth | Google Play 10,000 / 10,000 distinct; App Store 500 / 500 (Apple's maximum) |
| *Reviews since* and *Star ratings* on 4 apps | 511 reviews, 0 outside the date or the ratings |
| 9 countries (us, gb, de, jp, br, fr, it, ca, au) | Reviews in each country's language, 0 empty countries |
| Wrong inputs (unknown app, other website, bad country) | Clear free error rows, run succeeds |

#### Honest limits

- **Apple shows at most 500 reviews per app, country and sort order** (50 per page, 10 pages). This is Apple's limit for every tool that reads its public reviews; to get more, add countries or run both sorts (newest and most relevant).
- **App Store developer replies are not available** in Apple's public review data; Google Play replies are included.
- **Google Play groups reviews by language, not by country**: with the same language, `us` and `gb` return the same English reviews. Set a different language per run to get other markets.
- Google Play's *Most relevant* and *Highest rating first* orders are the store's own.

#### Pricing

**$0.10 per 1,000 reviews** (`review` event, $0.0001 each), for both stores. Filtered-out reviews and status rows are free. Set a maximum charge in the run options and the Actor stops there.

# Actor input Schema

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

App Store and Google Play apps, mixed, one per line: a store link (<code>https://apps.apple.com/us/app/whatsapp-messenger/id310633997</code>, <code>https://play.google.com/store/apps/details?id=com.whatsapp</code>), an Apple id (<code>310633997</code>) or a Google Play package name (<code>com.whatsapp</code>). Add the iPhone and the Android version of the same app to get both in one dataset.

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

Two-letter country codes, for example <code>us</code>, <code>gb</code>, <code>de</code>, <code>jp</code>. Every app is scraped in every country listed (the country in a store link is not used).

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

Google Play shows the reviews written in one language. Leave empty to use the main language of each country (English for us, German for de, Japanese for jp…), or set a code such as <code>en</code>, <code>es</code>, <code>pt-BR</code>. App Store reviews are always those of the country.

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

Order in which reviews are read. <b>Most relevant</b> is the order of the store page. <b>Highest rating first</b> works on Google Play only (the App Store then uses newest). To collect only low ratings, use <b>Star ratings</b> instead.

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

Limit for each app in each country. 0 = every review available (Google Play: all of them; App Store: Apple shows at most 500 per country and sort order).

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

Only reviews written on or after this date (for daily or weekly monitoring). Reviews are then read newest first and the run stops at this date.

## `ratings` (type: `array`):

Keep only reviews with these ratings, for example 1 and 2 stars to collect complaints. Leave empty for all. Reviews that are filtered out are not charged.

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

Not needed: the scraper connects directly and switches to Apify Proxy only if a store blocks it. Set a proxy here only to force one.

## Actor input object example

```json
{
  "apps": [
    "https://play.google.com/store/apps/details?id=com.whatsapp",
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
  ],
  "countries": [
    "us"
  ],
  "language": "",
  "sort": "newest",
  "maxReviewsPerApp": 20,
  "ratings": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per review, same fields for both stores: store, app, country, rating, title, text, date, app version, likes or votes, developer reply, user name.

# 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://play.google.com/store/apps/details?id=com.whatsapp",
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
    ],
    "countries": [
        "us"
    ],
    "maxReviewsPerApp": 20
};

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brii3343/app-store-google-play-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/NTp2WGq3lFYiptP4m/builds/83L9PUYGCTMTwasjC/openapi.json
