# App Store Reviews Scraper: Apple & Google Play API (`morgan-studio/app-store-reviews-scraper`) Actor

App Store reviews scraper and Google Play reviews scraper in one actor: export app reviews and app details by app ID, package name or store URL, in any country, to JSON or CSV. Rating, rating count, price, version, developer and review text. Failed items are free and still reported.

- **URL**: https://apify.com/morgan-studio/app-store-reviews-scraper.md
- **Developed by:** [Morgan Studio](https://apify.com/morgan-studio) (community)
- **Categories:** Developer tools, 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 Reviews Scraper (Apple + Google Play)

### What is App Store Reviews Scraper?

**App Store Reviews Scraper** is an **App Store reviews scraper** and **Google Play reviews scraper** in one actor: it collects **app reviews and app details from the Apple App Store and Google Play** as clean JSON, ready to export to CSV or Excel. Give it Apple app ids, App Store URLs, Google Play package names, or Play URLs, in any mix, and pick the store countries. For each app and country it returns the title, developer, price, star rating, rating count, version, release and update dates, genres, description, and screenshot count. For each review it returns the stars, title, text, author, app version, and date.

It reads Apple's public iTunes lookup API and customer-reviews feed, and Google Play's public app pages, over plain HTTP. No browser, no proxy, no sign-in. You pay per record: $0.003 per app-detail record and $0.0001 per review ($0.10 per 1,000 reviews). Failed items are never charged.

The easiest way to try it: paste a few app ids into the **Apps** field and press **Start**.

### What data can you extract from the App Store and Google Play?

Each app becomes one `app-detail` record per country. Anything a store does not publish is `null`; no key is ever missing.

| Field | Type | Apple | Google Play |
|---|---|---|---|
| `recordType` | string | `app-detail` | `app-detail` |
| `store` | string | `apple` | `google-play` |
| `appId` | string | Numeric app id | Package name |
| `country` | string | Store country, for example `us` | same |
| `title` | string | yes | yes |
| `developer`, `developerId` | string | yes | yes |
| `bundleId` | string | yes | Package name |
| `price`, `currency`, `formattedPrice` | number, string | yes | yes |
| `rating`, `ratingCount` | number | yes | yes |
| `ratingCurrentVersion`, `ratingCountCurrentVersion` | number | yes | `null` |
| `version` | string | yes | `null` (see Limits) |
| `releaseDate`, `lastUpdated` | string | ISO date | ISO date |
| `releaseNotes` | string | What's new | What's new |
| `genres`, `primaryGenre` | array, string | yes | yes |
| `contentRating` | string | For example `12+` | For example `Teen`, `PEGI 3` |
| `description` | string | Full description | Full description |
| `screenshotsCount` | number | iPhone + iPad + Apple TV | yes |
| `iconUrl` | string | yes | yes |
| `installs` | string | `null` | For example `1,000,000,000+` |
| `sizeBytes`, `minimumOsVersion`, `languages` | number, string, array | yes | `null` |
| `storeUrl`, `developerUrl` | string | yes | yes |
| `input` | string | What you typed | same |
| `fetchedAt`, `fetchStatus`, `error` | string | | |

Each review becomes one `review` record:

| Field | Type | Notes |
|---|---|---|
| `recordType` | string | `review` |
| `store`, `appId`, `country` | string | Which app and store it came from |
| `reviewId` | string | The store's review id |
| `title` | string | Apple only; Play reviews have no title |
| `body` | string | Review text |
| `rating` | number | Stars, 1 to 5 |
| `author` | string | Reviewer name |
| `authorUrl` | string | Apple only |
| `version` | string | App version the review was written on |
| `date` | string | ISO timestamp |
| `voteSum` | number | Apple: helpful votes sum. Play: thumbs-up count |
| `voteCount` | number | Apple only |
| `developerReply` | string | Play only, when the developer replied |
| `sortBy` | string | `mostRecent` or `mostHelpful` |
| `position` | number | Order within this app and country |
| `fetchedAt`, `fetchStatus`, `error` | string | |

Example app-detail record (description shortened):

```json
{
  "recordType": "app-detail",
  "store": "apple",
  "appId": "324684580",
  "country": "us",
  "title": "Spotify: Music and Podcasts",
  "developer": "Spotify",
  "developerId": "324684583",
  "bundleId": "com.spotify.client",
  "price": 0,
  "currency": "USD",
  "formattedPrice": "Free",
  "rating": 4.77159,
  "ratingCount": 42549933,
  "version": "9.1.90",
  "releaseDate": "2011-07-14T11:22:37Z",
  "lastUpdated": "2026-10-08T07:37:17Z",
  "genres": ["Music", "Entertainment"],
  "primaryGenre": "Music",
  "contentRating": "12+",
  "screenshotsCount": 14,
  "storeUrl": "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580",
  "fetchStatus": "ok",
  "error": null
}
```

The Output tab has two views: App details and Reviews.

### Why use this app review scraper?

- **Both stores in one run.** Apple ids and Play package names go in the same list; the store is detected from the format.
- **Every input comes back.** Each app and country produces a record, including failures, with a `fetchStatus` and an `error` message. Nothing is dropped silently, and failed records are free.
- **Tested before release.** In the release verification runs on Apify (2026-10-12), 10 of 10 Apple apps in 3 countries returned 30 of 30 app-detail records and 1,500 of 1,500 reviews, and 5 of 5 Google Play apps in 2 countries returned 10 of 10 app-detail records and 500 of 500 reviews. Title, developer, price, rating, and rating count filled on every record; review text, stars, and date on every review. Dead ids came back as `not-found` and were not charged.
- **Fast and light.** No browser and no proxy. The Apple test run (30 app-country pairs, 50 reviews each) finished in 51 seconds.
- **Price per record, usage included.** There is no separate platform usage bill, and you can cap the total charge for any run.

### How to scrape App Store and Google Play reviews

1. Open the **Input** tab.
2. Add apps to **Apps**: an Apple id (`284882215`), an App Store URL, a Play package name (`com.spotify.music`), or a Play URL.
3. Set **Countries** (default `us`). Each app is fetched once per country.
4. Set **Max reviews per app per country** (default 100, up to 500), or turn **Include reviews** off for app details only.
5. Press **Start**. When the run finishes, open the **Output** tab or download the dataset as JSON, CSV, or Excel.

### App Store reviews API: call it from your code

No App Store Connect key and no Google Play Console access needed, and the app doesn't have to be yours. Call the actor over the Apify API and get the records back in the same request:

```bash
curl -X POST "https://api.apify.com/v2/acts/morgan-studio~app-store-reviews-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"appIds": ["284882215", "com.duolingo"], "countries": ["us"], "maxReviewsPerApp": 100}'
```

The response is the JSON array of app-detail and review records. The API tab above has ready-made snippets for JavaScript, Python, the CLI and MCP.

### Export Apple App Store reviews to CSV or JSON

Run with Apple ids or App Store URLs and download the dataset from the Output tab as CSV, Excel or JSON, or from `https://api.apify.com/v2/datasets/<datasetId>/items?format=csv`. The Reviews view gives one row per review: stars, title, text, author, app version and date.

### Google Play reviews scraper

Google Play apps go in the same **Apps** list, by package name (`com.spotify.music`) or Play URL. Each Play review carries the stars, text, author, app version, date, thumbs-up count and the developer's reply when there is one. Play and Apple apps can be mixed in one run.

### Input

- **Apps** (`appIds`): Apple ids, App Store URLs, Play package names, or Play URLs.
- **Countries** (`countries`): two-letter store codes, default `["us"]`.
- **Include app details** (`includeAppDetails`): default on.
- **Include reviews** (`includeReviews`): default on.
- **Max reviews per app per country** (`maxReviewsPerApp`): default 100, up to 500.
- **Review order** (`sortBy`): `mostRecent` (default) or `mostHelpful`.
- **Max concurrency** (`maxConcurrency`): apps worked on at once, default 4, up to 10.

Example input:

```json
{
  "appIds": ["284882215", "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580", "com.duolingo"],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 100
}
```

### How much does it cost to scrape app reviews?

You pay per record. There is no separate charge for Apify platform usage; it is included in the record price.

| Event | Price |
|---|---|
| App-detail record (`fetchStatus: "ok"`) | $0.003 |
| Review record (`fetchStatus: "ok"`) | $0.0001 ($0.10 per 1,000) |
| Actor start | $0.00005 per run |

Only records that came back with data are charged. Failed records (`not-found`, `invalid-input`, `error`) and status rows (`no-reviews`) are free. They are still written to the dataset so you can see what happened.

For example, 10 apps in one country with 100 reviews each is 10 app-detail records and 1,000 reviews: about $0.13. Reviews only (details off) for the same run: about $0.10.

You can cap a run's total charge in the run options (maximum cost per run). If the next app-detail record would pass the cap, details stop and reviews continue; when the next review would pass it, the run stops.

### Limits

- **Apple serves at most 500 reviews per app per country** (10 pages of 50) through its public feed. Asking for more returns 500. For more history, add more countries.
- Apple's most-recent feed is occasionally empty for an app that has reviews (seen for Instagram in Germany). The actor then uses the most-helpful feed and says so in each review's `sortBy`.
- **Google Play `version` is `null`.** Play's public app page no longer shows the app version. Review records still carry the version each review was written on.
- Google Play reviews come from the same call the Play website uses. Google can change it without notice; if it stops working, Play reviews come back as `error` records (free) while Play details and all Apple data keep working.
- Prices, ratings, and reviews are per country store, as a signed-out visitor sees them.

### How failures are reported

Every app and country produces at least one record. Each record has a `fetchStatus`:

- `ok`: data was read.
- `not-found`: the store has no app with this id in this country.
- `invalid-input`: the line is not an app id, package name, or store URL.
- `no-reviews`: the app exists but the store returned no reviews for it in this country.
- `error`: the store failed three times in a row, or the response could not be read.

The `error` field says what happened. The run log ends with a summary line: records, failures, requests, retries, elapsed time, and usage.

### FAQ

**How do I scrape App Store reviews?** Paste the app's id or App Store URL into **Apps**, pick the countries, and press Start. You get up to 500 reviews per app per country, newest first, plus the app's details.

**Is there an App Store reviews API I can use for any app?** Apple's App Store Connect API only covers your own apps. This actor reads Apple's public review feed for any app, and you call it like an API from your code.

**Can I export Google Play reviews?** Yes. Add the Play package name, run, and download the Reviews view as CSV, Excel or JSON.

**Can I get more than 500 Apple reviews for one app?** Not from one country. Apple's public feed stops at 10 pages of 50. Running the same app across several countries gives each country's 500.

**Does it need an API key or a login?** No. Apple's lookup API and review feed are public and key-free, and Google Play's pages are public.

**Can I call it from my code or an AI agent?** Yes. Like any Apify actor it runs through the Apify API: start a run with your input and read the dataset as JSON.

**How do I keep costs under control?** Set a maximum cost per run in the run options, and use `maxReviewsPerApp` to bound reviews.

**Is it legal to scrape app store reviews?** The actor reads only public data that a signed-out visitor can see. Whether your use is allowed depends on what you do with the data and where you are. If you are unsure, ask a lawyer.

### Ready-made examples

Each one opens with its input filled in; copy it to your account and run.

- [App Store and Google Play app details lookup](https://apify.com/morgan-studio/app-store-reviews-scraper/examples/app-store-and-google-play-app-details-lookup)
- [App Store and Google Play reviews to JSON](https://apify.com/morgan-studio/app-store-reviews-scraper/examples/app-store-and-google-play-reviews-to-json)
- [Export Apple App Store reviews to CSV](https://apify.com/morgan-studio/app-store-reviews-scraper/examples/export-apple-app-store-reviews-to-csv)
- [Google Play reviews by package name](https://apify.com/morgan-studio/app-store-reviews-scraper/examples/google-play-reviews-by-package-name)
- [Google Play reviews exporter: CSV and Excel](https://apify.com/morgan-studio/app-store-reviews-scraper/examples/google-play-reviews-exporter-csv-excel)

### More actors from the same developer

- [Amazon Product Scraper & Price API (ASIN, Keyword)](https://apify.com/morgan-studio/amazon-product-price-scraper)
- [YouTube Transcript API & Scraper with Timestamps](https://apify.com/morgan-studio/youtube-transcript-scraper)
- [Zillow Scraper API: Property, Search & Zestimate](https://apify.com/morgan-studio/zillow-property-scraper)

### Changelog

- **2026-10-15**: README and listing reworded for search; new sections on API use, scheduling and export; links to the ready-made examples. No change to the scraper or the prices.
- **0.1** (2026-10-12): First release. Apple App Store and Google Play app details and reviews, any country. Pay per record: app-detail $0.003, review $0.0001, failed records free.

# Actor input Schema

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

One app per line. Apple: the numeric app id (284882215) or an App Store URL (https://apps.apple.com/us/app/.../id284882215). Google Play: the package name (com.spotify.music) or a Play URL (https://play.google.com/store/apps/details?id=com.spotify.music). The store is detected from the format.

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

Two-letter store country codes (us, gb, de, jp, ...). Each app is fetched once per country: one app-detail record and its reviews from that country's store.

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

Write one app-detail record per app per country (title, developer, price, rating, rating count, version, dates, genres, description).

## `includeReviews` (type: `boolean`):

Write one review record per review (rating, title, text, author, app version, date).

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

Stop each app's reviews after this many, per country. Apple's public review feed serves at most 500 reviews per app per country (10 pages of 50), so 500 is the ceiling.

## `sortBy` (type: `string`):

Most recent first, or most helpful first. If Apple's most-recent feed comes back empty for an app that has reviews, the actor falls back to most helpful; each review record says which order it came from.

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

How many apps to work on at once. 4 is polite and fast enough for most runs.

## Actor input object example

```json
{
  "appIds": [
    "284882215",
    "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
  ],
  "countries": [
    "us",
    "gb"
  ],
  "includeAppDetails": true,
  "includeReviews": true,
  "maxReviewsPerApp": 100,
  "sortBy": "mostRecent",
  "maxConcurrency": 4
}
```

# Actor output Schema

## `apps` (type: `string`):

One record per app per country with rating, rating count, price, version, developer, and fetchStatus.

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

One record per review with stars, title, text, author, app version, and date.

## `allRecords` (type: `string`):

Every record in the dataset, all fields.

# 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 = {
    "appIds": [
        "284882215",
        "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("morgan-studio/app-store-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 = {
    "appIds": [
        "284882215",
        "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580",
    ],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("morgan-studio/app-store-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 '{
  "appIds": [
    "284882215",
    "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
  ],
  "countries": [
    "us"
  ]
}' |
apify call morgan-studio/app-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

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