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

Scrape user reviews from BOTH Apple App Store and Google Play in one run, with one unified output schema. Multi-country, date and rating filters, developer replies included.

- **URL**: https://apify.com/carolling\_granite/app-reviews-scraper.md
- **Developed by:** [Ryan Chen](https://apify.com/carolling_granite) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 actor starts

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## App Store + Google Play Reviews Scraper

**Both mobile stores. One run. One schema.**

Most review scrapers cover a single store, so tracking one app across iOS and Android means running two Actors, learning two output formats, and writing glue code to stitch them together. This one returns Apple App Store and Google Play reviews as **identical rows** — same 17 fields, same field names, same date format — so you can group, filter and chart them the moment they land.

### What you get

- 🍎 **Apple App Store** — via Apple's own public review feed. No scraping tricks, no proxies, no breakage when a page layout changes.
- 🤖 **Google Play** — full pagination, so you can pull far more than the first page.
- 🌍 **Any market** — pass as many country codes as you like; reviews are region-specific and this treats them that way.
- 💬 **Developer replies** — captured with their timestamps, not dropped.
- 🎯 **Filters that save you money** — restrict by star rating, or by date. With `sinceDate` and newest-first sorting, the run *stops early* instead of paging through history you already have.
- 📦 **App metadata too** — title, developer, overall score, total rating count, price, version, icon.

### Input

| Field | What it does |
|---|---|
| `apps` | App Store links, Google Play links, numeric Apple IDs, or Android package names — **mixed freely in one list**. The store is detected for you. |
| `countries` | Two-letter codes, e.g. `["us","gb","de","jp"]` |
| `language` | Google Play review language (the App Store ignores it) |
| `maxReviewsPerApp` | Cap per app *per country* |
| `sort` | `newest` · `most_relevant` · `rating` |
| `minRating` / `maxRating` | e.g. `1`–`2` to read only the angry ones |
| `sinceDate` | ISO date. Only reviews after it. |
| `includeAppInfo` | Adds one metadata row per app |

```json
{
  "apps": [
    "https://apps.apple.com/us/app/facebook/id284882215",
    "com.facebook.katana"
  ],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 200,
  "sort": "newest",
  "minRating": 1,
  "maxRating": 2,
  "sinceDate": "2026-01-01"
}
```

### Output

Every row — from either store — looks like this:

```json
{
  "platform": "app_store",
  "type": "review",
  "appId": "284882215",
  "appName": "Facebook",
  "country": "us",
  "language": null,
  "reviewId": "https://itunes.apple.com/us/review?id=284882215&type=Purple%20Software",
  "userName": "Hannmillwood",
  "rating": 1,
  "title": "Why are you trying to charge me 20 to get Facebook back",
  "text": "After i accidentally deleted it??!?! I want my Facebook back!",
  "appVersion": "575.0.0",
  "submittedAt": "2026-08-21T09:14:33-07:00",
  "thumbsUp": 0,
  "voteCount": 0,
  "developerReply": null,
  "developerReplyAt": null,
  "url": "https://itunes.apple.com/us/reviews/id123456789",
  "scrapedAt": "2026-08-22T04:11:02+00:00"
}
```

`title` is always `null` for Google Play (that store has no review titles) and `developerReply` is always `null` for the App Store (Apple's public feed does not expose them). Everything else is populated by both.

### Good for

- **Competitor teardowns** — pull your rival's 1★ reviews across both stores and read what their users actually hate.
- **Release monitoring** — filter by `appVersion` and `sinceDate` to see what a ship did to sentiment.
- **Support triage** — feed reviews into an LLM to cluster complaints.
- **ASO research** — compare the same app's reception market by market.

### Honest limits

- Apple's public feed returns **at most 500 reviews per app per country** (10 pages × 50). Setting a higher cap will not get you more from that store — widen `countries` instead. Google Play has no such wall.
- **Google Play is not partitioned by country the way the App Store is.** Ask it for `us` and `gb` and it largely replays the same global review stream. This Actor deduplicates across the whole run, so you never receive — or pay for — the same review twice, and it stops paging a country once it is only replaying reviews you already have. For Google Play, vary `language` rather than `countries`. The App Store *is* genuinely per-country, and there more country codes really do mean more reviews.
- Apple's feed does not include developer replies. That is Apple's limitation, not this Actor's.
- Google Play review text is what the user typed; emoji-only reviews are common and are returned as-is.

### Pricing

Pay per event — you pay for rows you actually receive, not for runtime:

| Event | When |
|---|---|
| `actor-start` | Once per run |
| `review-scraped` | Per review row |
| `app-info-scraped` | Per app metadata row |

Filtered-out reviews are **not** charged. Neither are duplicates — see the Google Play note above.

# Actor input Schema

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

App Store or Google Play links (or raw IDs). The store is detected automatically — mix both freely.

Accepted: `https://apps.apple.com/us/app/facebook/id284882215` · `284882215` · `https://play.google.com/store/apps/details?id=com.facebook.katana` · `com.facebook.katana`

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

Two-letter country codes. Reviews are store-region specific, so add every market you care about. Apple returns up to 500 reviews per app per country.

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

Two-letter language code for Google Play reviews. The App Store ignores this — it returns whatever the country's store holds.

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

Hard cap so a run cannot surprise you. Apple's public feed tops out at 500 per country no matter what you set here; Google Play can go far higher.

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

`newest` is best for monitoring, `most_relevant` for a representative sample, `rating` for digging into the low-star complaints.

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

Drop reviews below this star rating. Set to 1 to keep everything.

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

Drop reviews above this star rating. Combine with Minimum rating to isolate, say, only 1–2 star complaints.

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

ISO date, e.g. `2026-01-01`. Leave empty for no date limit. Scraping stops early once it walks past this date, which saves you money.

## `includeAppInfo` (type: `boolean`):

Pushes one extra row per app with title, developer, overall score, total rating count, price and icon.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/facebook/id284882215",
    "com.facebook.katana"
  ],
  "countries": [
    "us"
  ],
  "language": "en",
  "maxReviewsPerApp": 100,
  "sort": "newest",
  "minRating": 1,
  "maxRating": 5,
  "includeAppInfo": true
}
```

# Actor output Schema

## `reviews` (type: `string`):

The full dataset: reviews from both stores, unified into the same 19 fields.

## `reviewsCsv` (type: `string`):

The same rows as a spreadsheet-ready CSV.

## `reviewsTable` (type: `string`):

Open the dataset in the Apify Console table view.

# 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/facebook/id284882215",
        "com.facebook.katana"
    ],
    "countries": [
        "us"
    ]
};

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

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

```

## MCP server setup

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