# App Store & Google Play Reviews Scraper API | One Schema (`timber_timber/app-review-monitor`) Actor

Scrape Apple App Store and Google Play reviews in one run — both stores return the exact same fields, so there is nothing to merge. Any country and language, incremental with sinceDays for daily monitoring, and you pay only for the reviews actually returned.

- **URL**: https://apify.com/timber\_timber/app-review-monitor.md
- **Developed by:** [timber timber](https://apify.com/timber_timber) (community)
- **Categories:** Developer tools, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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?

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 API — one run, one schema

Scrape customer reviews for any mobile app from **both the Apple App Store and Google Play** with a single Actor. Every review comes back with the **same field set** whatever the store, so results drop straight into your dashboard, spreadsheet, or LLM prompt — nothing to merge, nothing to re-parse.

### Why this Actor

- **Two stores, one schema.** Most review scrapers cover a single store. Here you get App Store and Google Play reviews in the same run, with identical field names. Store-specific fields (like Google Play's developer reply) are simply `null` where a store doesn't have them.
- **Monitoring-friendly.** Set `sinceDays: 1` and schedule the Actor daily: each run keeps only the reviews from the last 24 hours, and you pay only for those. The window moves with every run — no input editing needed.
- **Any storefront.** Works for the US, Japan, Germany, or any other country, including non-Latin languages (Japanese, Korean, ...).
- **No silent gaps.** Apple's public feed intermittently answers a *successful* request with an empty page — measured here at 12 out of 100 requests, spread randomly across apps and pages. A scraper that trusts that empty page stops paging early and quietly returns **zero reviews for that app**, with no error to warn you. This Actor detects the empty response, re-requests it with a fresh cache key (verified: 12/12 recovered, while simply waiting recovered 0/12), and logs every target that still ends up with no reviews.
- **Paste URLs or IDs.** `https://apps.apple.com/jp/app/line/id443904275` and `443904275` both work; same for Google Play package names and URLs.

### Input example

```json
{
    "appStoreApps": ["https://apps.apple.com/jp/app/line/id443904275"],
    "googlePlayApps": ["jp.naver.line.android"],
    "country": "jp",
    "language": "ja",
    "maxReviewsPerApp": 200,
    "sinceDays": 7
}
```

### Output example

One dataset item per review. **Both stores emit exactly these fields:**

```json
{
    "store": "googleplay",
    "appId": "com.example.app",
    "country": "jp",
    "lang": "ja",
    "reviewId": "aa0000bb-1111-2222-3333-ccc444ddd555",
    "userName": "T. S.",
    "rating": 2,
    "title": null,
    "text": "アップデートで使いにくくなりました",
    "appVersion": "26.11.0",
    "date": "2026-08-14T22:09:32Z",
    "thumbsUp": 5,
    "replyText": null
}
```

Field notes:

- `title` is always `null` for Google Play (its reviews have no title).
- `thumbsUp`, `replyText` (developer reply), and `lang` are always `null` for App Store — those concepts exist only on Google Play.
- `date` is ISO 8601. App Store dates carry the store's timezone offset; Google Play dates are UTC.

### Typical uses

- **Daily review monitoring** for your own app: schedule with `sinceDays: 1` and pipe new reviews to Slack, a spreadsheet, or an LLM for summarization.
- **Competitor watching**: track ratings and complaints for competing apps across both stores.
- **ASO / product research**: pull recent reviews of any category's top apps and mine them for feature requests and pain points.
- **AI agents**: this Actor can be called from the Apify MCP server, so your agent can look up "what do users complain about in app X" on demand.

### Limits

- **App Store**: the public RSS feed serves roughly the latest 500 reviews per storefront (10 pages × 50). That is plenty for monitoring new reviews, but this Actor is not a tool for bulk-downloading a full multi-year review history.
- **Google Play**: reviews are fetched newest-first with pagination; `maxReviewsPerApp` caps the depth.
- Rarely, a review has no parseable date. With `sinceDays`/`sinceDate` set, such reviews are kept (and charged) rather than silently dropped.

Note: store pages display counts of *ratings*, which include ratings without review text — so your review count will be lower than the store's headline number. That is normal.

### Pricing

You are charged per review delivered to the dataset (the `app-review` event) plus a small Actor-start fee — see the Pricing tab for the current rates. Compute time is not passed on to you.

At the rates set today that is **$1.00 per 1,000 reviews** ($0.001 each) plus $0.00005 per run, so a daily monitoring run on an app that received 20 new reviews costs about **$0.02**. Runs that return nothing are not charged for reviews.

### FAQ

**Which apps can I fetch?** Any app publicly listed in the App Store or Google Play. No login, no cookies, no API key.

**Can I fetch multiple apps in one run?** Yes — pass any mix of App Store and Google Play apps.

**Can I fetch multiple countries in one run?** Partly. `country` applies to the whole run, but an App Store URL containing a country code (e.g. `apps.apple.com/de/...`) overrides it for that app. Google Play apps always use the run's `country`, so run once per country there.

**What does `language` do?** It sets the review language for Google Play only. App Store reviews follow the storefront country automatically.

**What happens if one app fails?** The failure is logged and the run continues with the remaining apps, so one bad ID never costs you the whole run.

**Where do the reviews come from?** App Store reviews come from Apple's public RSS feed; Google Play reviews come from the same unauthenticated endpoint the Play website itself uses (unofficial, so Google-side changes can require an Actor update — monitored and maintained).

# Actor input Schema

## `appStoreApps` (type: `array`):

Apple App Store apps to fetch. Accepts numeric app IDs (e.g. 443904275) or full store URLs (e.g. https://apps.apple.com/jp/app/line/id443904275).

## `googlePlayApps` (type: `array`):

Google Play apps to fetch. Accepts package names (e.g. jp.naver.line.android) or full store URLs (e.g. https://play.google.com/store/apps/details?id=jp.naver.line.android).

## `country` (type: `string`):

Two-letter country code of the store front (jp, us, gb, de, ...). Applies to both stores.

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

Two-letter language code for Google Play reviews (ja, en, de, ...). App Store reviews follow the country automatically.

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

Upper limit of reviews fetched per app per store. App Store RSS serves at most ~500 recent reviews (10 pages x 50).

## `sinceDays` (type: `integer`):

Optional. Keep only reviews newer than N days ago — e.g. 1 for a daily scheduled run, 7 for weekly. Recommended for monitoring: the window moves with each run, so you only pay for recent reviews. Takes priority over sinceDate.

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

Optional. Keep only reviews newer than a fixed date, e.g. 2026-08-15. For scheduled monitoring prefer sinceDays: a fixed date makes each later run fetch (and charge for) a growing range.

## Actor input object example

```json
{
  "appStoreApps": [
    "443904275"
  ],
  "googlePlayApps": [
    "jp.naver.line.android"
  ],
  "country": "us",
  "language": "en",
  "maxReviewsPerApp": 100
}
```

# Actor output Schema

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

Every review fetched in this run, one item per review.

# 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 = {
    "appStoreApps": [
        "443904275"
    ],
    "googlePlayApps": [
        "jp.naver.line.android"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("timber_timber/app-review-monitor").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 = {
    "appStoreApps": ["443904275"],
    "googlePlayApps": ["jp.naver.line.android"],
}

# Run the Actor and wait for it to finish
run = client.actor("timber_timber/app-review-monitor").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 '{
  "appStoreApps": [
    "443904275"
  ],
  "googlePlayApps": [
    "jp.naver.line.android"
  ]
}' |
apify call timber_timber/app-review-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,timber_timber/app-review-monitor"
        }
    }
}

```

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/NYwX2URHeqQeO8sc6/builds/9Kq0OfwagVSISoEiJ/openapi.json
