# App Store & Google Play Scraper & Monitor (`automa-flow/app-store-google-play-monitor`) Actor

Scrape App Store and Google Play app metadata, ratings, prices, releases, reviews, and developer replies in one normalized dataset. Monitor up to 500 iOS and Android apps for exact changes and new reviews—no API key, login, or browser required.

- **URL**: https://apify.com/automa-flow/app-store-google-play-monitor.md
- **Developed by:** [Vadim Bezrukov](https://apify.com/automa-flow) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 successful app checks

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 Scraper & Monitor

Scrape App Store and Google Play app metadata and reviews into one normalized
Dataset, then monitor iOS and Android apps for new releases, version changes,
prices, ratings, new reviews, and developer replies.

Paste up to 500 numeric App Store IDs, Google Play package IDs, or full store
URLs. Use `snapshot` mode for a current app-data or review export, or `monitor`
mode for a reusable baseline and exact changes. No API key, login, or browser is
required, and direct HTTP normally works without a proxy.

### What data can this App Store and Google Play scraper extract?

- one normalized app record for every input, including explicit `SUCCESS`,
  `PARTIAL`, `NOT_FOUND`, `RATE_LIMITED`, `FAILED`, `INVALID_INPUT` or
  `SKIPPED_BILLING_LIMIT` status;
- first successful monitor run as `BASELINE`, then exact changed fields;
- `NEW_RELEASE`, `VERSION_CHANGED`, price/free/paid, rating and metadata changes;
- deterministic rating/count deltas and semantic fingerprints;
- only newly observed reviews on later runs, with a first-class 1–2 star feed;
- developer-reply-added events where the public source exposes replies;
- a compact last-successful state per store/app/country/language in Apify KVS.

A failed or partial check never overwrites good state. A source error can never
masquerade as zero reviews, a rating drop or an app removal.

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

1. Add one or more App Store IDs, Google Play package IDs, or full listing URLs
   to `apps`.
2. Choose `snapshot` for a current export or `monitor` for baseline-and-change
   tracking.
3. Turn reviews on or off, set the maximum review window, and optionally select
   star ratings.
4. Run the Actor and open the Dataset in Apify, or retrieve the rows through the
   API in JSON, CSV, Excel, XML, or another supported format.

Use structured objects when you need country, language or your own IDs:

```json
{
  "apps": [
    {
      "store": "google_play",
      "id": "com.spotify.music",
      "country": "US",
      "language": "en",
      "externalId": "spotify-android",
      "groupId": "spotify"
    },
    {
      "store": "app_store",
      "id": "324684580",
      "country": "US",
      "externalId": "spotify-ios",
      "groupId": "spotify"
    }
  ],
  "mode": "monitor",
  "outputMode": "changesOnly"
}
```

Full store URLs also work in the same `id` field:

```json
{
  "apps": [
    {
      "store": "app_store",
      "id": "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"
    },
    {
      "store": "google_play",
      "id": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en&gl=US"
    }
  ],
  "mode": "snapshot",
  "outputMode": "all"
}
```

`groupId` is an explicit join key supplied by you. The Actor never guesses that
an iOS and Android listing are the same product.

Saved Apify Tasks automatically isolate monitoring state by Task ID. For direct
API runs, set a stable `monitorId` when you need multiple independent baselines
for the same app/storefront.

### App Store and Google Play scraper output

Every input produces an app status row. Review collection adds one row per
matching review or developer-reply event. Records use stable source IDs,
timestamps, semantic fingerprints, and explicit status/change types:

```json
[
  {
    "record_type": "app",
    "store": "google_play",
    "app_id": "com.example.music",
    "status": "SUCCESS",
    "change_type": "NEW_RELEASE",
    "previous_version": "1.9.0",
    "current_version": "2.0.0",
    "rating": 4.6,
    "scraped_at": "2026-09-01T10:00:00Z"
  },
  {
    "record_type": "review",
    "store": "google_play",
    "app_id": "com.example.music",
    "review_id": "review-example-001",
    "rating": 1,
    "text": "Playback stops after the latest update.",
    "change_type": "NEW_NEGATIVE_REVIEW"
  }
]
```

The `apps` Dataset view selects app-status columns and `reviewEvents` selects
review columns. Views select columns but do not filter row types; API consumers
should filter `record_type` when they need only apps or only reviews.

### App Store and Google Play scraper workflows

#### Export app metadata for ASO and market research

Set `mode` to `snapshot`, `outputMode` to `all`, and `includeReviews` to `false`.
This returns current releases, versions, prices, ratings, counts, categories,
descriptions, screenshots, and explicit per-app status without creating state.

#### Export App Store and Google Play reviews

Set `mode` to `snapshot`, `outputMode` to `all`, and `includeReviews` to `true`.
Choose `maxReviewsPerApp` and `reviewRatings` to export current review text,
public author display names, app versions, helpful votes, and Google Play
developer replies. The resulting Dataset is ready for CSV, Excel, JSON, or API
use.

#### Competitor watchlist and new releases

Keep the defaults (`monitor` + `changesOnly`) and schedule the same input daily.
The first run establishes a baseline. A later version/timestamp change produces
`NEW_RELEASE` with `previous_version`, `current_version`, release notes and
`detected_at`.

#### New 1–2 star reviews

```json
{
  "apps": [
    {"store": "google_play", "id": "com.spotify.music", "country": "US"},
    {"store": "app_store", "id": "324684580", "country": "US"}
  ],
  "mode": "monitor",
  "outputMode": "changesOnly",
  "includeReviews": true,
  "maxReviewsPerApp": 100,
  "reviewRatings": [1, 2]
}
```

The baseline stores existing IDs without alerting them. Later unseen 1–2 star
IDs are `NEW_NEGATIVE_REVIEW` and are ready for a webhook payload.

Changing `maxReviewsPerApp` starts a fresh review-window baseline for each app.
This deliberately prevents older reviews exposed by a wider window from being
misreported as newly posted; app metadata monitoring continues from its existing
baseline.

### Automate app monitoring with schedules and webhooks

Create one Apify Task with the watchlist input and attach a daily schedule in the
Apify Console. Keep the same Task/KVS between runs; starting each run under a new
storage scope creates a new baseline.

A practical daily schedule is `0 6 * * *` (06:00 UTC). Through the API, create
an Apify schedule whose action runs the saved Task; do not run this monitor from
a local cron job that stops when your machine is offline.

For alerts, add a Dataset-item webhook to the Task run and route records where:

```text
record_type == "app" AND change_type NOT IN ("BASELINE", "UNCHANGED")
OR
record_type == "review" AND change_type IN
  ("NEW_REVIEW", "NEW_NEGATIVE_REVIEW", "DEVELOPER_REPLY_ADDED")
```

The supplied Dataset views select useful columns but do not filter rows. API and
webhook consumers should always apply the `record_type` and `change_type`
conditions above themselves.

### Use with AI agents through Apify MCP

Expose the Actor as a typed tool in an MCP-compatible client with Apify's hosted
MCP server:

```text
https://mcp.apify.com?tools=automa-flow/app-store-google-play-monitor
```

Example prompt:

```text
Run automa-flow/app-store-google-play-monitor in snapshot mode for these App
Store IDs and Google Play package IDs. Return app metadata and up to 100 recent
reviews per app, group 1–2 star reviews by recurring complaint, and preserve
each record's source_url in the answer.
```

For recurring agent workflows, use `mode: monitor` with a stable `monitorId`
and act only on explicit change types. `FAILED` and `PARTIAL` rows mean the
source was not fully verified; they never mean that nothing changed.

### How much does it cost to scrape App Store and Google Play?

The Actor uses pay per event:

- **$0.002 app check** for each distinct app/storefront that returns `SUCCESS`,
  including a quiet monitor check where nothing changed;
- **$0.002 app change** for a deterministic non-baseline app change delivered
  to the Dataset;
- **$0.0005 review result** for each baseline or newly observed review, or newly
  added developer reply, delivered to the Dataset.

Invalid, failed, partial, rate-limited and billing-skipped checks are not charged.
Retries, duplicate app aliases and unchanged reviews are never charged. Set an
Apify run spending limit when processing a new large watchlist.

### App Store and Google Play scraper limits

- Apple public reviews are capped at 10 pages × 50 reviews per app/country.
- Apple developer replies are not in the public feed and remain `null`.
- Google Play is an undocumented public web protocol, so schema health checks
  deliberately fail closed when Google changes it.
- Country changes availability, price, rating and counts. Monitor each country as
  a separate watchlist entry.
- Direct HTTP is the default; expected proxy cost is $0 and browser time is zero.
- Metadata is one request/app. At 100 reviews, Apple normally needs two additional
  requests and Google one additional request.

Public store data can still be subject to platform terms, copyright and privacy
rules. You are responsible for your use and redistribution. The Actor keeps only
compact monitoring state and does not retain raw source payloads.

Review rows include the public review text and the author's public display name.
The Actor does not enrich or contact reviewers. Compact KVS monitoring state
keeps review IDs and developer-reply fingerprints, not author names or review
text; Dataset retention is controlled by your Apify storage settings.

### FAQ

#### Do I need an App Store, Google Play, or developer API key?

No. The Actor reads public App Store and Google Play listing/review data without
a login or developer account. Apple metadata uses its public Lookup API; Google
Play data comes from public web responses and an undocumented public review
protocol.

#### Can I export App Store and Google Play reviews to CSV or Excel?

Yes. Run a review snapshot, open the Apify Dataset, and export it as CSV, Excel,
JSON, XML, or another supported format. You can also retrieve the same rows via
the Apify API.

#### Can I monitor competitor app releases and ratings?

Yes. Keep the same saved Task in `monitor` mode. The first successful run creates
a baseline; later successful runs return exact release, version, price, rating,
count, metadata, review, and developer-reply changes.

#### Does an empty review result mean the source failed?

No. A successful empty review window is different from a source failure. Failed,
partial, unavailable, rate-limited, and invalid inputs receive explicit status
rows and never overwrite the last successful monitoring state.

# Actor input Schema

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

One to 500 App Store or Google Play listings. Paste a numeric App Store ID, dotted Google Play package ID, or full store URL into each item's ID field. Country and Google Play language define a separate storefront baseline.

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

monitor compares with the last successful state. snapshot reads current public data without reading or writing state.

## `outputMode` (type: `string`):

changesOnly emits one app status row per input plus only new review/reply events. all also returns current matching reviews.

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

Fetch recent reviews and monitor stable review IDs. Turn off for the lowest-cost release/rating monitor.

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

Maximum recent reviews read per app (0–500). Apple exposes at most 500 per country through its public feed.

## `reviewRatings` (type: `array`):

Only reviews with these star ratings are emitted. Use \[1, 2] for the negative-review feed. All fetched IDs still participate in deduplication.

## `monitorId` (type: `string`):

Optional namespace for independent baselines when running directly through the API. Saved Apify Tasks are isolated automatically by Task ID.

## `proxyConfiguration` (type: `object`):

Optional. Direct HTTP is the verified default and expected proxy cost is $0. Do not use proxy rotation to circumvent store rate limits.

## Actor input object example

```json
{
  "apps": [
    {
      "store": "google_play",
      "id": "com.spotify.music",
      "country": "US",
      "language": "en",
      "externalId": "spotify-android",
      "groupId": "spotify"
    },
    {
      "store": "app_store",
      "id": "324684580",
      "country": "US",
      "externalId": "spotify-ios",
      "groupId": "spotify"
    }
  ],
  "mode": "monitor",
  "outputMode": "changesOnly",
  "includeReviews": true,
  "maxReviewsPerApp": 100,
  "reviewRatings": [
    1,
    2,
    3,
    4,
    5
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

## `reviewEvents` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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": [
        {
            "store": "google_play",
            "id": "com.spotify.music",
            "country": "US",
            "language": "en",
            "externalId": "spotify-android",
            "groupId": "spotify"
        },
        {
            "store": "app_store",
            "id": "324684580",
            "country": "US",
            "externalId": "spotify-ios",
            "groupId": "spotify"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automa-flow/app-store-google-play-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 = {
    "apps": [
        {
            "store": "google_play",
            "id": "com.spotify.music",
            "country": "US",
            "language": "en",
            "externalId": "spotify-android",
            "groupId": "spotify",
        },
        {
            "store": "app_store",
            "id": "324684580",
            "country": "US",
            "externalId": "spotify-ios",
            "groupId": "spotify",
        },
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("automa-flow/app-store-google-play-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 '{
  "apps": [
    {
      "store": "google_play",
      "id": "com.spotify.music",
      "country": "US",
      "language": "en",
      "externalId": "spotify-android",
      "groupId": "spotify"
    },
    {
      "store": "app_store",
      "id": "324684580",
      "country": "US",
      "externalId": "spotify-ios",
      "groupId": "spotify"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call automa-flow/app-store-google-play-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automa-flow/app-store-google-play-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/uJYBfkQ4FqzydpoDj/builds/CsoTEhG9DkK5ulqWU/openapi.json
