App Store and Google Play Reviews Scraper
Pricing
$0.10 / 1,000 reviews
App Store and Google Play Reviews Scraper
Scrape app reviews from Google Play and the Apple App Store into one fixed table. Pick the country and language, sort by newest, relevant or rating, filter by stars or date, and get thousands of reviews per app.
Pricing
$0.10 / 1,000 reviews
Rating
0.0
(0)
Developer
Om Ray
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Security
Limited permissionsShare
This actor collects app reviews from Google Play and the Apple App Store and puts them in one table. Every row has the same fields in the same order, whichever store it came from and whatever you set in the input. You can mix both stores in one run.
It runs without a login or a proxy. The actor only reads reviews that anyone can see on the store pages.
Input
Put one app per line in apps. The actor works out the store from what you paste:
- a Google Play package ID, like
com.spotify.music - a Google Play URL, like
https://play.google.com/store/apps/details?id=com.spotify.music - an App Store numeric ID, like
324684580orid324684580 - an App Store URL, like
https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580
The other settings apply to every app in the run.
| Field | What it does |
|---|---|
country | Two-letter country code. Default us. |
language | Language code such as en, fr or pt-BR. Default en. |
sort | newest, relevant or rating (highest first). Default newest. |
maxReviews | Most reviews to save for each app, from 1 to 100,000. Default 100. |
stars | Keep only these star ratings, for example ["1", "2"]. Empty keeps all. |
since | Keep only reviews from this date onward, for example 2026-10-01. |
includeReviewerName | Add the reviewer's public display name. Off by default. |
maxRunMinutes | Stop collecting after this many minutes. Default 30. |
This is the input from examples/input.json:
{"apps": ["com.spotify.music", "324684580"],"country": "us","language": "en","sort": "newest","maxReviews": 50}
Output
Each review is one dataset row. These two rows come from a real run of the input above.
[{"type": "review","store": "google-play","appId": "com.spotify.music","appTitle": "Spotify: Music and Podcasts","country": "us","language": "en","reviewId": "49084f4d-4f1d-4301-8559-80f8d1ccdf30","rating": 1,"title": null,"text": "fake offer. $1 first 30 days is not $13.90 for 2 months. Thats legit scamming! Waiting in full refund!","date": "2026-10-31T14:52:54.000Z","appVersion": "9.1.44.2120","helpfulCount": 0,"developerReply": "Hi. Thanks for bringing this up. We're open to feedback, and we'd love to get some more info about this. If you have the time, give our Customer Service a shout. You can find them by heading to support.spotify.com and searching \"Contact us\".","developerReplyDate": "2026-10-31T15:18:05.000Z","reviewUrl": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=49084f4d-4f1d-4301-8559-80f8d1ccdf30&hl=en&gl=us","reviewerName": null,"input": "com.spotify.music","statusMessage": null},{"type": "review","store": "app-store","appId": "324684580","appTitle": "Spotify: Music and Podcasts","country": "us","language": "en","reviewId": "14732288924","rating": 4,"title": "Great app but the non music and podcast related adds","text": "On Spotify it is stated in the name “music and podcasts” but I’m always getting adds that are not even related to music or podcasts half the time it just feels asinine to me that I’m getting adds about delivery services or clothes when the app is literally focused around music and podcasts. I don’t mind the music and podcasts adds but it’s the nonsense of these random business appearing on a music app","date": "2026-10-31T04:40:00.000Z","appVersion": "9.1.94","helpfulCount": 0,"developerReply": "Hi. We'd love to get some more info about this. If you have the time, give our Customer Service a shout. You can find them by heading to support.spotify.com and searching \"Contact us\".","developerReplyDate": "2025-09-05T12:30:46.000Z","reviewUrl": null,"reviewerName": null,"input": "324684580","statusMessage": null}]
Fields
| Field | Meaning |
|---|---|
type | review for a review. status for a free row that explains why an app gave nothing. |
store | google-play or app-store. |
appId | Package ID on Google Play, numeric ID on the App Store. |
appTitle | App name in the country and language you picked. |
country | The country code used for the request. |
language | The language code used for the request. |
reviewId | The store's ID for the review. |
rating | Stars, 1 to 5. |
title | Review title. Always null on Google Play, which has no titles. |
text | Review text. |
date | When the review was posted or last edited, in UTC. |
appVersion | App version the reviewer had. On the App Store, only the newest 500 or so reviews have it. |
helpfulCount | Thumbs-up count on Google Play. Helpful votes on the App Store, for the newest 500 or so reviews only. |
developerReply | The developer's reply, if there is one. |
developerReplyDate | When the reply was posted or last edited. Apple keeps an old reply on a review that was later edited, so this date can be older than date. |
reviewUrl | Link to the review on Google Play. null on the App Store, which has no link per review. |
reviewerName | Public display name, only when includeReviewerName is on. |
input | The line from apps that produced this row. |
statusMessage | On status rows, the reason nothing was collected. null on reviews. |
The actor never collects profile pictures or user IDs.
Run summary
The OUTPUT record in the key-value store lists every app with how many reviews were saved and why collection stopped:
reached-max: it savedmaxReviews.no-more-reviews: the store has no more reviews for this app, or none that match your filters.reached-since-date: withsortset tonewest, it reached reviews older thansince.store-limit: the store would not give more pages.time-budget:maxRunMinutesran out.charge-limit: your spending limit for the run was reached.invalid-app-idorapp-not-found: the app line was not an app, or the store has no such app in that country.error: the store kept failing after retries. The message has the details.
When an app gives no reviews, you also get one status row in the dataset with the reason, so you never end up with an empty table and no explanation.
Country and language
On the App Store, reviews belong to a country's store. Setting country to ng gets reviews from the Nigerian App Store only, and the app title comes from that store too. To cover more countries, run the actor once per country.
Google Play works differently and groups reviews by language. The actor sends your country to Google Play and records it on every row, but Google Play returns the same reviews for en whether the country is us, ng or gb. To get reviews in another language, change language.
How far it goes
On Google Play, the actor pages with the store's continuation token until it reaches maxReviews or the last review. In a local test it saved 3,000 Snapchat reviews in about 35 seconds.
On the App Store, it reads the same reviews API the App Store website uses, 20 reviews a page, and follows each page to the next. In a local test it saved 3,000 Snapchat reviews from the Nigerian store in about a minute. Apple slows down fast requests, so the actor waits and retries when that happens. Very large App Store runs take a while. The App Store does check language, and a code it doesn't know ends that app with an error status row.
If Apple's reviews API is not reachable, the actor falls back to Apple's public reviews RSS feed. That feed stops at 10 pages, which is about 500 reviews per country, and the summary says store-limit when that happens. Running more countries gets you more reviews in that case.
Filters work like this. A single star rating on Google Play is filtered by Google, so it is fast. Other star filters, and all star filters on the App Store, are applied as reviews come in, so the actor may read many reviews to find enough matches. The since filter stops early only with sort set to newest. With other sorts it has to read the whole list to find recent reviews, so on a big app it usually runs until maxRunMinutes. Use newest with since.
The rating sort on the App Store means most favorable first. If the RSS fallback is in use, rating falls back to newest first.
Price
You pay $0.0001 for each review saved, which is 10 cents per 1,000 reviews. Status rows are free. A run stops cleanly when it reaches the spending limit you set on Apify.
Run it locally
npm installnpm run checknpx apify run --input-file examples/input.json
The tests in test/ use fake store responses to check store detection, paging, filters, the fallback, status rows and the spending limit.
If something breaks or looks wrong, open an issue on the Issues tab and it gets fixed fast, and if this actor helped you, an honest review on the Store helps other people find it.