# App Reviews Scraper — Google Play + App Store, Only New (`steadyfetch/app-reviews-scraper`) Actor

App reviews scraper for Google Play and the App Store in one run: paste app ids or store links and get one row per review in one shape — rating, title, text, date, version, helpful count, developer reply. Repeat runs deliver only the reviews you have not received. No login, no start fee.

- **URL**: https://apify.com/steadyfetch/app-reviews-scraper.md
- **Developed by:** [Steadyfetch Team](https://apify.com/steadyfetch) (community)
- **Categories:** Developer tools, Marketing, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.15 / 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.
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, Only New

**Paste app ids or store links from Google Play and the App Store — mixed in one list — and get one row per review in one shape for both stores: rating, title, text, date, app version, helpful count and the developer's reply. Schedule it, and each run delivers only the reviews you have not received yet. No login, no start fee — from $0.15 per 1,000 reviews.**

Product, support and ASO teams read app reviews to catch a broken release, answer unhappy users and see what people ask for. This actor reads both stores in one run and returns them in ONE table, so an Android app and its iPhone twin land side by side. It remembers, in a store in your own Apify account, which reviews it already gave you for each app and country — so a daily schedule hands you the new ones, not the same hundred again.

**Using an AI agent?** Pin this actor in Apify's MCP server with one link: `https://mcp.apify.com?tools=steadyfetch/app-reviews-scraper`

- **Actor id:** `steadyfetch/app-reviews-scraper`
- **Input:** `{ "apps": ["org.telegram.messenger", "https://apps.apple.com/us/app/id686449807"], "maxReviews": 100, "country": "US" }`
- **Cap the bill:** set `maxTotalChargeUsd` on the run (a run option, not Actor input), e.g. `1.00` — the run reads only what that can pay for.
- **Price:** from $0.00015 per review ($0.0002 on the Apify free plan); a review page that brings fewer new reviews than one $0.0035 review page check is worth is billed one check instead. Full table below.
- **How often it changes:** a popular app gets new reviews every hour, most apps a few a week. A daily schedule with "Only reviews I have not received" on catches everything; reviews appear in the store within about a day.

*Unofficial. Not affiliated with, endorsed by, or sponsored by Google or Apple.*

### What you get

One row per review, the same columns for both stores:

| Column | What it holds |
|---|---|
| `store` · `appId` · `appName` · `country` · `language` | which app, on which store (`google_play` or `app_store`), read in which country and language |
| `reviewId` · `rating` · `title` · `text` | the review itself; `rating` is 1–5 stars |
| `date` · `datePrecision` | when it was written; App Store reviews carry the day only (`datePrecision: "day"`) |
| `appVersion` | the app version the reviewer used, when the store shows it |
| `helpfulCount` | how many people found it helpful (Google Play) |
| `developerReply` · `developerReplyDate` | the developer's public answer and when it was posted (Google Play) |
| `reviewerName` · `appUrl` | the reviewer's display name (never a picture) and the app's store page |

What each store shows, so the empty columns are expected:

| | Google Play | App Store |
|---|---|---|
| Review title | — | yes |
| Time of day | yes | day only |
| Helpful count | yes | — |
| Developer reply | yes | — |
| Most reviews per app per country | thousands | 500 |

With **Add an app details row** on, each app also gets one details row (`rowType: "app"`): name, developer, rating, number of ratings, version, last update, release date, price, category, size and (Google Play) installs.

Every row also carries `charged`, `chargedEvents`, `status` and `statusReason`, so you can reconcile your bill from the dataset itself.

### How to use it

1. Put your apps in **Apps** — one per line, from either store: `org.telegram.messenger` or its `play.google.com/store/apps/details?id=…` link, `686449807` or its `apps.apple.com/…/id686449807` link.
2. Set **Max reviews per app** (newest first), the **Country** (`US`, `GB`, `DE` …) and the **Language** (`en`, `de`, `pt-BR` …).
3. Press Start — or schedule it daily. Keep **Only reviews I have not received** on for a schedule.

Optional: **Only reviews from this date on** (`YYYY-MM-DD`), **Order** (`newest` or `helpful`), **Add an app details row**.

Refused before anything is read, and never charged: an entry that is not an app id or store link, a country or language neither store lists (each app gets its own row naming the field), and a country one store does not sell in (only that store's apps are refused).

### Only the new reviews

With **Only reviews I have not received** on (the default), the actor keeps a small record per app, country and language in a store named `app-reviews-account` in **your** Apify account: the ids of the reviews it delivered to you, nothing else. On the next run it reads the newest page first and stops at the reviews you already have. A repeat run that finds nothing new delivers no review and is billed one review page check per app — never your whole limit. Turn it off to receive every review the run reads again.

### Pricing

Pay per result, all-inclusive (no platform usage on top), no start fee:

| Event | Apify Free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Review (one delivered review row) | $0.0002 | $0.00018 | $0.00016 | $0.00015 |
| Review page check | $0.0035 | $0.0035 | $0.0035 | $0.0035 |
| App details (one app details row, only when asked) | $0.0025 | $0.0025 | $0.0025 | $0.0025 |

**The review page check.** Reviews are read in pages — 150 on Google Play, 25 on the App Store — and each page is read whole. A page bills **either** its new reviews **or** one check, whichever is more, never both. A full App Store page of 25 new reviews at Gold is $0.00375 and pays no check. A page with fewer new reviews (a repeat run that finds 3 new ones, or none, or an app with a handful of reviews) is billed one $0.0035 check on its own row, and its reviews say `charged: false`.

Examples at Gold: 100 Google Play reviews = $0.015. 100 App Store reviews = $0.015. A daily repeat run of 5 apps that finds nothing new = 5 checks = $0.0175.

### Good to know

- **Exact limits.** The run stops at **Max reviews per app**, and sizes each read to what your maximum charge can pay before it buys it.
- **A time limit ends the collecting, never the delivering**: reviews already read are delivered, and the receipt says which limit stopped the run.
- **Free plan:** on the Apify free plan a run reads four review pages per 24 hours; the row says when it resets. Paid plans have no daily allowance.
- **Standby endpoint:** the newest reviews of up to 3 apps are available as one HTTP request (`GET /?apps=686449807&maxReviews=50`), up to 150 reviews per app, at the same prices. The endpoint keeps **no** account memory: every request reads the newest reviews. Use a run for "only new".
- **Honest rows:** an app the store does not have in your country ends on one `not_found` row; an app with fewer reviews than you asked for on one `no_data` row; a read that did not arrive in time on a `try_again` row, and a re-run fixes it. None is charged.
- The receipt is the last row (`run_summary`) and the run's `OUTPUT` record.

### Support

Questions, an app that returns something odd, or a column you need: open an issue on the Issues tab and it will be looked at.

If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.

# Changelog

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

# Actor input Schema

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

One app per entry, from either store: a Google Play package id like org.telegram.messenger or its play.google.com/store/apps/details?id=… link, or an App Store app id like 686449807 or its apps.apple.com/…/id686449807 link. Each store is detected for you. An entry that is not an app is refused before anything is read, and nothing is charged for it.

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

The most reviews to deliver per app on one run, newest first. The App Store shows at most 500 reviews per app per country, so an App Store app reads up to 500. On a repeat run with "Only reviews I have not received" on, this is the most NEW reviews per app.

## `onlyNew` (type: `boolean`):

On (the default): this actor remembers, in a store in YOUR Apify account, which reviews it already delivered to you for each app and country, so a scheduled run delivers and charges only the new ones. Off: every review the run reads is delivered again.

## `since` (type: `string`):

Optional. Deliver only reviews written on or after this day, written YYYY-MM-DD. App Store reviews carry the day only, not the time.

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

The store country to read reviews from, as a two-letter code (US, GB, DE …) or a name. App Store reviews belong to one country's store. Google Play sells in 211 countries, the App Store in 105; an app whose store does not cover the country gets its own row saying so.

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

The review language, as a code (en, de, pt-BR …) or a name. Google Play returns reviews written in this language.

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

newest (the default) reads the most recent reviews first, which is what a schedule needs. helpful reads the store's most helpful (Google Play: most relevant) reviews first.

## `appInfo` (type: `boolean`):

Also return one row per app with its store details: name, developer, rating, number of ratings, version, last update, price, category and (Google Play) installs. Charged as one App details event per app.

## `maxRunSeconds` (type: `integer`):

Optional. Stop collecting after this many seconds; reviews already read are still delivered.

## Actor input object example

```json
{
  "apps": [
    "org.telegram.messenger",
    "686449807"
  ],
  "maxReviews": 100,
  "onlyNew": true,
  "country": "US",
  "language": "en",
  "sortBy": "newest",
  "appInfo": false
}
```

# Actor output Schema

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

One row per review from Google Play or the App Store, in one shape: store, app id and name, country, language, review id, rating, title (App Store only), text, date (App Store reviews carry the day only), app version, helpful count and the developer's reply with its date (Google Play only), and the reviewer's display name. Every row carries `charged`, `chargedEvents` and `status`, so the invoice reconciles from the dataset itself. A review row is charged once, as a `review`. A review page that brings fewer new reviews than one review page check is worth (a repeat run that finds nothing new, an app with a handful of reviews) is billed one `check` on its own row instead, and its reviews say charged: false. With "Add an app details row" on, each app also gets one details row, charged as one `app`.

## `misses` (type: `string`):

One uncharged row for each reason an app returned less than you asked for: `no_data` (the store shows fewer reviews, or none), `not_found` (no app with this id in this country), `skipped_seen` (you already received the rest on an earlier run), `skipped_date_window` (the rest are older than your since date), `try_again` (the answer did not arrive in time; a re-run is the fix), `input_error` (an entry is not an app, or a country, language, order or date names nothing — the row names the field), `skipped_budget` / `skipped_deadline` (your maximum charge or the run clock stopped it first) and `skipped.free_plan_allowance` (Apify free plan only: the plan's daily allowance on this actor; the row names the reset time).

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

The run's receipt: reviews delivered, what was asked for, reviews you already had, review pages read, the charged events and what stopped the run. Uncharged.

# 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": [
        "org.telegram.messenger",
        "686449807"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyfetch/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 = { "apps": [
        "org.telegram.messenger",
        "686449807",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadyfetch/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 '{
  "apps": [
    "org.telegram.messenger",
    "686449807"
  ]
}' |
apify call steadyfetch/app-reviews-scraper --silent --output-dataset

```

## MCP server setup

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