Apple App Store Review Scraper
Pricing
from $2.99 / 1,000 results
Apple App Store Review Scraper
๐ Apple App Store Review Scraper pulls iOS app reviews at scale โ ratings, titles, text, version, country & timestamps. ๐ Filters by star, date, or locale; handles pagination. ๐ Export JSON/CSV or API-ready for ASO, sentiment, CX, and competitor insights. ๐
Pricing
from $2.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Apple App Store Review Scraper โ Ratings, Text and Version Data
Apple App Store Review Scraper extracts public customer reviews from any Apple App Store listing: star rating, review title, full review text, the app version reviewed, reviewer name, review ID, and the exact publish date in both local and UTC form. Paste one or more App Store links (or bare numeric app IDs), set how many reviews you want per app, and rows stream into the output table as they are collected. Product teams tracking release sentiment, competitive analysts benchmarking rival apps, and developers piping review text into an analysis pipeline use it to turn a store listing into structured JSON.
What is Apple App Store Review Scraper?
Apple App Store Review Scraper is an Apify Actor that reads Apple's public customer-review feed for any app and returns 18 fields per review as typed JSON. The storefront is selected by the two-letter country code in the URL you supply, so the same app can be collected separately per market โ the same app ID with /us/, /gb/ and /de/ produces three independent review sets.
No Apple ID, login, or developer account is required. Only data already visible on the public store listing is collected.
Key capabilities:
- Collect reviews by App Store URL or bare numeric app ID, one entry per app
- Per-storefront collection โ each two-letter country code carries its own separate review set
- Merge a second
urlslist into the primaryurllist, with automatic de-duplication - Return star rating as both Apple's original string and a parsed integer for aggregation
- Return the publish date as both Apple's local-time string and a normalized UTC ISO timestamp
- Return the app version each review was written against, for release-over-release analysis
- De-duplicate on review ID within a single run
- Export as JSON, CSV, or Excel through the Apify Console or API
What data can I extract with Apple App Store Review Scraper?
Every row is one review, carrying the review text itself, its author, the app it belongs to, and run accounting. The dataset's default view lists all 18 keys the Actor writes โ nothing is hidden behind the view; what you see in the table is the complete row.
| Field | Example Value | Use Case |
|---|---|---|
type | "review" | Separating real reviews from uncharged accounting rows |
reviewId | "11846203991" | Deduplication across runs |
appId | "324684580" | Joining reviews back to an app record |
country | "us" | Per-market segmentation |
author | "mkrentz88" | Reviewer attribution |
rating | "5" | Rating exactly as Apple's feed returns it |
ratingNumber | 5 | Rating parsed to an integer for aggregation |
version | "9.0.34" | Tying sentiment to a specific release |
title | "Finally fixed the sync bug" | Headline sentiment, short-text classification |
content | "Been using this for two years..." | Full review body for analysis and RAG |
date | "2026-07-16T05:52:31-07:00" | Apple's local publish timestamp |
dateIso | "2026-07-16T12:52:31Z" | Normalized UTC timestamp for time-series work |
reviewUrl | "https://itunes.apple.com/us/review?id=..." | Linking back to the source review |
reviewerProfileUrl | "https://itunes.apple.com/us/reviews/id..." | Reviewer history lookup |
appStoreUrl | "https://apps.apple.com/us/app/.../id324684580" | The listing the row came from |
errorReason | null | Auditing failed or blocked app URLs |
errorDetail | null | Human-readable failure detail |
scrapedAt | "2026-07-25T09:14:02Z" | Collection timestamp |
Rating and version data
rating is returned exactly as Apple's feed provides it (a string), and ratingNumber is the same value parsed to an integer, so you can aggregate without a type cast while still keeping the raw source value. version is the app build the reviewer was running when they wrote the review โ the field that makes release-over-release sentiment tracking possible. Group rows by version and you can see whether a specific build moved the average rating, instead of watching only a lifetime score that barely moves.
Date and identity data
Apple returns publish times in the storefront's local UTC offset. date preserves that string unchanged; dateIso is the same instant normalized to UTC. Both are present on every row, so a multi-storefront dataset can be placed on one timeline without you writing timezone-parsing code. dateIso returns null rather than a guessed value when the source timestamp cannot be parsed โ never fabricated. reviewId is Apple's own identifier and is what the Actor uses to de-duplicate within a run, so a review that appears on two adjacent feed pages is written once.
โ ๏ธ The 500-review ceiling you should know about
Apple's public review feed hard-stops at 500 reviews per app per storefront. The feed serves 50 reviews per page, and requesting page 11 returns HTTP 400 โ a documented, measured behavior of Apple's feed, not a limit this Actor imposes. max_review accepts values up to 10,000 and clamps to 500 with a logged warning rather than erroring, so a large value never fails your run โ it simply returns everything the storefront has to offer. max_pages behaves the same way, clamping to 10. To collect more than 500 reviews for one app, split the run across storefronts: each country code carries its own independent 500-review budget, so /us/, /gb/, /de/, and /au/ together give you up to 2,000 rows for the same app, already segmented by market.
What isn't returned, and why
Two fields that exist in Apple's raw feed payload are deliberately left out of every row, rather than being included and mostly empty:
- Helpfulness vote counts (
im:voteCount/im:voteSumin Apple's raw feed) are not emitted. The Actor reads themostrecentfeed, and a measurement recorded directly in the source found non-zero vote data on only 10 of 500 sampled reviews โ a column that is empty on roughly 98% of rows is a dead column, so it is dropped rather than shipped as a mostly-null field. - Developer responses to reviews are not returned, on any app, in any storefront. They are not present in the keyless
customerreviewsfeed this Actor reads; the endpoint that does carry developer replies (amp-api) returns HTTP 401 and exposes no token this Actor โ or any keyless scraper โ can harvest.
Both omissions are structural to the public feed itself, not a configuration choice โ no input parameter turns either one on.
Why not build this yourself?
Apple's RSS review feed is public and needs no key, which makes a first-pass scraper look trivial โ and that is exactly where the problems start. The feed interleaves non-review entries into the same array as reviews, so a naive parser that assumes every entry is a review either miscounts or crashes. It returns overlapping entries across page boundaries, so a collector without deduplication over-reports the same review twice. It stops at page 11 with an HTTP 400 rather than an empty page, which reads as a failure unless you already know it is the feed's documented ceiling. Timestamps arrive with storefront-local offsets that must be normalized before any cross-market comparison is valid, and the app ID has to be parsed out of several different URL shapes (a full listing URL or a bare numeric ID). Developer reply text is also not present anywhere in this keyless feed's payload โ the authenticated endpoint that would carry it returns 401 with no token a script can harvest, so a hand-rolled scraper that promises developer responses from this surface cannot actually deliver them.
None of these problems is individually hard. Together, they are why a hand-rolled version of this scraper tends to produce a review count โ and a field set โ that does not match what the App Store's own listing shows.
How the Actor stays reliable at scale
Every run starts with no proxy at all โ Apple's review feed is public and the direct connection succeeds for the large majority of requests. The Actor only escalates when it has to, and it escalates in a fixed order rather than retrying blindly forever:
- Each feed page gets up to five attempts on its current connection tier, with exponential backoff between attempts.
- A
404or a400on page 11 is treated as a clean, expected stop (respectively: no more reviews in this store region, or Apple's documented 500-review ceiling) โ never as a failure requiring a retry. - A
403or429response, or a request that fails outright, escalates the connection: after exhausting attempts on a direct connection, the Actor switches to an Apify residential proxy session for the rest of that app's run, then continues retrying on that tier. - If the residential tier also fails repeatedly for the same page, the app's collection for that page stops and the reason (
BLOCKEDorFETCH_FAILED) is written to the accounting row โ a single stubborn page never hangs the whole run. - Connections are capped at 8 concurrent requests, and one app raising an unexpected exception never aborts the apps queued after it; the run continues and the failure is recorded as its own accounting row.
None of this changes what you configure โ proxyConfiguration only supplies the residential proxy group Apify uses if and when escalation happens; you do not choose the tiers or retry counts yourself.
How to use Apple App Store review data
Product and QA teams
The most direct workflow: point the Actor at your own app's listing across the storefronts you ship in, set max_review to 500 to pull everything available per market, and filter the output on ratingNumber at or below 2 to build a QA triage list. Because version is on every row, you can isolate complaints that started appearing only after a specific release โ the signal that separates a pre-existing issue from a regression.
Agencies and competitive analysts
Agencies running the same collection for multiple client or competitor apps benefit from the per-storefront design: one run with several app URLs, each carrying its own country code, produces a self-contained comparison set with appId and country on every row for grouping. A recurring workflow is a monthly pull for a client's app plus two or three named competitors, tracked over time by dateIso and ratingNumber to show whether a competitor's rating is trending up or down release over release.
Market research and intelligence
For a broader read on a category, run the same input against several apps in that niche and bucket the results by ratingNumber and version to see where a category's sentiment clusters โ for example, whether a wave of one-star reviews across several competing apps in the same week points to a shared platform issue rather than an app-specific bug. content gives you the raw text to run topic extraction or keyword frequency on top of the numeric rating.
AI agents and automated pipelines
content and title are already clean strings with no HTML to strip, so they can be passed directly into an LLM prompt, embedded into a vector store for retrieval-augmented generation, or scored by a classical sentiment model. Because the Actor runs as a standard Apify Actor, any agent framework that can call the Apify API โ a custom tool definition, a scheduled job, or a webhook-triggered pipeline โ can invoke it and receive the same typed JSON a human would see in the Console.
โฌ๏ธ Input
Required per the schema: max_review. In practice, a run also needs at least one app link in url or urls โ the Actor has nothing to collect otherwise.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
max_review | Yes | integer | Maximum reviews to collect for each app. Minimum 1, maximum 10000. Apple's feed can serve at most 500 per app per storefront; larger numbers are accepted and clamped to 500 rather than rejected. Default 20. | 500 |
url | No | array | App Store listing URLs, one entry per app. A bare numeric app ID also works. The two-letter country code in the URL selects the storefront (/us/, /gb/, /jp/). | ["https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580"] |
urls | No | array | A second list of App Store links, merged with url and de-duplicated. Useful when appending apps from another source. | [] |
max_pages | No | integer | The feed returns 50 reviews per page. Apple serves at most 10 pages; higher values are clamped to 10. Lower it to stop early. Minimum 1. Default 10. | 10 |
delay_between_pages | No | integer | Pause between consecutive feed pages, in seconds, to stay polite to Apple's servers. A small random jitter is added. Minimum 0. Default 2. | 3 |
proxyConfiguration | No | object | Apify Proxy settings. The review feed is public and normally works with no proxy at all, so this is only consulted if a direct request is refused. Not a credential โ no key or token is required here. | {"useApifyProxy": false} |
On proxyConfiguration: if you leave it at the default ({"useApifyProxy": false}), the Actor still keeps a residential Apify Proxy group available as its automatic fallback tier โ see "How the Actor stays reliable at scale" below โ it is simply not used unless a direct request is refused. If you do enable Apify Proxy and specify proxy groups, those groups are used for the fallback tier instead of the default residential group. There is no separate credential to enter here; proxy access is tied to your Apify account.
Common pitfall: the schema marks max_review as the only required field, not url. It is easy to fill in a review count and press Start without pasting a single app link โ that run will resolve zero apps and exit with a log line, producing nothing. Always supply at least one app link in url or urls before starting.
Example input
{"url": ["https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580","https://apps.apple.com/gb/app/spotify-music-and-podcasts/id324684580"],"urls": [],"max_review": 500,"max_pages": 10,"delay_between_pages": 2,"proxyConfiguration": { "useApifyProxy": false }}
โฌ๏ธ Output
One row per review, the same 18 keys on every run. Values that are not available come back as null rather than a missing key, so downstream code can rely on a stable schema. Export as JSON, CSV, or Excel from the Console, or read the dataset through the Apify API.
An app URL that cannot be resolved or fetched is written as an accounting row instead of vanishing: type is set to "error", every review field is null, and errorReason plus errorDetail explain what happened. These accounting rows are never charged. The Actor charges the row_result event only inside the review-writing path โ filter on type == "review" (or, equivalently, type != "error") to work with billed rows only; the accounting rows stay in your dataset for audit purposes at no cost.
errorReason takes one of four values, each set at a distinct point in the code:
| Value | Meaning |
|---|---|
INVALID_URL | The app ID could not be parsed out of the given string โ it was neither a recognizable App Store URL nor a bare numeric ID of 5+ digits. |
FETCH_FAILED | The page could not be loaded after the retry budget was exhausted, for a reason other than being blocked (a malformed response, a timeout, a connection error). |
BLOCKED | The page returned HTTP 403 or 429 repeatedly, including after escalating to a residential proxy. |
UNEXPECTED_ERROR | Any other exception raised while processing this app; errorDetail carries the exception type and message. |
Example output
{"type": "review","reviewId": "11846203991","appId": "324684580","country": "us","author": "mkrentz88","rating": "5","ratingNumber": 5,"version": "9.0.34","title": "Finally fixed the sync bug","content": "Been using this for two years and the offline sync would drop tracks on every long flight. The 9.0.34 update seems to have sorted it โ three flights, nothing lost. Search is faster too.","date": "2026-07-16T05:52:31-07:00","dateIso": "2026-07-16T12:52:31Z","reviewUrl": "https://itunes.apple.com/us/review?id=324684580&type=Purple%20Software","reviewerProfileUrl": "https://itunes.apple.com/us/reviews/id438291047","appStoreUrl": "https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580","errorReason": null,"errorDetail": null,"scrapedAt": "2026-07-25T09:14:02Z"}
An accounting row for a failed link looks like this โ same 18 keys, review fields null, failure fields populated:
{"type": "error","appStoreUrl": "https://apps.apple.com/us/app/not-a-real-app/id000000000","appId": "000000000","country": "us","author": null,"rating": null,"ratingNumber": null,"version": null,"title": null,"content": null,"date": null,"dateIso": null,"reviewId": null,"reviewUrl": null,"reviewerProfileUrl": null,"errorReason": "FETCH_FAILED","errorDetail": "page 1 could not be loaded","scrapedAt": "2026-07-25T09:20:11Z"}
How do you filter and target specific reviews?
Apple's feed itself accepts no rating, keyword, or date filters โ every review on the page is returned, sorted by most recent. Targeting a review collection with this Actor is therefore about three real controls: which storefronts you query, how much volume you pull, and how fast you pull it.
Storefront is the main targeting axis. The country code embedded in each URL selects an independent 500-review budget, so the same app supplied three times โ once per storefront โ produces a market-segmented dataset in one run rather than one undifferentiated pool. This is the closest equivalent to a "location filter" this Actor has, and it is usually more useful than a single global set because sentiment genuinely differs by market.
Volume is controlled by two parameters that interact. max_review caps rows per app; max_pages caps how many 50-review pages are fetched before that cap is even reached. Whichever limit is hit first stops collection for that app โ set max_pages: 2 to take a fast 100-review sample without touching max_review at all, or set max_review low with a high max_pages to get an early stop the moment you have enough rows.
Pacing affects reliability at scale, not result content โ delay_between_pages (plus built-in jitter) spaces out requests to reduce the chance of a throttled response on a long multi-app run.
There is no rating, keyword, or "quality threshold" filter at collection time; anything of that kind happens after collection, against ratingNumber, dateIso, and version in the rows you already have.
{ "url": ["https://apps.apple.com/us/app/duolingo-language-lessons/id570060128"], "max_review": 20 }
A fast, low-cost sample to sanity-check the field set before committing to a large run.
{"url": ["https://apps.apple.com/us/app/duolingo-language-lessons/id570060128","https://apps.apple.com/gb/app/duolingo-language-lessons/id570060128","https://apps.apple.com/de/app/duolingo-language-lessons/id570060128"],"max_review": 500}
Three storefronts for the same app, each drained to Apple's ceiling โ a market-segmented sentiment comparison in a single run.
{"url": ["https://apps.apple.com/us/app/duolingo-language-lessons/id570060128","https://apps.apple.com/us/app/babbel-language-learning/id829587759","https://apps.apple.com/us/app/busuu-learn-languages/id379968583"],"max_review": 200,"delay_between_pages": 3}
A competitor sweep across a category, with a slightly longer delay for a longer multi-app run.
โถ๏ธ Want to try other Apple App Store scrapers?
| Scraper Name | What it extracts |
|---|---|
| Google Play Store Review Scraper | Android review text, ratings, and app versions, with developer replies |
| Goodreads Review Scraper | Book reviews with star ratings and spoiler flags |
| Reddit User Profile Posts And Comments Scraper | A Reddit user's posts and comments |
| Truth Social Scraper | Public posts and profile data |
How to extract Apple App Store review data programmatically
Apple App Store Review Scraper is a standard Apify Actor: one call in through the apify-client library, structured JSON back from the dataset. No separate signup, API key, or credential beyond your Apify token is needed.
Python example
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<YOUR_USERNAME>/apple-app-store-review-scraper").call(run_input={"url": ["https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580","https://apps.apple.com/gb/app/spotify-music-and-podcasts/id324684580",],"max_review": 500,"max_pages": 10,})reviews = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items()if r.get("type") == "review"]# average rating per app version, per storefrontfrom collections import defaultdictbuckets = defaultdict(list)for r in reviews:buckets[(r["country"], r["version"])].append(r["ratingNumber"])for (country, version), ratings in sorted(buckets.items()):print(country, version, round(sum(ratings) / len(ratings), 2), len(ratings))
Run it from the Apify Console instead if you prefer a UI: paste the same input into the Actor's input form and click Start. Filtering on type == "review" in either path separates billed review rows from uncharged accounting rows.
Export to spreadsheets or a BI tool
Export the dataset as CSV and the field names map directly onto typical destination columns: ratingNumber โ Rating, version โ Release, dateIso โ Date, content โ Review Text, country โ Market, author โ Reviewer. Because dateIso is already UTC-normalized, a pivot table across storefronts works with no timezone handling required in the spreadsheet itself.
Is it legal to scrape Apple App Store reviews?
Yes โ Apple's customer reviews are published on public listing pages specifically so prospective users can read them before installing an app, and this Actor collects only what any visitor sees without signing in: no Apple ID, no developer account, no authentication of any kind.
One caveat genuinely matters: reviews carry personal data. author is a reviewer's chosen display name, reviewerProfileUrl links to their public review history, and content can contain personal details a reviewer chose to disclose. Storing or processing that data for EU or UK data subjects requires a lawful basis under GDPR (and CCPA where California residents are involved), and ordinary data-minimization practice applies โ if your analysis only needs ratingNumber, version, and content, drop the author fields at ingestion rather than storing them by default.
Consult legal counsel for commercial applications involving bulk storage of reviewer identity data.
โ FAQ
What happens if an app has no reviews, or the link is wrong?
An app URL that cannot be resolved or fetched produces an accounting row with type: "error" and errorReason / errorDetail explaining why โ never charged, never faked. An app that genuinely has no reviews in the requested storefront simply returns no review rows: the Actor stops after two consecutive empty feed pages and logs that it reached the end of the available set, rather than erroring.
Can I get app metadata โ name, developer, price โ along with the reviews?
No. This Actor's output is reviews only; there is no app-metadata field in any row. If you need the app's own listing details, pull them from a separate source โ this Actor's scope is strictly the customer-review feed.
How accurate is the review data?
The Actor returns each review exactly as Apple's public feed reports it at request time โ the same text, rating, and version a visitor sees on the live listing. Accuracy depends entirely on Apple's feed; the Actor performs no rewriting, rounding, or inference beyond parsing the rating to an integer and normalizing the timestamp to UTC, both of which are additive fields alongside the originals, not replacements for them.
How many reviews can I get per run?
Up to 500 per app per storefront. That is Apple's own ceiling: the feed serves 50 reviews per page and returns HTTP 400 on page 11. max_review accepts values up to 10,000 in the input schema but clamps to 500 with a logged warning rather than failing the run. To exceed 500 for a single app, collect it across multiple storefronts โ each country code carries its own independent budget.
Can I filter reviews by rating or date at collection time?
No โ Apple's public feed accepts no such filters, and this Actor does not add one on top. Every available review in the requested storefront is returned, most-recent first, and you filter afterward on ratingNumber, dateIso, or version in the output. All three are typed and normalized, so post-collection filtering is a single pass over the dataset.
Can I sort by most helpful or most critical instead of most recent?
No. This Actor reads Apple's mostrecent feed only; there is no input parameter to request a different sort order, and none is applied internally. If a workflow specifically needs most-critical-first ordering, sort the returned rows by ratingNumber after collection instead.
Will I get duplicate reviews?
No. Reviews are de-duplicated on reviewId during each run, so a review that appears on two adjacent feed pages is written once. reviewId is stable across separate runs too, so deduplicating a merged historical dataset later is an exact match on that field rather than a fuzzy comparison.
Does Apple App Store Review Scraper work with Claude, ChatGPT, and AI agent frameworks?
Yes, as a standard HTTP endpoint through the Apify API โ LangChain, CrewAI, n8n, or a custom tool definition can invoke it and receive typed JSON. content and title arrive as clean strings with no HTML to strip, so they can go straight into an LLM context window or a vector store.
How does Apple App Store Review Scraper compare to other App Store review scrapers?
Checked on the Apify Store on 26 July 2026:
| This Actor | scraped/apple-app-store-review-scraper | johnvc/apple-app-store-reviews-api | jdtpnjtp/apple-app-store-scraper | |
|---|---|---|---|---|
| Pricing model | Pay per event (row_result) | Flat monthly price | Pay per event | Pay per event |
| Documents the 500-review ceiling | Yes, in the input description and README | Yes, briefly, in the README | Not documented on the reviewed page | Advertises "Unlimited Reviews โ No 500-review cap" |
| Failed-URL handling | Uncharged accounting row with errorReason / errorDetail | Not documented | Warns in the log, stops cleanly, charges only what was already returned | Not documented |
| Sort order options | mostrecent only | Not documented | mostrecent, mosthelpful, mostfavorable, mostcritical | Not documented as a parameter |
| Developer reply text | Not returned (not present in this feed's payload) | Not documented | Not returned โ stated as unavailable from their data source | Advertised as "Developer Responses Included" |
| Field count per review row | 18, including raw and normalized rating/date | Not documented (README lists no fields) | 14+ documented fields including parsed helpfulness counts | Documented output includes a nested developerResponse object |
The two claims worth flagging: jdtpnjtp/apple-app-store-scraper's listing advertises both an uncapped review count and included developer responses. This Actor's own source-level testing found the opposite on both points for the public, keyless feed this class of scraper reads โ a hard 500-per-storefront ceiling (page 11 returns HTTP 400) and no developer-reply text anywhere in that feed's payload (the endpoint that carries replies requires an authenticated token this surface cannot obtain). This Actor documents both constraints rather than advertising past them.
What happens if I paste a bare numeric app ID instead of a full URL?
It works, but the storefront defaults to the US store. The Actor accepts a bare numeric ID of 5 or more digits in place of a full App Store URL, and app IDs are the same across every storefront โ but the country code that selects the storefront is normally read from the URL itself (/us/, /gb/, /de/). A bare ID carries no such code, so the country defaults to us rather than failing. If you need a non-US storefront, paste the full listing URL for that country instead of just the numeric ID.
Can I use Apple App Store Review Scraper without an Apple developer account or API key?
Yes. No Apple ID, no App Store Connect account, no Apple API key of any kind โ Apple's review feed is public. The only credential you need is your own Apify account and token to run the Actor.
Conclusion
Apple App Store Review Scraper turns any App Store listing into a clean, typed review dataset โ rating, full text, version, and an exact UTC timestamp โ with per-storefront collection and no Apple credentials required. It is built for product teams measuring sentiment against a specific release, competitive analysts benchmarking rival apps market by market, and developers who need review text in a form an LLM can read without preprocessing. Apple's 500-per-storefront ceiling is documented rather than hidden, and failed URLs are accounted for with an uncharged row rather than silently dropped. Open Apple App Store Review Scraper on Apify and run your first collection with a single app link.