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

App reviews scraper and API for Google Play and the App Store: reviews with rating, text, date, version and developer replies, plus app details and search. Multi-country.

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

## Pricing

Pay per event

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 Reviews Scraper — Google Play & App Store Reviews

Scrape app reviews from **Google Play and the Apple App Store in one run**: star rating,
review text, date, app version, helpful votes and the developer's reply, plus app details
(rating, number of ratings, installs, price, genre, version, last update) and keyword
search. Compare your iOS and Android apps, or your competitors', across countries and
languages. No login, no API key, no developer account. Export as JSON, CSV or Excel, or
pull the data through the API.

### What does App Reviews Scraper do?

App Reviews Scraper collects public data from both big app stores and returns it in one
dataset with the same fields for both stores:

- **Reviews** — paste Google Play or App Store links (or app IDs) and get the reviews:
  author, star rating, title (App Store), full text, date, app version, thumbs-up /
  helpful votes, and the developer's reply with its date (Google Play).
- **App details** — name, developer, average rating, number of ratings, rating histogram
  and installs (Google Play), price and currency, genre, content rating, current version,
  release and last update dates, short and full description, release notes, icon.
- **Search** — enter keywords such as "meditation" or "budget planner" and the scraper
  finds the top apps in Google Play, the App Store or both, then collects their details
  and reviews.
- **Countries and languages** — the App Store keeps separate reviews per country, so you
  can collect US, UK, German and Japanese reviews of the same app in one run. Google Play
  reviews are collected per language (English, German, Spanish, Brazilian Portuguese…).
- **Filters** — newest first or most relevant, only 1–2 star reviews (or any star
  range), and only reviews since a date or for the last N days.

Store and app are detected automatically from each link, so a single input list can mix
both stores.

### Use cases

- **Product and app teams** — read what users say after each release (`appVersion`
  field), find crash and bug reports in 1–2 star reviews, and compare iOS vs Android
  satisfaction for the same app.
- **App marketers and ASO specialists** — track competitors' ratings, rating counts,
  installs, release cadence and review themes in every market you target.
- **Customer support** — export reviews with and without developer replies to measure
  response coverage and find unanswered complaints.
- **Market researchers** — search a category keyword in both stores and build a
  comparison table of the leading apps with their ratings, prices and review samples.
- **Data scientists and AI teams** — feed thousands of labelled (1–5 star) reviews into
  sentiment analysis, topic modelling or an LLM summary of user feedback.
- **Agencies** — schedule weekly runs with "Reviews since: 7 days" and send new negative
  reviews of client apps to Slack or Google Sheets.

### How much does it cost?

You pay only for the results you get (pay-per-event). Duplicates and items over your
`maxItems` limit are never charged.

| Event | What you pay for | Free plan | Paid plans (from) |
| --- | --- | --- | --- |
| `review` | One review (Google Play or App Store) | $0.30 per 1,000 | $0.15 per 1,000 |
| `app` | One app details record | $1.00 per 1,000 | $0.50 per 1,000 |

"Paid plans (from)" is the Gold-and-above price; Bronze and Silver plans sit in between.
Apify also charges a tiny actor-start fee ($0.00005 per run).

Worked examples (Free plan prices):

1. **iOS vs Android comparison** — 500 US App Store reviews + 500 Google Play reviews of
   one app, with both app records: 1,000 × $0.30 / 1,000 + 2 × $0.001 = **$0.30**.
2. **Weekly negative-review alert for 20 apps** — 1–2 star reviews from the last 7 days,
   about 50 per app: 1,000 reviews = **$0.30 per week**.

The Apify Free plan includes $5 monthly credit, enough for about 16,000 reviews every
month.

### How to use App Reviews Scraper

In Apify Console:

1. Open App Reviews Scraper and click **Try for free**.
2. Paste app links into **App URLs** (Google Play and App Store links can be mixed), or
   enter **Search keywords**. The form is prefilled with Spotify on both stores.
3. Set **Max reviews per app**, the sort order and, if you like, **Countries**,
   **Languages**, a star-rating range or **Reviews since**.
4. Click **Start** and wait for the run to finish (a few seconds for hundreds of reviews).
5. Open the **Output** tab and export the dataset as JSON, CSV, Excel or HTML.

Through the API:

1. Get your API token in Apify Console → Settings → Integrations.
2. Call the actor with your input JSON (see [Integrations and API](#integrations-and-api)).
3. Read the dataset items from the run.

### Input

Fill in at least one of `appUrls`, `appIds` or `searchTerms`.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `appUrls` | array | – | Google Play (`play.google.com/store/apps/details?id=...`) or App Store (`apps.apple.com/us/app/.../id123456789`) links, mixed. |
| `appIds` | array | – | Google Play package names (`com.spotify.music`) or numeric App Store ids (`324684580`). |
| `maxReviewsPerApp` | integer | `100` | Reviews per app, per App Store country and per Google Play language/country. `0` = app details only. |
| `sort` | string | `newest` | `newest`, `relevance` (Google Play "Most relevant", App Store "Most helpful") or `rating` (Google Play's Rating order; App Store uses Most helpful). |
| `includeAppDetails` | boolean | `true` | Also output one `app` item per app (per country on the App Store). |
| `countries` | array | – | Two-letter codes (`us`, `gb`, `de`, `jp`…). App Store: reviews and details per country. Google Play: store country (prices, availability, ranking of "relevance" reviews). Empty = the country in the App Store link, else `us`. |
| `languages` | array | `["en"]` | Google Play review languages (`en`, `de`, `es`, `pt-BR`…), each collected separately. |
| `searchTerms` | array | – | Keywords to search in the stores below. Found apps are scraped like app links. |
| `searchStores` | array | both | `googlePlay`, `appStore` or both. |
| `maxSearchResults` | integer | `5` | Top apps per keyword and store (1–200). |
| `minRating` / `maxRating` | integer | `1` / `5` | Keep only reviews in this star range. |
| `reviewsSince` | string | – | A date (`2026-10-01`) or a period (`7 days`, `2 weeks`, `3 months`). |
| `maxItems` | integer | `1000` | Hard cap on all output items (reviews + apps) in the run. |
| `proxyConfiguration` | object | Apify Proxy | Proxy settings. |
| `debug` | boolean | `false` | Log every page fetched. |

Example — iOS vs Android, US and UK, only 1–2 star reviews from the last 30 days:

```json
{
    "appUrls": [
        "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"],
    "languages": ["en"],
    "minRating": 1,
    "maxRating": 2,
    "reviewsSince": "30 days",
    "maxReviewsPerApp": 500
}
```

Example — find the top 3 meditation apps in both stores, details only:

```json
{
    "searchTerms": ["meditation"],
    "searchStores": ["googlePlay", "appStore"],
    "maxSearchResults": 3,
    "maxReviewsPerApp": 0
}
```

### Output

Every item has `type` (`review` or `app`) and `store` (`googlePlay` or `appStore`).
Examples below come from a real run on 2026-11-02 (long text shortened).

#### Review (Google Play, with developer reply)

```json
{
    "type": "review",
    "store": "googlePlay",
    "appId": "com.spotify.music",
    "appName": "Spotify: Music and Podcasts",
    "reviewId": "1ae4163a-cd41-49ef-ac44-15de331963f3",
    "author": "Scott Serago",
    "authorImage": "https://play-lh.googleusercontent.com/a/ACg8ocK7I2Zib7P8rlBWSMReFwgI7BCOm5HzJeiMSQSMnVr4yvhQXA=mo",
    "rating": 1,
    "title": null,
    "text": "app constantly fails to start claiming im offline when i have full wifi and cellular. song duplications eat space unnecessarily without a duplicate filter option...",
    "date": "2026-11-01T16:07:39Z",
    "appVersion": "9.1.94.1929",
    "thumbsUp": 0,
    "replyText": "Hi, we can see how this would affect your listening experience. Could you restart your device and internet connection, and try switching between 4G/5G/WiFi? ...",
    "replyDate": "2026-10-31T15:48:31Z",
    "country": "us",
    "language": "en",
    "url": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=1ae4163a-cd41-49ef-ac44-15de331963f3",
    "searchTerm": null
}
```

#### Review (App Store)

```json
{
    "type": "review",
    "store": "appStore",
    "appId": "324684580",
    "appName": "Spotify: Music and Podcasts",
    "reviewId": "14736661579",
    "author": "StyloSavage",
    "authorImage": null,
    "rating": 1,
    "title": "Terrible performance now",
    "text": "App freezes, doesn’t play music and stays in a loading loop",
    "date": "2026-11-01T07:12:42Z",
    "appVersion": "9.1.94",
    "thumbsUp": 0,
    "replyText": null,
    "replyDate": null,
    "country": "us",
    "language": null,
    "url": "https://apps.apple.com/us/app/id324684580?see-all=reviews",
    "searchTerm": null
}
```

#### App

```json
{
    "type": "app",
    "store": "googlePlay",
    "appId": "com.spotify.music",
    "bundleId": "com.spotify.music",
    "name": "Spotify: Music and Podcasts",
    "developer": "Spotify AB",
    "developerId": "Spotify+AB",
    "developerEmail": "support@spotify.com",
    "developerWebsite": "https://www.spotify.com",
    "rating": 4.3491,
    "ratingsCount": 36581291,
    "reviewsCount": 1857986,
    "ratingsHistogram": { "1": 3719183, "2": 1068492, "3": 1310636, "4": 3106198, "5": 27376767 },
    "installs": "1,000,000,000+",
    "installsMin": 1000000000,
    "installsExact": 3181010787,
    "price": 0.0,
    "currency": "USD",
    "free": true,
    "inAppPurchases": "$4.99 - $203.88 per item",
    "genre": "Music & Audio",
    "genreId": "MUSIC_AND_AUDIO",
    "contentRating": "Teen",
    "version": null,
    "released": "2014-05-27T13:12:17Z",
    "updated": "2026-11-02T11:59:56Z",
    "summary": "Listen to songs, play podcasts, create playlists and discover music you'll love",
    "description": "With the Spotify music and podcast app, you can play millions of songs, albums and original podcasts for free...",
    "releaseNotes": "We’re always making changes and improvements to Spotify...",
    "icon": "https://play-lh.googleusercontent.com/IzQgYCcnCFCD08GR-3bdtcT8xzOvrNkC84avGT5CwTX2VIqmTmKKJcP_Cd4JoBOdmCMlTndlOzV6hrthg2fOWA",
    "country": "us",
    "language": "en",
    "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en&gl=US",
    "searchTerm": null
}
```

App Store app items have the same fields: for Spotify they show `bundleId:
"com.spotify.client"`, `rating: 4.7701`, `ratingsCount: 42891031` (for that country),
`version: "9.1.94"` and `contentRating: "12+"`.

Field notes:

- `date` is when the review was last written or edited, in UTC (ISO 8601).
- `thumbsUp` is the "helpful" count on Google Play and the helpful-vote count on the App
  Store.
- Fields a store does not publish are `null`: App Store reviews have no developer reply,
  author image or language; Google Play reviews have no title. App Store apps have no
  installs, rating histogram or developer email.
- Google Play `version` is `null` when the store shows "Varies with device".
- `searchTerm` is filled for apps (and their reviews) found through a keyword search.
- `country` on Google Play reviews is the store country used for the request; Google Play
  groups reviews by `language`, not by country.

### Integrations and API

Run the actor and get the items back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/innolabs~app-reviews-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"appIds": ["com.spotify.music", "324684580"], "maxReviewsPerApp": 200}'
```

Python with [apify-client](https://docs.apify.com/api/client/python):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("innolabs/app-reviews-scraper").call(
    run_input={
        "appUrls": ["https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"],
        "countries": ["us", "gb", "de"],
        "maxRating": 2,
        "maxReviewsPerApp": 300,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "review":
        print(item["store"], item["country"], item["rating"], item["text"][:80])
```

- **Make, Zapier, n8n** — use the Apify app/node to start the actor and send new reviews
  to Google Sheets, Airtable, Notion, Slack, Jira or email.
- **Scheduling** — create a schedule in Apify Console (e.g. every Monday) with
  "Reviews since: 7 days" so each run delivers only the past week's reviews.
- **Webhooks** — trigger your pipeline when a run finishes.
- **AI agents (MCP)** — connect Claude, Cursor or other MCP clients through the Apify MCP
  server at https://mcp.apify.com and let your agent pull and summarise app reviews on
  demand.

### FAQ

#### Is it legal to scrape app reviews?

The scraper only collects data that both stores show publicly to anyone without logging
in: reviews, ratings and app listings. It does not log in or access private data.
Reviews contain reviewer names, which may be personal data under laws such as GDPR, so
make sure you have a legitimate reason to store them and that your use complies with the
stores' terms.

#### Do I need proxies?

No setup is needed. The default Apify Proxy setting works for both stores, and the
scraper retries throttled requests automatically.

#### How many reviews can I get?

Google Play: as many as the app has in the chosen language, page by page (tested with
thousands per app). App Store: Apple publishes the 500 most recent reviews per country
(or the 500 most helpful), so for more App Store reviews add more `countries`.
`maxReviewsPerApp` and `maxItems` keep the cost under your control.

#### Can I get only new reviews?

Yes. Set **Reviews since** to a date or a period like `7 days` and keep the sort on
**Newest first**: the scraper stops as soon as it reaches older reviews, so a scheduled
run delivers just the recent ones and you pay only for those.

#### What if an app or a link fails?

Each app is processed on its own. If one link is wrong, an app was removed, or it is not
available in a country, the run continues with the rest and the problem is listed in the
run log and in the run's `SUMMARY` record. You are not charged for failed apps. If every
app fails, the run is marked as failed with the reason.

#### Why does the same app have different ratings on Google Play and the App Store?

The stores rate independently and the App Store counts ratings per country, which is
exactly what the comparison is for. Use the `country` field to compare like with like.

### Limits

- App Store: at most 500 reviews per app and country (Apple's public review feed has 10
  pages of 50), sorted by newest or most helpful only. Apple sometimes leaves a page of
  the feed empty, so a country can return a little less (e.g. 450). Developer replies to
  App Store reviews are not available.
- Google Play: reviews are grouped by language; adding several countries for the same
  language returns the same reviews (they are delivered and charged once).
- Google Play search shows about 20–30 apps per keyword; App Store search up to 200.
- Rating filters with a single star value (e.g. only 1-star) are applied by Google Play
  itself; star ranges are filtered after download, so the scraper may read more pages to
  find enough matching reviews.
- Review dates are the dates the stores display (the last time a review was written or
  edited).

# Changelog

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

# Actor input Schema

## `appUrls` (type: `array`):

Google Play or App Store app pages, mixed freely. The store is detected from the URL, e.g. https://play.google.com/store/apps/details?id=com.spotify.music or https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580.

## `appIds` (type: `array`):

App identifiers instead of URLs: a Google Play package name (com.spotify.music) or a numeric App Store id (324684580 or id324684580).

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

How many reviews to collect per app, per country (App Store) and per language/country combination (Google Play). Set 0 to get only app details. The App Store publishes at most 500 recent reviews per country.

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

Newest first, most relevant (Google Play) / most helpful (App Store), or Google Play's Rating order (the App Store uses most helpful for this option).

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

Also output one app item per app (and per country on the App Store): name, developer, rating, number of ratings, installs (Google Play), price, genre, version, last update and description.

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

Two-letter country codes (us, gb, de, fr, jp, ...). App Store: reviews and app details are collected for each country. Google Play: sets the store country (prices, availability, review ranking). Empty = the country in the App Store URL, otherwise us.

## `languages` (type: `array`):

Google Play review languages, e.g. en, de, es, pt-BR. Reviews are collected separately for each language. The App Store ignores this option (its reviews are per country).

## `searchTerms` (type: `array`):

Keywords searched in the stores below, e.g. 'meditation' or 'budget planner'. Each found app is scraped like an app URL (details and reviews).

## `searchStores` (type: `array`):

Stores to search: googlePlay, appStore or both.

## `maxSearchResults` (type: `integer`):

How many top search results to scrape per keyword and store. Google Play shows up to about 30 apps per search, the App Store up to 200.

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

Keep only reviews with at least this many stars (1-5).

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

Keep only reviews with at most this many stars (1-5). Set min and max to 1 to get only 1-star reviews.

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

Only reviews from this date on: a date (2026-10-01) or a period back from now (7 days, 2 weeks, 3 months). With 'Newest first' the scraper stops paging when it reaches older reviews.

## `maxItems` (type: `integer`):

Hard cap on dataset items (reviews and apps together). The run stops cleanly when reached.

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

Apify Proxy settings. The default datacenter proxy works for both stores.

## `debug` (type: `boolean`):

Log per-app progress and diagnostics.

## Actor input object example

```json
{
  "appUrls": [
    "https://play.google.com/store/apps/details?id=com.spotify.music",
    "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
  ],
  "maxReviewsPerApp": 50,
  "sort": "newest",
  "includeAppDetails": true,
  "languages": [
    "en"
  ],
  "searchStores": [
    "googlePlay",
    "appStore"
  ],
  "maxSearchResults": 5,
  "minRating": 1,
  "maxRating": 5,
  "reviewsSince": "",
  "maxItems": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "debug": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

All items produced by the run, one JSON object per record.

# 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 = {
    "appUrls": [
        "https://play.google.com/store/apps/details?id=com.spotify.music",
        "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
    ],
    "maxReviewsPerApp": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("innolabs/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 = {
    "appUrls": [
        "https://play.google.com/store/apps/details?id=com.spotify.music",
        "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580",
    ],
    "maxReviewsPerApp": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("innolabs/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 '{
  "appUrls": [
    "https://play.google.com/store/apps/details?id=com.spotify.music",
    "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
  ],
  "maxReviewsPerApp": 50
}' |
apify call innolabs/app-reviews-scraper --silent --output-dataset

```

## MCP server setup

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