App Store & Google Play Reviews Scraper
Pricing
$0.20 / 1,000 reviews
App Store & Google Play Reviews Scraper
User reviews of iOS and Android apps in one Actor, with developer replies where the store publishes them.
Pricing
$0.20 / 1,000 reviews
Rating
0.0
(0)
Developer
Lantern Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
A Lantern Lab Actor. Give it iOS and Android apps and get their user reviews: one row per review with the rating, title, text, app version, publish time, reviewer name and - on Google Play - the developer's public reply. Both stores in one run, any storefront, including the Chinese App Store. No login, no cookies, no account of your own.
Every app and country gets a summary row saying whether its reviews were collected in full. An app that was cut short is marked partial: true with the reason, and one that could not be read is failed - neither is ever reported as "0 reviews".
What it does
- Reads App Store reviews from Apple's public customer-review feed, page by page, and Google Play reviews from the store page's own review endpoint, following its pagination.
- Takes both stores in one
appslist: App Store links or IDs, Google Play links or package names, mixed freely. - Reads every app once per country in
countries, so one line covers as many storefronts as you need. - Carries the developer's reply on Google Play rows: who answered, what they wrote and when.
- Says per app and country how complete the result is, and ends with a
RUN_SUMMARYholding the run totals, the request count and the reason the run stopped.
What it does not do
- No app details, charts, or store search. Reviews only.
- No sentiment scores and no AI summaries. The text is the store's, unchanged.
- No developer replies on App Store rows. Apple's public review feed does not carry them, so
developerReplyisnullon every App Store row and the summary row saysdeveloperRepliesAvailable: false. Google Play rows carry the real reply. The field is never filled with a guess. - No review titles on Google Play rows: that store has no title field, so
titleisnull. - No guessing when a store returns nothing for an app in a storefront: that pair is reported
not_foundwith the reason, never as an app without reviews. For the App Store the empty feed is checked against Apple's public lookup first, so "no such app" and "no reviews yet" stay apart. - No scheduling or monitoring built in; use Apify schedules.
Input
| Field | Default | Meaning |
|---|---|---|
apps | - | One app per line: an App Store link (https://apps.apple.com/us/app/id284882215), a bare App Store ID (284882215 or id284882215), a Google Play link (https://play.google.com/store/apps/details?id=com.spotify.music), or a bare package name (com.spotify.music). Required. |
countries | ["us"] | Two-letter storefront codes. Each app is read once per country. |
maxReviewsPerApp | 200 | Reviews per app and country (1-5000). |
sort | newest | newest, mostHelpful, or rating. |
maxUpstreamRequests | derived | Hard ceiling on store requests for the whole run, counted in HTTP attempts. |
Example:
{"apps": ["https://apps.apple.com/us/app/id284882215","com.spotify.music"],"countries": ["us", "gb"],"maxReviewsPerApp": 200,"sort": "newest"}
The same app entered twice is read once. The country in an App Store link is ignored: countries decides which storefronts are read.
Two store limits are reported rather than worked around:
- The public App Store feed holds at most 500 reviews per app and country. Ask for more and that pair ends
partialwithpartialReasonCode: "store_page_limit". - That feed has no rating sort. With
sort: "rating"an App Store app is read newest-first and its summary row showssortRequested: "rating",sortApplied: "newest". Google Play supports all three orders.
maxUpstreamRequests gives you a known upper bound before the run starts. Left empty, the Actor derives one from your input - (sum over app/country pairs of ceil(reviews wanted / 50) + 1) x 2 + 2, which is 12 for one app, one country and 200 reviews - so a run is never uncapped. When the ceiling is reached, the pair being read is marked partial with partialReasonCode: "request_cap", every pair after it is written as not_collected, and the run ends normally. That is your limit, not a problem at the store.
Output
One dataset; recordType tells the rows apart. Two table views are predefined: Reviews and App summaries. A RUN_SUMMARY record in the key-value store holds the run totals and the status of every app and country.
Review rows (recordType: "review"):
| Field | Meaning |
|---|---|
store | appStore or googlePlay. |
appId | Numeric App Store ID, or Google Play package name. |
country | The storefront this row was read from. |
reviewId | The store's own ID for the review. |
parentCommentId | Always null: neither store threads reviews. |
rating | Stars, 1-5. |
title | Review title. null on Google Play, which has no title field. |
text | The review as the user wrote it. |
version | App version the review was written against, when the store publishes it. |
publishedAt | When the store says it was posted (UTC). Apple updates this timestamp when a review is edited. |
userName | The public display name shown next to the review. |
helpfulVotes | Google Play: thumbs-up count. App Store: Apple's net helpful-vote sum. |
developerReply | { developerName, text, repliedAt }, or null. Always null on App Store rows. |
appUrl, reviewUrl | Public links. reviewUrl is null on App Store rows: Apple has no per-review link. |
collectedAt | When we read the row (UTC). |
App summary rows (recordType: "app_summary"), one per app and country:
| Field | Meaning |
|---|---|
collectionStatus | complete, partial, empty, not_found, failed, or not_collected. |
partial | true when this pair was not collected in full. |
partialReason / partialReasonCode | Why collection was short, in words and as a stable code: request_cap, charge_limit, store_page_limit, store_blocked, store_error. The code column never carries anything else, so it is safe to branch on. |
statusReason | The status in words, including statuses that have no code - for example an app that is not in this storefront. |
reviewsCollected / reviewsRequested | What we got, and what the run asked for. |
duplicatesSkipped | Reviews the store returned twice while paging; written once. |
pagesRead | Store pages read for this pair. |
developerReplies | How many of the collected reviews had a developer reply. |
developerRepliesAvailable | Whether this store publishes replies at all. |
sortRequested / sortApplied | What you asked for, and what the store could serve. |
Statuses in one line: complete - everything you asked for, or everything the store has; partial - cut short, reason given; empty - the app exists here and has no reviews; not_found - no such app in this storefront; failed - the store could not be read; not_collected - the run stopped before this pair was reached.
Collection boundaries
Only what the stores show publicly, signed out. No login, no cookies, no account. Reviewer fields are limited to the display name the store prints next to the review; no avatars, profile links or other personal data are collected.