# App Reviews: App Store + Google Play (`grit-77/app-reviews-app-store-google-play`) Actor

App Store and Google Play reviews scraper for feedback analysis. Export review text, ratings, dates and developer replies as JSON, with optional app profile rows.

- **URL**: https://apify.com/grit-77/app-reviews-app-store-google-play.md
- **Developed by:** [Grit](https://apify.com/grit-77) (community)
- **Categories:** Marketing, Developer tools
- **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.

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: App Store + Google Play

App Store and Google Play reviews scraper returns review text, ratings, dates, and developer replies. App reviews API also returns app profile rows when requested.

Sources: the public web reviews endpoint of apps.apple.com (with Apple's customer-reviews RSS JSON as automatic fallback), the iTunes Lookup API for app metadata, and the public Google Play store pages. No logins, no API keys.

### What you get

| Field | Type | Example value |
|---|---|---|
| `type` | string | `"app"` |
| `store` | string | `"apple"` |
| `app_id` | string | `"324684580"` |
| `app_name` | string | `"Spotify: Music and Podcasts"` |
| `country` | string | `"us"` |
| `language` | string | `"en"` |
| `rating_avg` | number | `4.77209` |
| `ratings_count` | integer | `42426516` |
| `installs` | string | `"10,000,000,000+"` |
| `version` | string | `"9.1.88"` |
| `updated` | string | `"2026-10-01T15:03:03Z"` |
| `released` | string | `"2011-07-14T11:22:37Z"` |
| `developer` | string | `"Spotify"` |
| `developer_id` | string | `"324684583"` |
| `category` | string | `"Music"` |
| `price` | number | `0.0` |
| `currency` | string | `"USD"` |
| `content_rating` | string | `"12+"` |
| `bundle_id` | string | `"com.spotify.client"` |
| `icon` | string | `"https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/5f/b6/e0/5fb6e0c6-cea6-e107-8d54-8e8fcec573ce/AppIcon-0-0-1x_U007epad-0-1-0-0-sRGB-85-220.png/512x512bb.jpg"` |
| `source_url` | string | `"https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580?uo=4"` |
| `review_id` | string | `"14625616231"` |
| `author` | string | `"Hhhmm lo fácil"` |
| `rating` | integer | `5` |
| `title` | string | `"I love Spotify"` |
| `text` | string | `"You can listen to every song and you can find every song"` |
| `date` | string | `"2026-10-04T06:24:26Z"` |
| `thumbs_up` | integer | `0` |
| `developer_reply` | string | `null` |
| `developer_reply_date` | string | `"2026-06-26T11:09:03Z"` |

`app` rows add: `rating_avg`, `ratings_count`, `installs` (Google Play), `version`, `updated`, `released`, `developer`, `developer_id`, `category`, `price`, `currency`, `content_rating`, `bundle_id`, `icon`.

### Input example

```json
{
  "apps": [
    "324684580"
  ],
  "countries": [
    "us"
  ],
  "sort": "newest",
  "maxReviewsPerApp": 10
}
```

Use the input schema for the remaining filters and defaults.

### Output example

This is a selected-field excerpt of the first object in [sample_output.json](sample_output.json).

```json
{
  "type": "app",
  "store": "apple",
  "app_id": "324684580",
  "app_name": "Spotify: Music and Podcasts",
  "country": "us",
  "language": "en",
  "rating_avg": 4.77209,
  "ratings_count": 42426516,
  "installs": null,
  "version": "9.1.88",
  "updated": "2026-10-01T15:03:03Z",
  "released": "2011-07-14T11:22:37Z",
  "developer": "Spotify",
  "developer_id": "324684583"
}
```

### Pricing

Pay per event: **$0.00009 per review** and **$0.002 per app-info row** (switch off with `includeAppInfo`). No start fee, error rows are free. See `PRICING.md` for the comparison with the other review actors in the Store.

### Measured on Apify (2026-10-05)

Spotify on both stores, country `us`, newest 50 per app: 100 reviews and 2 app rows, 8.3 s run time, 512 MB memory (peak use 62 MB), 0.0012 compute units. Event charges for that run: $0.013.

### Measured on a local run

4 apps (Instagram and Spotify on the App Store, WhatsApp and Spotify on Google Play), 2 countries (us, gb), newest 60 per app and country: 480 reviews and 8 app rows in 3.2 s. A first run took 30 s because Apple answered with 429 rate-limit responses that the actor retried with backoff. 19 of the 480 reviews carried a developer reply.

### Limits and honest caveats

- **App Store**: the primary source is the web reviews endpoint of apps.apple.com. It pages back through the full history (20 per request) but carries neither the app version nor helpful votes, so `version` and `thumbs_up` are `null` for these rows. Apple's documented RSS feed (`itunes.apple.com/{country}/rss/customerreviews/...`, 10 pages of 50) does carry them, but on the day this was built it returned empty pages for most apps and pages (Apple serves it from a sparse cache), so it is used as a fallback only. `appleSource: "rss"` forces it.
- **Google Play** serves most reviews per language, not per country: the same review appears under several countries, so it is kept once, under the first country. To get more of one app, raise `maxReviewsPerApp` or add languages.
- The `languages` option only creates extra passes on Google Play; the App Store review set does not depend on it.
- Both stores can throttle. The actor retries with backoff; an app that still fails produces an `error` row instead of stopping the run.
- The data is public store content and includes reviewer display names as the stores publish them. Use it in line with the stores' terms and applicable privacy law.

### FAQ

**What limits the output?** The maxItems input caps output rows; its schema maximum is 1,000,000. Source availability and errors may yield fewer rows.

**Does it need a proxy, login, or API key?** The actor reads public App Store and Google Play pages or feeds without a store login. No proxy input is defined.

**How is it priced?** PRICING.md proposes $0.00009 per review row and $0.002 per app profile row when app info is enabled. These are proposed custom events.

**What happens on rate limits?** The code bounds parallel store requests and backs off after transient failures. Store throttling can reduce results.

**How fresh is the data?** Rows reflect the store response at run time. Review date and app updated date describe source records, not a live subscription.

**Can one run mix stores?** Yes. The apps input accepts App Store IDs or URLs and Google Play package names or URLs.

### Use with AI agents / MCP

Call the actor through the Apify MCP server (`https://mcp.apify.com`) or the Apify API as a tool: pass `apps` and filters, then read the dataset. The unified schema lets an agent compare iOS and Android sentiment for the same product from a single call. Example prompt: "Get the 1 and 2 star reviews of Spotify on both stores since 2026-09-01 and summarise the top complaints by version."

# Actor input Schema

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

App Store URLs or numeric ids (https://apps.apple.com/us/app/spotify/id324684580, 324684580) and Google Play URLs or package names (https://play.google.com/store/apps/details?id=com.spotify.music, com.spotify.music). The store is detected automatically; prefix with `ios:` or `android:` to force it.

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

2-letter country codes, e.g. us, gb, de. App Store reviews are per storefront. Google Play shares most reviews between countries of the same language, so repeats are removed (kept under the first country). If left empty, the country in an app URL is used, otherwise `us`.

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

Language codes, e.g. en, de, pt-BR. Google Play returns reviews per language, so each one is a separate pass. The App Store review set does not depend on language, so only the first one is used there.

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

`newest` returns the latest reviews first (best for monitoring and with a start date). `relevant` returns the store's own ranking (Apple: most helpful, Google Play: most relevant).

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

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

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

Keep reviews with at most this many stars (1-5). Use minRating 1 and maxRating 2 to collect complaints.

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

ISO date or datetime, e.g. 2026-09-01. Reviews older than this are dropped; with sort `newest` reading stops there, which keeps runs short.

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

Upper bound of reviews kept for each app in each country/language pass, after filters. 0 returns only app info.

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

Hard cap on all charged rows (reviews plus app-info rows). Error rows are free and not counted.

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

Add one `type: app` row per app and country with average rating, ratings count, installs (Google Play), version, last update and developer. Charged as its own event.

## `maxConcurrency` (type: `integer`):

How many apps are read in parallel. Keep low; both stores rate-limit.

## `appleSource` (type: `string`):

`auto` reads the public web reviews endpoint of apps.apple.com and falls back to Apple's customer-reviews RSS feed. `web` or `rss` force one. RSS is limited to 500 reviews and often returns empty pages.

## Actor input object example

```json
{
  "apps": [
    "https://apps.apple.com/us/app/instagram/id389801252",
    "https://play.google.com/store/apps/details?id=com.whatsapp"
  ],
  "countries": [
    "us"
  ],
  "languages": [
    "en"
  ],
  "sort": "newest",
  "minRating": 1,
  "maxRating": 5,
  "maxReviewsPerApp": 200,
  "maxItems": 1000,
  "includeAppInfo": true,
  "maxConcurrency": 4,
  "appleSource": "auto"
}
```

# Actor output Schema

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

Dataset with all result rows

# 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/instagram/id389801252",
        "https://play.google.com/store/apps/details?id=com.whatsapp"
    ],
    "countries": [
        "us"
    ],
    "languages": [
        "en"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("grit-77/app-reviews-app-store-google-play").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/instagram/id389801252",
        "https://play.google.com/store/apps/details?id=com.whatsapp",
    ],
    "countries": ["us"],
    "languages": ["en"],
}

# Run the Actor and wait for it to finish
run = client.actor("grit-77/app-reviews-app-store-google-play").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/instagram/id389801252",
    "https://play.google.com/store/apps/details?id=com.whatsapp"
  ],
  "countries": [
    "us"
  ],
  "languages": [
    "en"
  ]
}' |
apify call grit-77/app-reviews-app-store-google-play --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,grit-77/app-reviews-app-store-google-play"
        }
    }
}
```

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/oThihyCZB3Eix6LFx/builds/nepOO1vojVUDtJYQE/openapi.json
