App Store & Google Play Reviews Scraper avatar

App Store & Google Play Reviews Scraper

Pricing

from $0.15 / 1,000 delivered reviews

Go to Apify Store
App Store & Google Play Reviews Scraper

App Store & Google Play Reviews Scraper

Scrape Apple App Store and Google Play reviews into one schema, with incremental `since` sync and optional lexicon sentiment.

Pricing

from $0.15 / 1,000 delivered reviews

Rating

0.0

(0)

Developer

David Brooks

David Brooks

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

11 hours ago

Last modified

Share

Both mobile stores, one review schema, one price — with the Apple 500-per-storefront cap explained instead of hidden.

This App Store Reviews Scraper and Google Play Reviews Scraper pulls app reviews from Apple and Google into a single flat schema, so an iOS and an Android app can be compared side by side without reconciling two exports. Every row carries the rating, title, body, app version, developer reply, helpful votes, storefront, language and posting date, plus a stable review id for deduplication. Pass numeric App Store ids, Android package names, or store URLs and the store is detected for you. Use since for incremental runs that stop as soon as they reach reviews you already have, and turn on sentiment for a positive/neutral/negative label with topic keywords.

What you get

  • Both stores in one run: apps: ["284882215", "com.spotify.music"] returns one dataset with identical keys
  • Every row is proven to belong to the app you asked for — Apple rows are checked against the feed's own id and each review's permalink, and any row pointing elsewhere is dropped rather than delivered
  • Developer replies and reply dates from Google Play, quality sub-ratings (battery, performance, ads) where Google collects them
  • since incremental sync: a scheduled run stops at the first review older than your cutoff, so you pay for new reviews only
  • countries: ["all"] walks all 115 App Store storefronts in one run, deduplicating by review id — the supported way past Apple's 500-per-storefront ceiling
  • Optional lexicon sentiment label plus up to three topic keys per review — deterministic, no LLM, no API key
  • Reviewer names off by default; schemaVersion on every row so keys never change under you

Sample row:

{
"schemaVersion": 1,
"sourceId": "google-play:us:04d72efa-9805-4abf-bb76-5958628b868f",
"sourceUrl": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=04d72efa-9805-4abf-bb76-5958628b868f",
"source": "google-play",
"subjectId": "com.spotify.music",
"subjectName": "Spotify: Music and Podcasts",
"country": "US",
"language": "en",
"rating": 3,
"title": null,
"body": "Good catalogue but the ads between every song are too much.",
"author": null,
"version": "9.1.80.2221",
"publishedAt": "2026-09-13T15:41:22.000Z",
"developerReply": "Hey! We hear you and we'll pass your feedback along to the Ads team.",
"developerReplyAt": "2026-09-13T19:27:18.000Z",
"helpfulVotes": 0,
"totalVotes": null,
"subRatings": "{\"ads_frequency\":2,\"visual_appeal\":1}",
"sentiment": "negative",
"sentimentTopics": [
"ads",
"price"
]
}

Input

FieldDescription
appsApple numeric ids (284882215), Android packages (com.spotify.music), or store URLs. Mixed lists are fine.
storeauto (default), apple or google — force detection when an id is ambiguous
countriesTwo-letter storefront/country codes, default ["us"], or ["all"] to walk all 115 App Store storefronts
languageGoogle Play hl code for review text and the app title (default en)
sortrecent (default), helpful, or rating
sinceISO date; stop paging at reviews older than this. Makes scheduled runs incremental.
includeAuthorInclude the reviewer's display name. Off by default — personal data.
sentimentAdd a lexicon sentiment label and topic keys. Charged per scored review.
maxItemsHard cap on delivered reviews (default 100)
maxCostUsdHard stop on spend, enforced before each request

Pricing

Pay per event. You are charged only for delivered, validated results — never for empty pages, blocked requests, or duplicates. maxCostUsd is a hard stop enforced before each request.

EventPriceUnit
run-start$0.001per run — charged only once the run delivers its first row
review$0.00015per delivered review — $0.15 per 1,000
sentiment$0.0008per scored review — only when sentiment is enabled
  • 10,000 reviews across both stores ≈ $1.50
  • A daily 200-review incremental monitor ≈ $0.93/month
  • 1,000 reviews with sentiment ≈ $0.95

Why this actor

  • Delivering a review from the wrong app is structurally impossible on the Apple side: the feed's own id and each review's permalink are both checked against the app you requested, and a whole response that belongs to another app fails the run instead of filling your dataset
  • Apple's feed intermittently answers HTTP 200 with no reviews at all; a scraper that treats that as the end of the data silently returns a fraction of what exists. Empty pages are retried, and one empty page never ends a fan-out that still has pages behind it
  • The 500-review ceiling is a platform limit, not a bug, and it is documented here with the storefront fan-out that gets you past it — rather than surfacing as an unexplained cap of 10 or 99 results
  • One schema for both stores, versioned with schemaVersion, so output keys do not change between runs
  • Caps are enforced before the request that would breach them, and you are charged only for validated rows that reach your dataset
  • A run that is blocked or finds nothing costs nothing at all, run-start included

Known limits

  • Apple serves at most 10 pages of 50 reviews for each storefront and sort, so 500 reviews per storefront per sort is a hard ceiling (page 11 answers HTTP 400). To go further, list more countries or pass ["all"] for all 115 storefronts: each has its own 500. The actor also fans out across both of Apple's sorts and deduplicates by review id.
  • countries: ["all"] fans out App Store apps only. Google Play does not partition reviews by storefront the way Apple does, and each Play country costs a large details fetch, so Play uses the country codes you list explicitly, or us.
  • Google Play pagination stops at 200 pages per app and storefront (20,000 reviews), and stops early if Google repeats a continuation token or two pages in a row bring nothing new.
  • Apple's public feed carries no developer replies, so developerReply and developerReplyAt are always null for App Store rows. Google Play rows do carry them.
  • Apple has no rating-sorted feed; sort: "rating" falls back to newest first for App Store apps and is applied normally on Google Play.
  • Setting since forces newest-first ordering on both stores, because that is the only ordering in which stopping early is correct.
  • Sentiment is a keyword lexicon with negation handling, not a language model, and the sentiment event is priced as a convenience add-on rather than as model inference passed through at cost. It falls back to the star rating when a review contains no lexicon term. It is accurate on plain review prose and will miss sarcasm. Leave sentiment off and pay nothing for it if you would rather score the text yourself.
  • On the default flat output, Google Play sub-ratings are one JSON-string column named subRatings (null when a review has none), so every row has the same columns; the sample row above shows that shape. With outputFormat: nested it is an object.
  • Google Play rows are attributed to the package id you requested: Google's review payload and continuation token do not repeat the package id, so unlike the App Store (where the feed id and each entry's app link are checked) there is nothing in the response to cross-check it against.
  • Google Play review rows carry no title (the store has no title field) and Apple rows carry no per-review permalink, so sourceUrl is the app page for App Store rows.
  • Neither store needs a proxy for small runs. Google Play throttles per IP after a few hundred pages — switch on the datacenter Apify Proxy for large Play pulls.
  • When Apple's feed is having an outage, meaning a storefront answers every page with HTTP 200 and no usable reviews (no entries at all, or entries that arrive without an app id in their link), that storefront is listed in meta.appleFeedEmpty with a warning. The run ends with a PARSE ERROR, and nothing is charged, only when no review was delivered from any storefront or store; otherwise it succeeds with what it found. A storefront whose lookup reports 0 ratings is not an outage: that app simply has no reviews, and the run succeeds empty and free.

Use from an AI agent (MCP)

Add the actor as an MCP tool in Claude Desktop / Cursor via the Apify MCP server:

{ "mcpServers": { "app-reviews": { "url": "https://mcp.apify.com?actors=<your-username>/app-reviews", "headers": { "Authorization": "Bearer <APIFY_TOKEN>" } } } }

The tool accepts exactly the input fields above and returns the same rows, so an agent can ask for "the last 200 one-star reviews of com.spotify.music in the US" in one call.

Use from n8n / Make

Use the Apify node → "Run actor" with actor <your-username>/app-reviews and a JSON input such as {"apps":["284882215","com.facebook.katana"],"countries":["us","gb"],"since":"2026-09-01","sentiment":true,"maxItems":1000} on a daily schedule, then "Get dataset items" and route negative rows to Slack.

FAQ

Why do I only get 500 reviews per app from the App Store?

Apple's public review feed stops at 10 pages of 50 per storefront and sort; page 11 returns HTTP 400 for every app. Add more entries to countries, or pass ["all"] to walk all 115 storefronts, and the actor deduplicates by review id across every one of them.

What happens if a run is blocked or the app has no reviews?

You are charged nothing, including the run-start fee, which is only applied once the run delivers its first row. A blocked run fails with a typed error rather than reporting success with an empty dataset.

Why is developerReply empty for my iOS app?

Apple does not expose developer replies anywhere in the public feed. Google Play does, and those rows are populated.

How do I run this incrementally?

Set since to the timestamp of your last run. Paging stops at the first review older than that, so a daily run charges only for new reviews.

Does the sentiment option call an LLM?

No. It is a deterministic keyword lexicon with negation handling, so the same text always gets the same label and there is no API key to supply.

Do I need a proxy?

Not for small runs. Google Play starts throttling per IP after a few hundred pages, so enable the datacenter Apify Proxy for large Play pulls. Residential is never required.

This actor reads publicly published app reviews from Apple's open RSS feed and Google Play's public store pages. It never logs in, never uses accounts or cookies from accounts, and never solves a CAPTCHA. Reviewer display names are personal data under GDPR and CCPA, so includeAuthor is false by default and no reviewer avatar, profile URL or numeric reviewer id is ever emitted unless you switch it on and have a lawful basis for doing so. Review text is the reviewer's copyrighted expression: it is delivered to you for your own analysis, and we neither rehost it nor build or resell a corpus. Request rates are kept modest, 429 responses are honoured with backoff, and a blocked run fails with a typed error rather than quietly returning nothing.

Support

Open an issue on the Issues tab; first response within 6 hours on business days. Every run writes a RUN_SUMMARY record to the key-value store with items delivered, events charged, and the stop reason.