App Store Reviews Scraper & App Search API
Pricing
from $0.10 / 1,000 reviews
App Store Reviews Scraper & App Search API
Apple App Store reviews and app search with a live Standby HTTP API, so an AI agent can pull reviews mid-task with no cold start. Clean, LLM-ready JSON: rating, title, text, app version, helpful votes, date. Any storefront, no tokens to rotate. No start fee, pay only for results.
Pricing
from $0.10 / 1,000 reviews
Rating
0.0
(0)
Developer
Omar Nagy
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
9 days ago
Last modified
Categories
Share
Pull Apple App Store reviews and search the App Store at speed, with clean, LLM-ready JSON. Built for AI agents, review-monitoring pipelines, and product teams who need real user feedback in a structured shape.
Two things make this one different: it runs in Standby mode, so an agent can call a live HTTP endpoint mid-task with no cold start, and it reads Apple's own public feeds, so there is no token to rotate, nothing to unblock, and no proxy bill.
What you get
- Reviews by app: star rating, review title, review text, app version, helpful votes, timestamp, and a permalink.
- App search: find an app's numeric App Store ID, plus developer, average rating, rating count, price, genre, and icon.
- Any storefront:
countryselects the store, and reviews differ per store, sous,gb,deandegeach return their own. - Standby HTTP API: a persistent endpoint your agent or app can hit directly.
- MCP ready: exposed as a typed tool through Apify's MCP server via the input schema.
- No dead columns: every field in the output is a field Apple actually serves. Measured on 5 September 2026: 100 of 100 reviews carried a title.
Use cases
- Watch what users say after each iOS release, and catch a crash wave before the support queue fills up.
- Compare the same app across storefronts, which is the fastest read on a localisation problem.
- Feed competitor reviews into an LLM for feature-gap and pain-point analysis.
- Give an AI agent a live tool that answers "what are people complaining about in this app right now".
- Collect training or RAG data from real, public product feedback.
Modes
| Mode | You give it | You get back |
|---|---|---|
search | query (app name or keyword) | matching apps with their numeric App Store IDs |
reviews | appIds (numeric IDs) | reviews, paginated up to maxItems |
Start with search to get an ID, then run reviews on it. reviews and search are the only two accepted modes, lowercase and exact.
Input
Find an app:
{"mode": "search","query": "notion","country": "us","maxItems": 5}
Pull its reviews:
{"mode": "reviews","appIds": ["310633997"],"country": "us","maxItems": 100,"sortBy": "mostRecent"}
Compare three apps in one run. maxItems is the budget for the whole run and is
split evenly, so this returns 30 reviews of each, not 90 of the first one:
{"mode": "reviews","appIds": ["324684580", "544007664", "310633997"],"country": "us","maxItems": 90}
| Field | Type | Default | Notes |
|---|---|---|---|
mode | reviews or search | reviews | required. Any other value is rejected before anything is fetched. |
appIds | array of strings | numeric App Store IDs, for example 310633997. Required when mode is reviews. Ignored in search. | |
query | string | app name or keyword. Required when mode is search. Ignored in reviews. | |
country | 2-letter code | us | App Store storefront |
maxItems | integer 1 to 5000 | 100 | budget for the whole run, split evenly across appIds. 100 across 3 apps is 34 / 33 / 33. |
maxItemsPerApp | integer 1 to 5000 | optional. When set, every app gets exactly this many and the even split is ignored, so 3 apps at 50 return up to 150 rows. | |
sortBy | mostRecent, mostHelpful | mostRecent | review order, reviews mode only |
A run that asks for reviews without appIds, or search without query, fails immediately with a clear input error and returns nothing, so a misconfigured run costs you nothing.
Output
Real output from runs on 5 September 2026. Larger samples of both are in the examples/ folder of the source.
App search:
{"type": "app","appId": 1232780281,"bundleId": "notion.id","name": "Notion: Notes, Tasks, AI","developer": "Notion Labs, Incorporated","rating": 4.77668,"ratingCount": 89975,"price": "Free","genre": "Productivity","url": "https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281?uo=4","icon": "https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/2e/aa/40/2eaa406d-99e0-e722-530a-ce20259f3834/AppIconProd-0-0-1x_U007epad-0-0-0-1-0-0-P3-85-220.png/100x100bb.jpg"}
A review:
{"type": "review","appId": "310633997","country": "us","reviewId": "14505487796","author": "Barirah Ibrahim","rating": 1,"title": "Terrible","text": "Keeps of restricting my account for no reason, usually I get my account back after a few hours but this time it's been 5 days. I still can't login!!!","version": "26.34.72","votesHelpful": 0,"votesTotal": 0,"updatedAt": "2026-09-03T05:29:13-07:00","url": "https://itunes.apple.com/us/reviews/id1964520100"}
Example run
Input: the two blocks above. Output on 5 September 2026: 100 reviews for 310633997 in about 1 second, and 5 apps for the notion search. Every one of the 100 reviews had a non-empty title and text.
Use it from an agent (Standby)
Standby keeps the Actor warm and answers over plain HTTP, so there is no per-call container start.
GET {standbyUrl}/search?query=notion&country=us&maxItems=5GET {standbyUrl}/reviews?appId=310633997&country=us&maxItems=50&sortBy=mostRecent
Every successful response is:
{"ok": true,"count": 90,"perApp": [{ "appId": "324684580", "requested": 30, "fetched": 30, "charged": 30, "error": null },{ "appId": "544007664", "requested": 30, "fetched": 30, "charged": 30, "error": null },{ "appId": "310633997", "requested": 30, "fetched": 30, "charged": 30, "error": null }],"items": [ ... ],"tookMs": 2410}
The numbers above show the shape of a three-app call at maxItems: 90, not a
recording of one particular request.
perApp is the run's own accounting: what each app was allotted, what it returned,
and what it was billed. An app id that cannot be read gets an error string and
charged: 0 while the rest of the call keeps its full budget, so one bad id does
not fail the request.
GET {standbyUrl}/ returns a small service document with the modes and the running build number.
appId (singular) is accepted as a convenience alongside a comma-separated appIds.
Errors are typed, so an agent knows whether to retry
| Status | When | Body |
|---|---|---|
404 | the path is not /reviews or /search, for example /foobar, /REVIEWS, /v1/reviews | { "ok": false, "error": "...", "statusCode": 404, "modes": ["reviews","search"] } |
400 | the path is valid but the parameters are not, for example /reviews with no appId | same shape, statusCode: 400 |
500 | an upstream failure | same shape |
404 and 400 mean "fix the call", not "try again". Neither fetches any data, so neither returns anything billable.
Good to know
- App IDs are numeric, for example
310633997for WhatsApp Messenger. Get them frommode: "search", or read them off the end of an App Store URL. - Reviews are per storefront. The same app returns a different set in
usand inde. There is no global feed. - Apple's paging has holes, and this Actor reads through them. The feed serves up to 10 pages of about 50 reviews, but an individual page can come back empty while later pages are full, and which pages are empty moves over minutes. One 10-page sweep of
389801252on 6 September 2026 read[0, 50, 50, 50, 50, 50, 50, 0, 0, 50], and re-reading an empty page URL five times a second apart returned 0 every time, so an in-run retry buys nothing. This Actor therefore reads every one of the 10 pages until your budget is full: a run of empty pages, however long, never ends the pull early. It can still return fewer rows than the app really has, if Apple serves those pages empty for the whole run. Results are de-duplicated by review ID. - The practical ceiling is roughly 500 reviews per app and storefront, which is what Apple exposes. Ask for more across several storefronts if you need more.
maxItemsis split evenly acrossappIds. Three apps atmaxItems: 90return 30 each, and an app that runs out early leaves its remainder unspent rather than handing it to the next app, so no app can spend another app's budget. SetmaxItemsPerAppwhen you want a fixed number each regardless of how many apps you list. (Until 6 September 2026 the first app in the list took the whole budget and the rest returned nothing. That is fixed.)- Per-app accounting is in the run. Every batch run writes a summary to the key-value store as
OUTPUT, including amode: searchrun where the per-app list is empty, and logs one[app] <id> requested=N fetched=N charged=Nline per app. Standby answers over HTTP and does not write to the key-value store: it returns the same breakdown asperAppin the response body instead. - Reviews are public data published by users on the App Store. Respect Apple's terms and any applicable privacy law in how you store and use it.
Parity with the Google Play Actor
There is a sibling Actor, Google Play Reviews Scraper & App Search API, with the same two modes, the same Standby routes, the same error shapes and the same pay-per-event model. Input is the same except for two fields, and the review record maps field for field with five differences. Every difference below is a difference in what the two stores publish, not a difference in style.
Input:
| Field | App Store | Google Play |
|---|---|---|
mode, appIds, appId, query, country, maxItems, maxItemsPerApp | same | same |
| review order | sortBy: mostRecent, mostHelpful | sort: newest, rating, helpfulness |
| review language | not accepted, Apple serves per storefront only | lang |
Review output:
| What it means | App Store | Google Play |
|---|---|---|
| record kind | type | type |
| app identifier | appId (numeric, 310633997) | appId (package name, com.whatsapp) |
| storefront | country | country |
| review id | reviewId | reviewId |
| author display name | author | author |
| stars, 1 to 5 | rating | rating |
| review body | text | text |
| app version | version | version |
| permalink | url | url |
| when it was posted | updatedAt | date |
| review language | not served | lang |
| helpfulness | votesHelpful and votesTotal | thumbsUp |
| headline | title | not served |
| developer reply | not served | replyText, replyDate |
The five differences, each measured rather than assumed:
- Timestamp name. Apple's customer-reviews feed names its only time field
updated, so this Actor exposesupdatedAt. Google Play carries a review date, exposed there asdate. - Language. A live Apple feed entry carries exactly these keys:
author,content,id,im:contentType,im:rating,im:version,im:voteCount,im:voteSum,link,title,updated(read 6 September 2026, storefrontus, app324684580, 50 entries). There is no language key, so there is nothing to expose. - Helpfulness. Apple gives two numbers, a sum and a count, exposed as
votesHelpfulandvotesTotal. Google Play gives one,thumbsUp. - Headline. Apple serves a review
title. Google Play no longer does: zero of 1,200 reviews across 8 apps carried one on 5 September 2026, so that field is absent there. - Developer reply. Apple's feed has no reply key at all (see the key list in point 2). Google Play serves one and it is common there (111 of 150 reviews on Adobe Scan, measured 5 September 2026).
One behavioural difference worth knowing when you compare depth: Apple serves up to 10 fixed pages and an individual page can come back empty while later pages are full, which this Actor skips rather than treating as the end. Google Play pages with a continuation token until it runs out.
Pricing
You pay for results, not for time. There is no start fee, and nothing is charged for a run that returns nothing.
- review: one App Store review row returned, in batch mode or through Standby.
- app: one app record returned by a search.
A 1,000-review pull is charged as 1,000 review events. Finding an app costs a handful of app events. Current rates are on the Pricing tab of this page.
FAQ
How do I find an app's ID?
Run mode: "search" with the app name. The appId in the output is the numeric ID.
Can I get every review an app ever received? No. Apple exposes a recent window per storefront, around 500 reviews. Pull the same app from several storefronts for a wider picture, or run it on a schedule and accumulate.
Does it need a proxy? No. It reads Apple's public feeds directly.
Can I run it on a schedule? Yes. Use Apify's scheduler, or call the Standby endpoint from your own job.
Do you support Google Play too? Yes, in a separate Actor in the same series.
Built by Omar Nagy. Part of an agent-native data-tool series on Apify.