# Google Play Listing Change Monitor (`technicaldost/google-play-listing-change-monitor`) Actor

Compare public Google Play app listings across locales and track metadata changes for ASO workflows. No reviews or contacts.

- **URL**: https://apify.com/technicaldost/google-play-listing-change-monitor.md
- **Developed by:** [Technical Dost Solutions](https://apify.com/technicaldost) (community)
- **Categories:** Developer tools, Marketing
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 app listing delivereds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Google Play Listing Change Monitor

Compare a bounded watchlist of public Google Play app-detail pages across countries/languages and track metadata changes for ASO teams. Not a reviews scraper or contact finder. No sign-in, cookies, keys, searches, or private/internal endpoints.

### Pricing

Pay-per-event price: **$0.0005 per useful delivered app-locale row ($0.50/1,000)**. No start charge. Errors and the key-value-store SUMMARY are not billed. Duplicate inputs are removed. With `changesOnly`, unchanged listings are not emitted or billed; the initial baseline rows are billable. Apify compute, data transfer and storage usage are billed separately under your plan.

### Quick start

Default input is two apps (WhatsApp and Telegram), GB/en-GB, maximum two delivered rows. See `INPUT.example.json`. Choose known package IDs rather than app names. Set `stateStoreName` to a unique named key-value store to compare across future runs. Without it, the baseline is run-local. Scheduling is external (for example an Apify schedule); this Actor does not schedule itself.

`appIds`: 1–100 package IDs. `locales`: 1–10 country/language pairs. Allowlisted countries: US GB IN CA AU DE FR ES IT BR JP KR MX NL. Languages: en en-US en-GB de fr es it pt-BR ja ko nl hi. At most 200 distinct app-locale combinations. `maxResults`: 1–200 useful rows (default 2). `changesOnly`: boolean (default false). `stateStoreName`: blank or 3–63 alphanumeric/hyphen characters, beginning alphanumeric. Unknown inputs fail validation. Locale requests are hints to the source, not a guarantee of geographical availability; no country proxies are used.

### Output

Each delivered row contains appId, requested country/language, sourceUrl, observedAt (UTC), title, descriptionHash, descriptionLength, categories, price, currency, rating, ratingCount, reviewCount, installBucket, updated, version, sourceEvidence, missingFields, fingerprint, changeType, changes and localeComparison. `changes` contains field/before/after triples. `changeType` is initial, changed or unchanged. `localeComparison` names the first fetched locale for that app and known-field differences against it. Timestamp/rating observations can differ slightly between requests.

Most fields come from public JSON-LD SoftwareApplication. No full app descriptions are exported or persisted. A visible description element, or otherwise the source's short JSON-LD description, is transiently parsed, whitespace-normalized and hashed with SHA-256. descriptionHash is the hexadecimal digest; descriptionLength is the normalized Unicode code-point count. Changes report only old/new hashes and lengths, never description text. A hash change indicates text changed but does not explain the wording; source extraction changes can also change the hash. sourceEvidence.descriptionSource identifies the extraction source. Rating count is not the number of written reviews. reviewCount and version remain null unless explicitly supplied. Only English visible labels currently yield installBucket and updated; other languages yield null for these fields. Updated date remains a source string, not a guessed normalized timestamp. No exact downloads, revenue, developer contacts, reviewer profiles or reviews are collected. Missing fields are null, with evidence and missingFields; null is never removal evidence.

SUMMARY in the default key-value store contains requested/fetched/delivered counts, unbilled errors, whether baselineCommitted, baselineScope and caveats. Only useful listing rows appear in the dataset.

### Persistence and limits

Baseline schema version 2 excludes description text; older schema baselines fail closed. Use a fresh baseline store when upgrading from a pre-release full-description build. Baselines are scoped deterministically to the sorted watchlist and locales. Snapshot promotion is all-or-nothing: any fetch failure, budget exhaustion, failed delivery or output truncation prevents baseline updates. Absent apps are never marked removed; missing fields retain the prior known field for future comparisons. A newly available previously-null field is baseline enrichment, not a change alert. An initial valid row is emitted even with changesOnly. Missing fields may change without an alert.

Do not overlap runs using the same baseline store: this package does not implement cross-run locking. Changing the watchlist creates a fresh scope. A successful first run followed by the same watchlist with changesOnly establishes normal change monitoring. Set maxResults high enough for your watchlist; clipping intentionally prevents promotion. All combinations (maximum 200) may be fetched before output clipping to support locale comparison. HTTP requests are sequential with a short delay, 25-second timeout, no retries, no redirects, and a 4MB page cap. robots.txt is checked at startup; unavailable/disallowed rules stop the run. Challenge/denied pages are not bypassed.

### Source and rights caveats

Checked public robots.txt and Google Play / Google terms on 2026-11-07 UTC. /store/apps/details was not disallowed; /store/search, /store/getreviews, internal and account paths are excluded. Google's general terms prohibit automated access contrary to machine-readable instructions. Play terms reserve content rights and restrict redistribution of Content. This review is **not legal clearance** for metadata reuse or commercial redistribution. Use only where permitted and respect publisher/content rights. No official Google affiliation.

Sources: https://play.google.com/robots.txt ; https://play.google.com/about/play-terms/ ; https://policies.google.com/terms?hl=en . A non-English locale can return fallback/localized content and missing fields. Source layout and structured data can change.

### Reliability

If every source fails, SUMMARY is saved and the run fails rather than reporting an empty success. A valid unchanged watchlist with changesOnly succeeds with zero delivered rows. Baseline storage failures fail the run and are recorded in SUMMARY when possible; a later SUMMARY storage failure also fails the run, but cannot roll back an already committed baseline.

This narrowed release retains factual metadata and description hashes/lengths only. It does not resolve all third-party rights questions and is not legal clearance.

# Actor input Schema

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

1–100 known package IDs, maximum 200 app-locale combinations.

## `locales` (type: `array`):

1–10 objects. Countries: US, GB, IN, CA, AU, DE, FR, ES, IT, BR, JP, KR, MX, NL. Languages: en, en-US, en-GB, de, fr, es, it, pt-BR, ja, ko, nl, hi.

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

Output cap; all bounded locales may be fetched. Truncation prevents baseline updates.

## `changesOnly` (type: `boolean`):

Unchanged rows omitted and unbilled. Initial observations emitted.

## `stateStoreName` (type: `string`):

Optional 3–63 character named store. Blank is run-local. Do not overlap runs using this store.

## Actor input object example

```json
{
  "appIds": [
    "com.whatsapp",
    "org.telegram.messenger"
  ],
  "locales": [
    {
      "country": "GB",
      "language": "en-GB"
    }
  ],
  "maxResults": 2,
  "changesOnly": false,
  "stateStoreName": ""
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

## `summary` (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 = {
    "appIds": [
        "com.whatsapp",
        "org.telegram.messenger"
    ],
    "locales": [
        {
            "country": "GB",
            "language": "en-GB"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("technicaldost/google-play-listing-change-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 = {
    "appIds": [
        "com.whatsapp",
        "org.telegram.messenger",
    ],
    "locales": [{
            "country": "GB",
            "language": "en-GB",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("technicaldost/google-play-listing-change-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 '{
  "appIds": [
    "com.whatsapp",
    "org.telegram.messenger"
  ],
  "locales": [
    {
      "country": "GB",
      "language": "en-GB"
    }
  ]
}' |
apify call technicaldost/google-play-listing-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,technicaldost/google-play-listing-change-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/zSFesItk22fDJWGhf/builds/4iilAIbOOe6VEyxqc/openapi.json
