# App Store Reviews & Google Play Reviews Scraper (`ahmed.fouaad82/app-store-reviews`) Actor

Scrape App Store reviews and Google Play reviews into one dataset: rating, review text, date, app version and developer reply. $0.15/1,000 results.

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

## Pricing

$0.15 / 1,000 review or app records

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

Scrape **Apple App Store and Google Play reviews** into one dataset for product managers, app developers and customer-feedback researchers. Get review text, ratings, dates, app versions, developer replies and optional app metadata without a login.

**First 25 saved results of every run are free; after that, $0.15 per 1,000 saved results.** One review or app-details row is one result; failed requests do not create result events. The Pricing tab is authoritative. Apify plan allowances and any applicable platform/storage charges are separate.

**Example output** (illustrative abbreviated record, not a captured result):

```json
{"recordType":"review","store":"google-play","appId":"com.example.app","rating":5,"text":"The latest update works well."}
```

### What does this Actor do?

Extract **Google Play and Apple App Store reviews in one run**, using one stable JSON schema. Collect ratings, review text, versions, public reviewer display names and Google Play developer replies. An optional app-details mode adds product metadata. It uses public [Google Play](https://play.google.com/store/apps) and [Apple App Store](https://apps.apple.com/) HTTP endpoints, without login, browser or paid proxy.

### Who is it for?

Product managers, customer-support teams, app developers and market researchers can compare feedback across Android and iOS, monitor releases and schedule incremental review collection through the Apify API. Export JSON, HTML, CSV or Excel; connect datasets to Google Sheets, Make, Zapier or your own sentiment-analysis workflow.

### How to scrape both app stores

1. Paste Android package IDs or Google Play URLs, and numeric Apple IDs or App Store URLs.
2. Choose countries and Google Play languages.
3. Set the per-locale review limit and global output limit. Click Start.
4. Inspect the dataset and SUMMARY diagnostic record. Partial storefront failures do not discard successful data.

See the Input tab for all options. Defaults are immediately usable with the prefilled WhatsApp examples.

```json
{
  "apps": ["com.whatsapp", "https://apps.apple.com/us/app/whatsapp-messenger/id310633997", "com.spotify.music"],
  "countries": ["us", "gb"],
  "languages": ["en"],
  "sort": "newest",
  "mode": "both",
  "maxReviews": 5,
  "maxResults": 36,
  "dateFrom": "2026-10-01"
}
```

### What data is extracted?

| Field | Type | Meaning |
|---|---|---|
| `recordType` | string | `review` or `app` |
| `store`, `appId` | string | Source store and validated app ID |
| `reviewId`, `date` | string | Source review ID and UTC publication/update date |
| `rating`, `title`, `text` | number/string | Rating, title if available, full review text |
| `appVersion` | string/null | Reviewed version; current version for app rows |
| `developerReply` | object/null | Google Play reply text and UTC date |
| `thumbsUpCount` | integer/null | Google Play helpful votes |
| `reviewerName` | string/null | Public display name only |
| `country`, `language` | string/null | Requested storefront and Google query language, not reviewer residence or detected language |
| `appDetails` | object/null | Title, description, developer, URL, version, rating, rating count, price, currency, genre, update date, installs and bundle/package ID |

Absent fields are null, never invented. Apple RSS exposes neither replies nor helpful-vote counts; Apple's language and requestedLanguage are null. Google review titles are generally null.

### Example output

Illustrative, anonymized review record:

```json
{
  "recordType": "review",
  "store": "google-play",
  "appId": "com.example.app",
  "reviewId": "example-review-123",
  "date": "2026-10-15T12:00:00.000Z",
  "rating": 5,
  "title": null,
  "text": "The latest update works well.",
  "appVersion": "1.2.0",
  "developerReply": {"text": "Thank you!", "date": "2026-10-16T12:00:00.000Z"},
  "thumbsUpCount": 2,
  "reviewerName": "Example Reviewer",
  "country": "us",
  "language": "en",
  "requestedLanguage": "en",
  "sort": "newest",
  "appDetails": null
}
```

### Incremental monitoring and coverage

Use `sort: newest` and an inclusive ISO `dateFrom`, e.g. `2026-10-01T00:00:00Z`. Schedule the Actor and advance your own watermark, leaving a small overlap; upsert externally on store + appId + country + language + reviewId. Each new run starts afresh; a checkpoint only resumes the same run. Review edits can change dates. Sort/helpfulness is source-defined and can change while paging.

`maxReviews` applies per app/country/Google-language combination; `maxResults` caps all dataset records, including app details. Apple is queried once per country even if multiple languages were supplied. Apple public RSS is capped at ten pages, approximately 500 recent reviews per app/storefront. This is **not a full historical archive**. A date filter cannot recover reviews outside that window. Google uses continuation tokens; `maxPages` bounds work. Duplicate IDs are suppressed within the same locale, not across countries because storefront provenance matters. Page-cap warnings are shown in the log.

### How much does it cost?

**First 25 saved results of every run are free; after that, $0.15 per 1,000 results.** One result = one review or one app-details record saved to your dataset. Failed requests are not charged. The exact current price is always shown in the Pricing tab.

After the first 25 saved results, the code invokes `Actor.charge` once per stored item and checks the SDK budget before further requests/output. No paid proxies are used. Startup and request overhead make tiny runs more expensive per item than larger runs. No billing is attached to failed queries. The platform's own run charges still depend on your plan.

### Reliability and FAQ

#### Does it work for every country and language?

Google Play accepts requested country/language filters but does not certify reviewer location. Apple exposes storefront-specific feeds without a language filter. Unavailable apps can return no reviews. Review availability, order and count are controlled by the stores.

#### What happens on errors or rate limits?

Requests have timeouts, two retries and increasing backoff, with sequential requests and a default 750 ms delay. Increase the delay if rate-limited. SUMMARY lists failures and counts. A completely failed run is marked failed; mixed successes finish with diagnostics. Abort/migration checkpoints preserve progress. Storage writes and billing are not transactional: a sudden process death between them may leave a stored item uncharged.

#### Can I get private user information?

No login, private data, profile URL, avatar or reviewer user ID is collected. Only public review display names are returned. Text may nevertheless contain personal information shared by reviewers; apply lawful purpose, access controls and retention policies. Respect Google/Apple terms, applicable privacy law and rate limits. This Actor is not affiliated with either company and does not bypass access controls. Use the Issues tab for reproducible bug reports and the API tab for integration examples.

# Actor input Schema

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

Google Play URLs/package IDs and Apple App Store URLs/numeric IDs. No login required.

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

Two-letter storefront countries; these are not reviewer locations.

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

Google Play language filters. Apple ignores this field: its feed cannot filter by language.

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

Newest supports early termination for date monitoring. Helpfulness sorts by helpful votes where available.

## `mode` (type: `string`):

Reviews, app details only, or both. App details are separate dataset items.

## `maxReviews` (type: `integer`):

Successful review items for each locale. Apple is fetched once per country.

## `maxResults` (type: `integer`):

Global item cap, including app-details rows. First 25 results of every run are free.

## `maxPages` (type: `integer`):

Safety request cap; Google pages contain up to 150 reviews. Apple has at most 10 pages (about 500 reviews).

## `dateFrom` (type: `string`):

ISO date/time, e.g. 2026-10-01 or 2026-10-01T00:00:00Z. Omit for all available dates.

## `requestDelayMs` (type: `integer`):

Delay before every request and additional backoff on retries. No paid proxy.

## Actor input object example

```json
{
  "apps": [
    "com.whatsapp",
    "310633997"
  ],
  "countries": [
    "us"
  ],
  "languages": [
    "en"
  ],
  "sort": "newest",
  "mode": "reviews",
  "maxReviews": 5,
  "maxResults": 10,
  "maxPages": 10,
  "dateFrom": "",
  "requestDelayMs": 750
}
```

# Actor output Schema

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

Unified review and app records.

## `summary` (type: `string`):

Counts, limits and query failures.

# 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": [
        "com.whatsapp",
        "310633997"
    ],
    "maxReviews": 5,
    "maxResults": 10,
    "dateFrom": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed.fouaad82/app-store-reviews").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": [
        "com.whatsapp",
        "310633997",
    ],
    "maxReviews": 5,
    "maxResults": 10,
    "dateFrom": "",
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed.fouaad82/app-store-reviews").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": [
    "com.whatsapp",
    "310633997"
  ],
  "maxReviews": 5,
  "maxResults": 10,
  "dateFrom": ""
}' |
apify call ahmed.fouaad82/app-store-reviews --silent --output-dataset

```

## MCP server setup

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

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/useLSYSW5q8iVXd2A/builds/wbQm66i7hy1dwIkeO/openapi.json
