App Store Reviews & ASO Scraper
Pricing
Pay per event
App Store Reviews & ASO Scraper
Unified Google Play + Apple App Store review scraper with ASO rollup signals — rating distribution, trend, velocity, and keyword frequency across both stores in one run. Pay-Per-Event, no login, no API key.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
TL;DR
Give it a list of apps — each with a Google Play package name, an Apple App Store numeric id, or both — and it returns one unified row per review from whichever stores you supplied, plus one ASO rollup row per app. The leading single-store scrapers on the Apify Store cover one platform each. This one bundles both behind a shared schema, so a cross-store comparison is a GROUP BY instead of a reconciliation project.
✨ What it does
- Both stores, one schema.
store: "google_play" | "app_store"on every row. Same field names, same date format, same rating scale — no post-processing to line them up. - ASO rollup per app. Rating distribution, monthly rating trend, reviews-per-day velocity, and the keyword frequencies behind praise and complaints. One row, computed from the reviews actually sampled.
- Either store alone is fine. Supply only
playPackageNameor onlyappleAppIdand it happily runs single-store. - Country storefronts.
appleCountryCodeper app, andplayHl/playGlfor Play's language and country. - Fault-isolated. One app failing does not sink the run — it skips that app and keeps going, so a 20-app batch returns 19 apps' reviews instead of nothing.
🛡️ What we handle so you don't
Neither store hands review data over politely. Google Play has no public reviews API at all — the data comes from an internal batched RPC endpoint whose payload is a nested array with no field names, and which changes shape without notice. Apple's customer-reviews feed is per-country, paginated, and hard-caps at roughly 50 reviews per app no matter what you ask for.
Retries, backoff, pagination, proxy rotation, per-store rate limits and the RPC payload decoding all live inside the Actor. When a store throttles us we back off and come back rather than failing your run. You send app ids; you get rows.
🎯 Who it's for
- ASO and app-marketing teams — track sentiment and rating trend across both stores in one dataset.
- Product teams — pull the complaint keywords behind a rating drop after a release.
- Competitive intelligence — sample rivals' reviews and compare velocity and distribution, not just the headline star rating.
- Support and QA — surface recurring defect language before it reaches your own ticket queue.
📥 Inputs
| Field | Type | Default | Notes |
|---|---|---|---|
apps | array | (Instagram example) | List of { playPackageName, appleAppId, appleCountryCode, label }. Each entry needs at least one of playPackageName / appleAppId. |
maxReviewsPerApp | integer | 200 | Per-store cap. Apple's own feed hard-caps near 50 regardless of what you set. |
playHl | string | "en" | Google Play language. |
playGl | string | "us" | Google Play country. |
includeRollup | boolean | true | Emit the per-app ASO rollup row alongside the review rows. |
proxyConfiguration | object | unset | Apify Proxy editor. Optional — neither endpoint required a proxy in testing. |
📤 Outputs
Two row shapes share one dataset, distinguished by row_type:
Review row — one per review:
store, app_label, app_id, review_id, author_name, rating, title, content, review_date, app_version, thumbs_up_count, developer_reply_content, developer_reply_date, scraped_at
ASO rollup row (row_type: "aso_rollup") — one per app:
stores_included, total_reviews_sampled, rating_distribution, average_rating, rating_trend_monthly, review_velocity_per_day, top_praise_keywords, top_complaint_keywords, scraped_at
Export as JSON, CSV, Excel or via the API.
🚀 How to use it
- Add one entry to
appsper app you care about. Include both ids to get both stores. - Set
maxReviewsPerAppto how deep you want to sample. - Leave
includeRollupon unless you only want raw reviews. - Run it. Rows stream into the dataset as each app completes.
{"apps": [{"playPackageName": "com.instagram.android","appleAppId": "389801252","appleCountryCode": "us","label": "Instagram"}],"maxReviewsPerApp": 50,"includeRollup": true}
💰 Pricing
Pay-Per-Event — you pay for rows, not for runtime:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.20 | One-off warm-up charge per run |
review-scraped | $0.0012 | Per review row written to the dataset |
rollup-computed | $0.005 | Per ASO rollup row (once per app, not per review) |
1 000 reviews for one app ≈ $1.41 ($0.20 + 1 000 × $0.0012 + one $0.005 rollup). No subscription, no seat fee, no minimum.
❓ FAQ
Do I need an API key, a login, or my own proxy? No. There is no public reviews API to get a key for — that is the whole point of this Actor. Everything is handled inside it.
Why does Apple return so few reviews?
Because Apple's public customer-reviews feed caps out around 50 per app, per country. That is their limit, not ours, and no scraper can raise it. Setting maxReviewsPerApp to 500 will not change Apple's answer — though it will still deepen the Google Play side.
Can I scrape only one store? Yes. Omit the id for the store you don't want.
What happens if one app in my list fails? That app is skipped and the run continues. You get every other app's reviews, and the log names which app failed and why. A single bad app id does not cost you the batch.
Does an app with zero reviews fail the run? No. An app that legitimately has no reviews is a valid empty answer, not an error. The run finishes SUCCEEDED and says so.
How current are the reviews? Both sources are sampled most-recent-first, so you get the newest reviews up to your cap — the right shape for tracking a rating trend after a release.
Is the ASO rollup computed from all reviews or only the sampled ones?
Only the ones actually sampled in that run, and total_reviews_sampled tells you exactly how many. We would rather report an honest sample size than imply a full-catalogue statistic we did not fetch.