Google Play Store Reviews Scraper: Android App Reviews
Pricing
from $0.05 / 1,000 reviews
Google Play Store Reviews Scraper: Android App Reviews
Scrape Google Play reviews by app URL or package name, language and country: rating, text, reviewer nickname, date, app version, thumbs-up, developer reply and review id, newest first, most relevant or highest rating. Several apps per run, a cap per app, a free app row with a completeness verdict.
Pricing
from $0.05 / 1,000 reviews
Rating
0.0
(0)
Developer
Hyperbach
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Google Play reviews by app, language and country, logged out: Play URLs or package names in, one row per review out — the star rating, the text, the reviewer's nickname and avatar, the date, the app version the reviewer used, the thumbs-up count, the developer's reply with its date, the criteria ratings and the review id — newest first, most relevant or highest rating first, several apps in one run, a cap per app. One free app row per app carries a completeness verdict: COMPLETE (the list's own end), CAPPED (your limit) or PARTIAL. An unknown package, an app with no review in the language: free typed rows. No login, no Google account, no API key, proxies handled for you.
Why this Google Play reviews scraper
- Several apps in one run. Give Play URLs or package names: each app gets its own cap (
maxReviewsPerApp), and the run's cap sits on top (maxItems). A URL's ownhlandglare used whenlanguageandcountryare empty. - Three orders.
newest,mostRelevant(Google Play's own order) andrating(5 stars first, then 4, 3, 2, 1). The first pages of newest and most relevant shared no review on our test. Each row carries itsrankin the order read. - Every field Google Play shows. The star rating and the text, the reviewer's nickname and avatar, the date (UTC), the app version the review was written on, the thumbs-up count, the developer's reply with who wrote it and when, the criteria ratings some apps ask for (
criteria), and Google Play's review id with a link to the review; every row carries the app, the language, the country and the input it answers. - Deep walks. The reviews come 200 a call in the order asked, page after page, to the end of Google Play's list: our test read 12,000 of WhatsApp's newest English reviews with no end in sight (2026-10-22). The free
approw says how many reviews were delivered from how many pages and why the walk stopped: the list's own end (COMPLETE), your cap (CAPPED), or a refusal or the time limit (PARTIAL). - Language is the set. Google Play lists the reviews written in the language asked (
language, the store'shl): French reviews are another set from English ones. Thecountry(the store'sgl) is on every row; on our test it did not change the reviews listed. - Honest runs. A package Google Play does not know is a free
not_foundrow (its app page answered 404 on two exits), an app with no review in the language a freeemptyrow, a value that is no Play app a freeinvalidrow, a repeated app a freeduplicaterow. Every input gets a row; a review is charged once a run. - Fast and light. Plain HTTP on the call Google Play's own web page makes: 200 reviews a call, about 30 KB on the wire for the newest 200. A run of 3 apps × 260 reviews took 4 seconds of reading on our test.
Who it's for
- App developers and product teams — the newest reviews of your Android app in every language you ship, with the app version per review to see what a release changed, and your team's replies beside them.
- ASO and market researchers — the reviews of a list of competitor apps in one run, newest, most relevant or highest rated first, with the criteria ratings some categories carry.
- Data and analytics teams — typed rows keyed by
app_id,languageandreview_id, a free row per app with the status and verdict, a run summary to check a pipeline against.
Quick start
The newest reviews of two apps (a Play URL and a package name)
{"appIds": ["https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US","com.instagram.android"],"maxReviewsPerApp": 50}
One app's reviews in German, up to 1,000
{"appIds": ["com.spotify.music"],"language": "de","country": "DE","maxReviewsPerApp": 1000}
The most relevant reviews of an app
{"appIds": ["com.duolingo"],"sort": "mostRelevant","maxReviewsPerApp": 200}
Output
One row per review (and one free app row per app):
| field | meaning |
|---|---|
row_type | review (one review, charged) or app (the app's row with the walk's verdict; free). |
input_index | The 1-based position in appIds of the input this row answers. |
input_value | The input as you gave it (the URL or package name). |
app_id | The app's package name (com.whatsapp). |
language | The language read (Google Play's hl: en, pt-BR …). |
country | The store country sent (Google Play's gl: US, GB …). |
sort | The order read: newest, mostRelevant or rating. |
status | An app row: ok, empty, not_found, invalid, duplicate, failed or not_read (see the FAQ). A review row: ok. |
status_detail | Why, in words, when the status is not ok. |
scraped_at | When the row was read (ISO 8601, UTC). |
review_id | Google Play's review id. |
rank | The review's position in the order read (from 1). |
rating | The star rating, 1 to 5. |
text | The review's text. |
reviewer_name | The reviewer's nickname, as Google Play shows it. |
reviewer_image | The reviewer's public avatar image. |
published_at | When the review was written or last edited (ISO 8601, UTC). |
app_version | The app version the review was written on (null when Google Play does not show one). |
thumbs_up | How many users marked the review helpful (thumbs up). |
reply_by | Who wrote the developer's reply (the developer's name), null when there is no reply. |
reply_text | The developer's reply to the review, null when there is none. |
replied_at | When the developer replied (ISO 8601, UTC). |
criteria | The criteria ratings Google Play asks for in some categories, as {criterion, rating} pairs (vaf_app_quality_visual_appeal …); null when the review has none. |
url | A link to the review on Google Play. |
app_url | The app's Google Play link in the language and country read (app row). |
reviews_delivered | Review rows delivered for this app (app row). |
pages_read | Pages of Google Play's review list read for this app (app row). |
verdict | COMPLETE (the list's own end), CAPPED (your limit) or PARTIAL (a refusal or the time limit) (app row). |
verdict_detail | The verdict in words, with the numbers (app row). |
Example record:
{"row_type": "review","input_index": 2,"input_value": "com.spotify.music","app_id": "com.spotify.music","language": "en","country": "US","sort": "newest","status": "ok","status_detail": null,"scraped_at": "2026-10-22T20:03:24Z","review_id": "7e211cf7-901d-448b-a5f5-41e0649d4b2d","rank": 3,"rating": 1,"text": "too much annoying ads after every song, atleast let us play 4-5 songs then give ads it will be still better 😡","reviewer_name": "nickname-redacted","reviewer_image": "https://play-lh.googleusercontent.com/a/avatar-redacted","published_at": "2026-10-21T20:01:44Z","app_version": "9.1.92.3058","thumbs_up": 0,"reply_by": "Spotify AB","reply_text": "Hi. Thanks for bringing this up. We'll pass this on to our ads team. If you're seeing more ads than usual, can you try a quick reinstall? If that doesn't help, reach out to our Customer Service in support.spotify.com and search \"Contact us\". They'll help you report this.","replied_at": "2026-10-21T20:29:44Z","criteria": [{"criterion": "vaf_app_quality_ads_frequency","rating": 1}],"url": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=7e211cf7-901d-448b-a5f5-41e0649d4b2d","app_url": null,"reviews_delivered": null,"pages_read": null,"verdict": null,"verdict_detail": null}
Pricing
Pay for the reviews a run delivers, plus one run start; no platform usage is billed to you. The review price falls with your Apify plan.
| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
Review (review) | per 1,000 | $0.10 | $0.085 | $0.07 | $0.05 |
Run start (start) | per run | $0.001 | $0.001 | $0.001 | $0.001 |
A review is $0.10 per 1,000 on the Free plan ($0.0001 a review). Each run that delivers a charged review also pays the run start, $0.001 once; a run that delivers no charged review pays nothing at all. So the 500 newest reviews of one app cost $0.0510 on the Free plan and $0.0435 on Starter, and 1,000 reviews $0.1010 / $0.0860; several apps in one run share one start. The free app row of every app, an unknown package (not_found), an app with no review in the language (empty), a value that is no Google Play app (invalid), a repeated app (duplicate), an app left at the cap or the time limit (not_read) and a refusal the run could not pass (failed) are never charged. A review is charged once a run. A run that stops early (a timeout, an abort) is charged for the reviews it delivered. maxItems counts the charged rows; before the first request the log names the price of each row at your plan and the most the run can cost. Enterprise plans have their own rates: the Actor's Pricing tab shows the price for your plan.
Usage patterns
- Apps, language and country —
appIdstakes Google Play URLs (https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US;market://details?id=links too) or package names (com.whatsapp).languagetakes Google Play language codes (en,de,pt-BR,es-419…) andcountrytwo-letter codes (US,GB,DE…). Each app is read in thelanguageandcountrygiven; when they are empty, in its URL's ownhlandgl, else inenandUS. - What a row is —
row_type=review: one review with Google Play's record;rankis its position in the order read;sortthe order.row_type=app: the free row of one app in one language and country —reviews_delivered,pages_read, theverdictwith itsverdict_detail, and thestatuswith its reason. - How far an app goes —
maxReviewsPerApp= 0 (the default) reads every review Google Play lists for the app, language and order — a big app lists millions, so set a cap,maxItemsor a run timeout.maxReviewsPerApp= 100 is the first 100 in the order asked.maxItemscaps the charged rows of the whole run. The app row'sverdictsays where the walk stopped and why.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
appIds | array | The apps to read: Google Play URLs (https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US) or package names (com.whatsapp). A URL's own hl and gl are used when language and country are empty. Up to 1,000 apps a run; a value that is no Google Play app gets a free invalid row, an app given twice for the same language and country a free duplicate row. | |
language | string | The reviews' language as Google Play codes it (en, de, fr, pt-BR, es-419 …). Google Play lists the reviews written in this language, so each language is a different set of reviews. Empty: the app URL's hl, else en. | |
country | string | The two-letter Google Play country (US, GB, DE, IN …; UK is read as GB), sent as the store's gl and written on every row. Empty: the app URL's gl, else US. On our test the country did not change which reviews Google Play lists; the language does. | |
sort | newest / mostRelevant / rating | "newest" | newest: the newest reviews first. mostRelevant: Google Play's own most-relevant order. rating: the highest star rating first. |
maxReviewsPerApp | integer | 0 | Stop each app after this many review rows (0 = every review Google Play lists for the app, language and order; a big app lists millions, so set a cap or maxItems). |
maxItems | integer | 0 | Stop the run after this many review rows across every app (0 = no limit). App rows are free and not counted; an app left unread at the cap gets a free not_read row. |
Errors
A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:
- the status message starts with
INPUT REJECTED; - the dataset holds one row,
{"error": true, "code": "…", "message": "…"}, and no results; - the key-value store record
ERRORholds the same object.
From code, check error on the first row before reading results.
An app with no review in the language asked is not an error: it gets one free app row with status empty, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.
FAQ
Which status is which?
An app row's status is ok (reviews served), empty (the app exists and has no review in that language), not_found (Google Play does not know the package; its app page answered 404 on two exits), invalid (a value that is no Google Play app), duplicate (the same app, language and country twice: read once), failed (a refusal or an error; free) or not_read (left at maxItems, the charge limit or the run's time limit). A review row's status is ok.
Is there a review title?
No. A Google Play review has a star rating and a text, no title; the row carries what Google Play shows.
Does it read ratings without a text?
No. Google Play lists the reviews with a written text; a star rating given without one is not in the list, so the review count of an app on its page (the ratings) is larger than what any review scraper returns.
Is the reviewer's nickname on the row?
The nickname and the avatar are on every review row as Google Play shows them publicly. They are personal data: process them under your own lawful basis.
Does it need a Google account or API key?
No. Everything is read from Google Play's public web pages, logged out.
Integration
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('hyperbach/google-play-reviews-scraper').call({"appIds": ["https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US", "com.instagram.android"], "maxReviewsPerApp": 50});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('hyperbach/google-play-reviews-scraper').call(run_input={'appIds': ['https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US', 'com.instagram.android'], 'maxReviewsPerApp': 50})items = client.dataset(run['defaultDatasetId']).list_items().items
CLI
$apify call hyperbach/google-play-reviews-scraper --input '{"appIds": ["https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US", "com.instagram.android"], "maxReviewsPerApp": 50}'
REST
curl -X POST "https://api.apify.com/v2/acts/hyperbach~google-play-reviews-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' -d '{"appIds": ["https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=US", "com.instagram.android"], "maxReviewsPerApp": 50}'
Support
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.