App & Extension Review Intelligence
Pricing
from $0.50 / 1,000 review data records
App & Extension Review Intelligence
Monitor public reviews from Google Play, Apple App Store, and Chrome Web Store. Extract normalized review records, detect new reviews, classify sentiment/topics, create app summaries, and send webhook alerts.
Pricing
from $0.50 / 1,000 review data records
Rating
0.0
(0)
Developer
Вадим Захаров
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Store V1 production-ready public review monitor for Google Play reviews, Apple App Store reviews, and Chrome Web Store reviews.
This unofficial Actor is a Google Play reviews scraper, Apple App Store reviews scraper, and Chrome Web Store reviews scraper for app reputation monitoring, competitor review analysis, product feedback, extension review monitor workflows, and negative review alerts.
Use it as an app review monitor when you need one normalized workflow across public mobile app and browser extension review sources.
What this Actor does
App & Extension Review Intelligence collects publicly visible app and extension reviews, normalizes them into one dataset schema, detects new reviews with stateful deduplication, creates app_summary records, classifies rule-based sentiment and topic classification locally, writes a user-facing OUTPUT summary to the Key-Value Store, and can send webhook alerts with new negative reviews.
Use cases:
- App reputation monitoring across stores, countries, and languages.
- Competitor review analysis for public app feedback.
- Product feedback mining from complaint themes such as
bug_crash,login,performance,billing, andfeature_request. - Support automation through negative review alerts to Slack, Make, Zapier, CRM, or helpdesk workflows.
- Scheduled onlyNewSinceLastRun monitors that output only reviews not already seen for the same
stateKey.
Supported sources
The Actor reads public review surfaces exposed by each store. Use the store-specific app or extension ID listed below.
Supported stores
| Store | Input id | Public source | Language behavior | Developer replies |
|---|---|---|---|---|
| Google Play reviews | Android package name, for example com.spotify.music | Public Google Play review surface | Uses requested country and language as public endpoint context where supported | Included when exposed by the public payload |
| Apple App Store reviews | Numeric app ID, for example 324684580 | Public iTunes customer reviews RSS/JSON feed | Storefront-specific; requested language is target context, not a guaranteed source filter | Not exposed by this public RSS source |
| Chrome Web Store reviews | Extension ID, for example aapbdbdomjkkjkaonfhkkikfgjllcleb | Public Chrome Web Store review surface | Uses requested country/language context where supported | Included when exposed by the public payload |
What it does not do
- No login.
- No cookies.
- No private APIs.
- No private developer dashboards.
- No CAPTCHA bypass.
- No account impersonation.
- No guaranteed full historical depth.
- No AI calls or external enrichment APIs.
This Actor collects public data only. Public reviewer display names can appear only when they are part of public review content. It is not affiliated with Google, Apple, Chrome, or any app/extension owner.
Input schema
| Field | Type | Default | Description |
|---|---|---|---|
apps | { store, id, country?, language? }[] | required | Apps/extensions to scrape. Store must be google_play, app_store, or chrome_web_store. |
maxReviewsPerApp | integer | 100 | Maximum raw reviews per concrete target, from 1 to 5000. A concrete target is store + appId + country + language. |
maxReviewsPerTarget | integer | empty | Alias for maxReviewsPerApp. If both are provided, they must match. |
ratings | integer array | [1, 2, 3, 4, 5] | Rating filter applied after normalization. Duplicate ratings are removed. |
languages | string array | ["en"] | Global languages used when a target has no app-level language. |
countries | string array | ["US"] | Global countries/storefronts used when a target has no app-level country. |
onlyNewSinceLastRun | boolean | false | When true, only unseen review records for the same stateKey are pushed to the dataset. |
stateKey | string | default | Namespace for incremental state in the Actor's internal named Key-Value Store. |
includeTopicClassification | boolean | true | Adds rule-based topics for negative reviews. |
includeAppSummary | boolean | true | Pushes one app_summary record per successful target. |
webhookUrl | HTTP(S) URL | empty | Sends one final JSON POST with summaries and new negative reviews. |
proxyConfiguration | Apify proxy object | { "useApifyProxy": true } | Standard Apify proxy configuration used for store HTTP requests when a proxy URL is available. |
maxConcurrency | integer | 3 | Maximum store targets fetched in parallel. |
requestTimeoutSecs | integer | 30 | Timeout for public HTTP requests. |
maxRequestRetries | integer | 3 | Retry budget for transient store request failures. |
maxTargets | integer | 100 | Safety limit for expanded concrete targets. |
maxTotalReviews | integer | 10000 | Safety limit for expandedTargets.length * maxReviewsPerApp. |
App-level country and language override global arrays. Without overrides, the Actor expands every app into global countries x languages combinations. maxReviewsPerApp is applied after expansion, per concrete target.
Input examples
1. Google Play review monitor
{"apps": [{ "store": "google_play", "id": "com.spotify.music", "country": "US", "language": "en" }],"maxReviewsPerApp": 100,"ratings": [1, 2, 3, 4, 5],"includeAppSummary": true,"stateKey": "google-play-monitor"}
Google Play example
The example above is the standard Google Play example for a single app monitor.
2. Apple App Store review monitor
{"apps": [{ "store": "app_store", "id": "324684580", "country": "US", "language": "en" }],"maxReviewsPerApp": 100,"includeAppSummary": true,"stateKey": "apple-app-store-monitor"}
Apple App Store example
The example above monitors a public Apple App Store RSS review feed by numeric app ID.
3. Chrome Web Store review monitor
{"apps": [{ "store": "chrome_web_store", "id": "aapbdbdomjkkjkaonfhkkikfgjllcleb", "country": "US", "language": "en" }],"maxReviewsPerApp": 50,"includeAppSummary": true,"stateKey": "chrome-extension-monitor"}
Chrome Web Store example
The example above is a Chrome extension monitor for public extension reviews.
4. Multi-store competitor review analysis
{"apps": [{ "store": "google_play", "id": "com.spotify.music", "country": "US", "language": "en" },{ "store": "google_play", "id": "com.duolingo", "country": "US", "language": "en" },{ "store": "app_store", "id": "324684580", "country": "US", "language": "en" },{ "store": "chrome_web_store", "id": "aapbdbdomjkkjkaonfhkkikfgjllcleb", "country": "US", "language": "en" }],"maxReviewsPerTarget": 100,"includeAppSummary": true,"includeTopicClassification": true,"stateKey": "competitor-review-analysis"}
5. onlyNewSinceLastRun scheduled monitor
{"apps": [{ "store": "google_play", "id": "com.spotify.music", "country": "US", "language": "en" },{ "store": "app_store", "id": "324684580", "country": "US", "language": "en" }],"maxReviewsPerApp": 50,"onlyNewSinceLastRun": true,"includeAppSummary": true,"stateKey": "daily-negative-review-monitor"}
6. negative review webhook alert
{"apps": [{ "store": "google_play", "id": "com.spotify.music", "country": "US", "language": "en" },{ "store": "app_store", "id": "324684580", "country": "US", "language": "en" }],"ratings": [1, 2],"onlyNewSinceLastRun": true,"webhookUrl": "https://example.com/review-alerts","includeAppSummary": true,"stateKey": "daily negative review monitor"}
Output examples
Output schema
Review records use "recordType": "review":
{"recordType": "review","store": "google_play","appId": "com.example.app","appName": null,"appUrl": null,"developerName": null,"country": "US","language": "en","scrapedAt": "2026-05-29T09:00:00.000Z","reviewId": "review-123","fingerprint": "google_play:com.example.app:review-123","reviewUrl": null,"rating": 1,"title": "Crashes after update","text": "The app crashes every time I open it after the latest update.","reviewDate": "2026-05-28T00:00:00.000Z","reviewCreatedAt": "2026-05-28T00:00:00.000Z","reviewUpdatedAt": null,"authorName": "Public reviewer name","authorId": null,"authorUrl": null,"appVersion": "4.2.1","developerReply": null,"developerReplyText": null,"developerReplyDate": null,"hasDeveloperReply": false,"sentiment": "negative","sentimentMethod": "rating_plus_rules","topic": "bug_crash","topicMethod": "rule_based","primaryTopic": "bug_crash","topics": ["bug_crash"],"topicScores": { "bug_crash": 2 },"isNew": true,"sourceUrl": "https://play.google.com/store/apps/details?id=com.example.app&hl=en&gl=US","sourceLanguageFilterApplied": true,"languageFilterReliability": "best_effort","storeCategory": null,"storeRating": null,"storeReviewCount": null,"warnings": [],"storeData": {}}
If a source does not expose an optional field, the Actor writes null or [] instead of breaking the schema.
Summary records use "recordType": "app_summary":
{"recordType": "app_summary","store": "google_play","appId": "com.example.app","country": "US","language": "en","scrapedAt": "2026-05-29T09:00:00.000Z","stateKey": "weekly-monitoring","reviewsScraped": 100,"reviewsOutput": 17,"newReviews": 17,"newNegativeReviews": 8,"reviewCount": 100,"averageRating": 3.42,"negativeRate": 0.32,"sentimentCounts": { "negative": 32, "neutral": 18, "positive": 50 },"topTopics": [{ "topic": "bug_crash", "count": 12, "rate": 0.375 }],"developerReplyRate": 0.12,"developerReplyCoverage": "available","sourceLanguageFilterApplied": true,"languageFilterReliability": "best_effort","sentimentMethod": "rating_plus_rules","topicMethod": "rule_based","appName": null,"appUrl": null,"developerName": null,"storeCategory": null,"storeRating": null,"storeReviewCount": null,"warnings": []}
User-facing Key-Value Store output
Each run writes a compact OUTPUT record in the default Key-Value Store. This is separate from internal incremental state and is safe to use as the run-level summary for integrations.
OUTPUT contains actorName, runId, status, scrapedAt, stateKey, onlyNewSinceLastRun, datasetId, keyValueStoreId, summary counters, byStore, byTarget, appSummaries, warnings, and errors. Status is succeeded, partial_success, or failed.
If all targets fail, the Actor still writes OUTPUT with status="failed" and then throws so the Apify run is marked failed.
Webhook usage
When webhookUrl is set, the Actor sends one final JSON POST after dataset records and state are written. The webhook payload includes run metadata, summary counters, app summaries, warnings, errors, and up to 100 new negative reviews with review text truncated to avoid huge payloads.
Webhook payload example
{"actorName": "App & Extension Review Intelligence","runId": "apify-run-id","scrapedAt": "2026-05-29T09:00:00.000Z","stateKey": "weekly-monitoring","onlyNewSinceLastRun": true,"summary": {"targetsProcessed": 3,"targetsSucceeded": 3,"targetsFailed": 0,"reviewsScraped": 250,"reviewsOutput": 42,"newReviews": 42,"newNegativeReviews": 19},"appSummaries": [],"newNegativeReviews": [],"warnings": [],"errors": [],"datasetId": "default-dataset-id","keyValueStoreId": "default-key-value-store-id"}
Webhook failures are warnings, not scraping failures. If delivery fails after retries, the Actor writes LAST_WEBHOOK_FAILURE with failedAt, attempts, errorCode, errorMessage, webhook host only, datasetId, summary counters, and newNegativeReviewsCount. It does not store full webhook payloads, raw HTML, cookies, tokens, or secrets.
Incremental state / stateKey
onlyNewSinceLastRun controls dataset output, not scraping. The Actor still fetches the current public review page, normalizes records, deduplicates within the run, and updates state for successful targets.
State is stored in the Actor's internal named Apify Key-Value Store, separate from the per-run default store that holds INPUT, OUTPUT, and webhook diagnostics. Internal state entries use:
APP_EXTENSION_REVIEW_INTELLIGENCE_STATE_<safeStateKey>
Use different stateKey values for independent monitors, for example weekly-monitoring, competitors-us, or release-7-2. Fingerprints are namespaced by store + appId + country + language, so the same app can be monitored separately across locales.
Rule-based sentiment and topic classification
The Actor uses deterministic local rules and does not call external AI, sentiment, enrichment, or topic APIs.
The rule-based sentiment method is rating_plus_rules. Ratings 1 and 2 are negative, rating 3 is neutral, and ratings 4 and 5 are positive, with limited keyword rules for borderline cases.
Topic classification runs for negative reviews when includeTopicClassification=true. It returns topic, primaryTopic, topics, and topicScores. Supported topics are billing, bug_crash, login, performance, support, pricing, UX, feature_request, spam, and other.
Understanding warnings
| Warning code | Meaning |
|---|---|
APP_STORE_LANGUAGE_FILTER_NOT_GUARANTEED | Apple App Store public RSS is storefront-based and does not guarantee filtering by requested language. |
TOPIC_CLASSIFICATION_ENGLISH_BIASED | Topic rules use an English keyword dictionary; interpret non-English topic labels cautiously. |
NO_PUBLIC_REVIEWS_FOUND | The public source returned no reviews for the target/filter combination. |
PUBLIC_ACCESS_BLOCKED | The public source returned a login, CAPTCHA, or access-blocked response. |
GOOGLE_PLAY_PARSE_FAILED | Google Play public payload changed or could not be parsed. |
APP_STORE_RSS_UNAVAILABLE | Apple RSS feed failed or returned malformed data. |
CHROME_WEB_STORE_LIMITED_REVIEWS | Chrome reports more public reviews than this run could retrieve from the public endpoint. |
CHROME_WEB_STORE_PARSE_FAILED | Chrome Web Store public payload changed or could not be parsed. |
LOW_CONFIDENCE_INCREMENTAL_DEDUPE | A review lacked stable identifiers, so incremental dedupe used a lower-confidence fallback. |
WEBHOOK_DELIVERY_FAILED | The webhook endpoint timed out or returned an error. |
Limitations
Apple language limitation
Apple App Store public RSS is storefront-based. Requested language is preserved in output and target keys, but source-side language filtering is not guaranteed. Apple targets include sourceLanguageFilterApplied=false, languageFilterReliability="not_applied", and APP_STORE_LANGUAGE_FILTER_NOT_GUARANTEED.
Apple developer reply limitation
Apple App Store public RSS does not expose developer replies. Apple summaries use developerReplyCoverage="not_exposed_by_source".
Google/Chrome public endpoint limitation
Google Play and Chrome Web Store data comes from public review surfaces. Availability, ordering, pagination depth, historical coverage, developer replies, and metadata can change by store, country, language, app, and time. Public endpoint limitations are reported as warnings when possible.
Store limitations and troubleshooting
| Symptom | Likely reason | What to check |
|---|---|---|
| No records for a target | No public reviews were returned for that country/language/filter | Try another country/language or broader ratings. |
| Partial success | One target failed while others succeeded | Check OUTPUT.byTarget and warnings/errors. |
| All-target failure | Every target failed validation or fetching | Check run logs and failed OUTPUT. |
| Apple language warning | Apple RSS language filtering is not guaranteed | Treat Apple language as target context. |
| Webhook warning | Endpoint rejected or timed out | Verify the endpoint accepts JSON POST and returns HTTP 2xx. |
Pricing note
For Store V1, keep pricing simple. A good draft is a small Actor start event plus a low per-result price based on default dataset items. Because this Actor writes both review and app_summary records to the default dataset, default dataset item pricing charges both record types unless configured otherwise in Apify Console. Do not apply pricing automatically without final owner approval.
Public data only
This Actor works with public review sources only. It does not request credentials, does not read private dashboards, does not use cookies, and does not bypass CAPTCHA or access controls. Use it in a way that respects source terms and local laws.
Development
npm run buildcompiles TypeScript todist/.npm startruns the compiled Actor entrypoint.npm run devruns the TypeScript entrypoint withtsx.npm run smoke:liveruns a small real-source smoke against one target per supported store and writesstorage/smoke-live-report.json.npm testruns the Vitest suite once.npm run test:watchruns Vitest in watch mode.