Google Play Reviews Scraper - Replies, Versions, Monitor
Pricing
$0.05 / 1,000 per review returneds
Google Play Reviews Scraper - Replies, Versions, Monitor
$0.045 per 1,000 reviews, no start fee. Google Play reviews for any Android app: rating, text, author, date, thumbs-up, app version, developer reply, criteria. Many apps x languages x countries per run, star + date filters, newest-first early stop and a monitor mode that never bills a review twice.
Pricing
$0.05 / 1,000 per review returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Google Play Reviews Scraper — Developer Replies, App Versions, Monitor Mode
Turn any Android app's Google Play reviews into clean rows, read from the same endpoint the Play Store website uses to render its own review list. One row per review: rating, body, userName, userImage, date, thumbsUp, appVersion, developerResponseBody, developerResponseDate, developerResponseAuthor, criteria, reviewUrl — plus the app's appName, appScore and appRatingsCount on every row. Many apps × languages × countries in one run, star and date filters, newest-first early stop, and a monitor mode that never bills the same review twice. No login. No API key. No browser.
$0.045 per 1,000 reviews ($0.000045 each), no start fee.
{"apps": ["com.whatsapp"],"languages": ["en"],"countries": ["us"],"sort": "newest","maxReviewsPerApp": 200}
That block is the input the Actor ships with. Press Start and you get WhatsApp's 200 newest English reviews for $0.009 — measured on the live Actor 2026-09-23: 200 rows, 200 charged, 5 seconds.
This is the Android twin of our
App Store Reviews Scraper: the
same field names wherever the concept is the same (body, userName, date,
appVersion, developerResponseBody, developerResponseDate, position, order,
appUrl), so you can union the two datasets downstream.
What makes it different
- Languages, not just countries — measured, not assumed. Google Play's review list is
keyed by language far more than by country: WhatsApp's 200 newest English reviews were
87–100% identical across the us, gb, in, au and de stores (measured 2026-09-23), while
hl=dereturns a different, German corpus.languagestakes a list, every app is crossed with every language and country, and a review already delivered for another country or language is dropped before billing (dedupeAcrossCountries, on by default). A scraper that sweeps five English-speaking countries without this bills you for largely the same reviews five times. - Monitor mode that cannot skip a gap.
onlyNewReviewskeeps a per app × language × country bookmark in a named key-value store in your account. The next run reads newest-first only down to the bookmark (with a one-hour overlap, because Google's frontends can lag each other by minutes — observed), skips every review it already delivered, and only advances the bookmark when the walk actually reached it — a run cut short by a cap re-reads the gap next time instead of losing it. Measured: a second run 90 s after a 10,000-review baseline read 1 page, recognised 105 overlap reviews as already delivered, and billed $0. - App context on every row.
appName,appScoreandappRatingsCountcome from the app's own store page (its schema.org block), so a multi-app dataset is self-describing. The same read tells a non-existent package (HTTP 404 — skipped, $0, named in the run summary) apart from an app with no reviews in that language. - Integrity checks that end the run instead of shipping bad rows. Every page's review ids are checked against the walk so far; a repeated continuation token or a page of nothing but repeats is a pagination loop and stops the walk. If Google changes the review format, the run fails loudly rather than delivering a page of nulls. At the end, charged events must equal delivered rows exactly.
Read this before you buy rows
dateis when the review was written or last edited. A developer reply can therefore be older than the review it answers — measured on Robinhood: replies from 2022–2025 on reviews re-edited in September 2026. That is Google's data, not a bug.- Google publishes reviews with a delay. The newest review Google served on 2026-09-23 ~05:00 UTC was stamped 2026-09-22 ~04:59 UTC — about a day old. A "last hour" window will usually be empty; that is the source, not the Actor.
- Country barely changes the newest list; language does. See above. For a worldwide
sweep, list languages (
en,es,pt-BR,de,fr,ja…) with one country each. Countries do change the most relevant order (27–35% overlap between us and gb/in/au/de for Spotify, measured). - Reviews are not ratings. Spotify shows 36.4M ratings; the reviews Google serves are the written ones in the language you ask for. Home Assistant (English) ended at 1,574 reviews — the corpus end is a missing continuation token, and the run says "corpus exhausted at N reviews".
criteriaare Google's own raw keys (vaf_app_quality_usability,vaf_phase1_investing…) with the number Google stores. Google does not publish what each number means, so the Actor passes them through untranslated rather than guess.- Reviewer fields are a name and an avatar only.
userNameis the public display name shown on the Play Store (sometimes a real name, sometimes "A Google user");userImageis the public avatar URL. No email, phone or address exists in this data.
What you get
One row per review. Dates are ISO-8601 UTC. rating is an integer 1–5.
| Group | Fields | Notes |
|---|---|---|
| Identity | reviewId, appId, appName, language, country | language/country are the values you requested — Google does not label a review's language, so the Actor never infers one |
| Review | rating, body, date, thumbsUp | thumbsUp = "helpful" votes; 0 is a real zero |
| Reviewer | userName, userImage | public display name + avatar URL |
| Version | appVersion | the app version the reviewer had installed; null when Google shows none |
| Developer reply | developerResponseBody, developerResponseDate, developerResponseAuthor | all three null together when there is no reply — never "" |
| Quality questions | criteria | [{criterion, rating}], Google's raw keys, or null |
| App context | appScore, appRatingsCount | from the app's store page (turn off with includeAppDetails) |
| Provenance | position, order, starFilter, reviewUrl, appUrl, source, scrapedAt | position = rank within its app × language × country walk |
Field fill — measured on the live Actor, three frames
Frames were chosen to disagree on purpose (newest vs most relevant; ten apps vs one), so the spread between them is the honest range.
| Field | A: 10 apps × 200 newest (2,000 rows) | B: same 10 apps × 200 most relevant (2,000) | C: WhatsApp 10,000 newest |
|---|---|---|---|
reviewId, rating, body, date, userName, userImage, thumbsUp, reviewUrl | 100% | 100% | 100% |
appName, appScore, appRatingsCount | 100% | 100% | 100% |
appVersion | 81.8% | 98.9% | 82.2% |
developerResponseBody / Date / Author | 27.9% | 27.3% | 0.0% |
criteria | 19.6% | 35.4% | 25.8% |
thumbsUp > 0 | 13.6% | 90.0% | 20.6% |
Developer replies are publisher behaviour, not a parser rate. Per app in frame A (of 200
newest): Booking.com 193, Robinhood 175, TikTok 157, Spotify 31, Uber 1 — and 0 for WhatsApp,
Netflix, Airbnb, Instagram and Duolingo. The offline validator checks the negative direction
too: every raw reply, version and criteria block in the captured bytes is emitted (0 parser
gaps across 400 fixture reviews). The ten apps were: WhatsApp, Spotify, Robinhood, Duolingo,
Uber, Instagram, Netflix, Airbnb, Booking.com, TikTok. Every run prints its own fill in the
log and in RUN_SUMMARY.
How to run it
1. The default — one app, newest 200
The shipped input above. $0.009.
2. Complaint mining across competitors
{"apps": ["com.spotify.music", "com.soundcloud.android", "deezer.android.app"],"languages": ["en"],"countries": ["us"],"stars": [1, 2],"maxReviewsPerApp": 2000}
Stars are filtered server-side by Google (one star at a time, 1★ first; the per-app cap is shared across them). 6,000 reviews max = $0.27.
3. Support-behaviour audit — only reviews the developer answered
{ "apps": ["com.booking"], "onlyWithDeveloperReply": true, "maxReviewsPerApp": 1000 }
Reviews without a reply are read but never billed.
4. A date window, cheaply
{ "apps": ["com.whatsapp"], "sort": "newest", "sinceDate": "2026-09-01", "untilDate": "2026-09-15", "maxReviewsPerApp": 0 }
With sort: "newest" paging stops at the first review older than sinceDate. (With the other
sorts, dates are applied row by row and paging cannot stop early — the log warns you.)
5. Daily monitor across languages
{"apps": ["com.yourcompany.app"],"languages": ["en", "es", "pt-BR", "de", "fr"],"countries": ["us"],"onlyNewReviews": true,"maxReviewsPerApp": 5000}
Save it as a Task, attach a Schedule (0 7 * * *). The first run is your baseline
(it reads newest-first up to your caps and sets the bookmark); every later run delivers only
what is new. From the API:
curl -X POST "https://api.apify.com/v2/acts/scrapersdelight~google-play-reviews-scraper/runs?token=YOUR_TOKEN" \-H 'Content-Type: application/json' \-d '{"apps":["com.whatsapp"],"languages":["en"],"onlyNewReviews":true}'
API callers used to other scrapers' inputs can send a single "language": "de" — it is
accepted and replaces languages.
Sample row
A real row from the live run of 2026-09-23 (frame A, Robinhood, newest):
{"reviewId": "398cee35-43b5-440f-8b02-5c2551876b84","appId": "com.robinhood.android","appName": "Robinhood: Trading & Investing","country": "us","language": "en","rating": 4,"body": "Finally, updated and fixed all kinds of stuff. upgraded review from 2 to 4 stars, but now, it's got too much nonsense. 🤷♂️","userName": "Christian Zagarskas","userImage": "https://play-lh.googleusercontent.com/a-/ALV-UjUHIeC5rq2CH3qVdxD35VfDnE60V24nELfXX9mbOA1-OXnyqpNQ","date": "2026-09-22T01:53:49.801Z","thumbsUp": 4,"appVersion": "2026.37.4","developerResponseBody": "Sorry to hear this wasn’t a great experience. If you’re up for it, send a note to reviews@robinhood.com with a few more details.","developerResponseDate": "2026-09-22T03:31:00.382Z","developerResponseAuthor": "Robinhood","criteria": [{ "criterion": "vaf_phase1_investing", "rating": 1 }],"position": 2,"order": "newest","starFilter": null,"reviewUrl": "https://play.google.com/store/apps/details?id=com.robinhood.android&reviewId=398cee35-43b5-440f-8b02-5c2551876b84","appUrl": "https://play.google.com/store/apps/details?id=com.robinhood.android&hl=en&gl=us","appScore": 4.624,"appRatingsCount": 574404,"source": "google-play-batchexecute","scrapedAt": "2026-09-23T05:04:40.951Z"}
Input
| Field | Type | Default | What it does |
|---|---|---|---|
| 🎯 What to scrape | |||
apps | string list | ["com.whatsapp"] | Package names or Play Store links. A package that does not exist is reported and skipped, $0. Empty = the WhatsApp sample. |
languages | string list | ["en"] | hl codes, one per entry (en, de, pt-BR…). Each is its own corpus. |
countries | string list | ["us"] | gl codes, one per entry. |
sort | select | newest | newest, mostRelevant (the store page's default) or rating (highest first). |
| 🎚️ Filters (applied before billing) | |||
stars | integer list | [] (all) | e.g. [1, 2]. Server-side. |
sinceDate / untilDate | date | — | UTC; a plain date covers the whole day. Early stop with newest. |
onlyWithDeveloperReply | boolean | false | Only reviews carrying a developer reply. |
onlyNewReviews | boolean | false | Monitor mode (above). Forces newest. |
| 📊 Output & cost | |||
maxReviewsPerApp | integer | 200 | Per app × language × country. A review already delivered for another country/language fills a slot without being billed again. 0 = no cap. |
maxItems | integer | 10000 | Hard cap for the whole run ($0.45). 0 = none. |
dedupeAcrossCountries | boolean | true | Drop a review already delivered for another country or language. |
| ⚙️ Advanced | |||
includeAppDetails | boolean | true | Adds appName/appScore/appRatingsCount and detects non-existent packages; one ~1.3 MB page per app. |
maxConcurrency | integer | 3 | Parallel app × language × country walks, max 5. |
proxyConfiguration | proxy | off | Direct from Apify's network by default; retries after two failures move to a RESIDENTIAL session automatically. |
saveRawResponses | boolean | false | Debugging: stores up to 40 raw Google responses in the run's key-value store. |
Pricing
$0.000045 per review returned — $0.045 per 1,000. Charged on the review-scraped event,
as rows are pushed. No start fee, no monthly fee from this Actor.
| Run | Reviews | Cost |
|---|---|---|
| The shipped default | 200 | $0.009 |
| 10 apps × 200 newest | 2,000 | $0.09 |
| One app's newest 10,000 | 10,000 | $0.45 |
| A 100,000-review corpus | 100,000 | $4.50 |
- You pay for rows delivered. Repeats, reviews removed by your star/date/reply filters, reviews a previous monitor run already delivered and packages that do not exist are never charged.
- A run's maximum total charge is honoured to the row: whole reviews, clean stop.
- Every run ends with a billing integrity check — charged events must equal delivered rows exactly, or the run errors instead of mis-billing.
Honest limits
- Only written reviews. Star-only ratings are not public and not in any Play endpoint.
- Language is Google's matching, not a detector. Google serves reviews for the
hlyou ask; a few may be in another language. Thelanguagefield states what was requested. - Replies depend on the publisher — 0% for many large apps (see the fill table).
criteriavalues are unlabelled by Google and passed through raw.- One Google field is not emitted: about 1% of reviews carry a second short text next to the review body whose meaning Google does not label. Rather than guess a name for it, the Actor leaves it out.
- Throughput: measured 10,000 reviews in 37.6 s at the default 512 MB (one app, one walk). Continuation tokens are sequential by nature; parallelism comes from multiple app × language × country walks.
- This is Google's internal web endpoint, not a published API. If Google changes the response shape, the run fails loudly (it will not ship nulls) and the parser gets updated.
How it works
The Actor POSTs to play.google.com/_/PlayStoreUi/data/batchexecute (rpc UsvDTd) — the
call the Play Store website makes when you scroll its review list — with the sort, the page
size (200), the star filter and the continuation token, and reads the JSON the page itself
renders from. The request and response shape were derived from bytes captured on
2026-09-23, and the offline test suite (29,553 assertions) runs the parser over real captured
pages: an 8-page corpus walked to its end (1,574 reviews, 0 duplicates, dates strictly
newest-first), star-filtered pages, a German store page, and a non-existent package.
Transport, measured: direct from Apify's network, 0 retries across every test run (including 51 consecutive pages for a 10,000-review walk). A non-200, a body that is not a batchexecute answer, or a Google "unusual traffic" page is treated as a transport failure — retried with backoff and, from the third attempt, on a fresh RESIDENTIAL session — never as "no more reviews".
Support
Found an app that returns nothing, or need another field? Open an issue on the Issues tab with the package name, language and country.