App Store Scraper — App Details & Reviews API avatar

App Store Scraper — App Details & Reviews API

Pricing

from $2.00 / 1,000 apps

Go to Apify Store
App Store Scraper — App Details & Reviews API

App Store Scraper — App Details & Reviews API

Search or look up any app on the iOS/macOS App Store and get its full details (price, rating, version, description, screenshots) plus its most recent customer reviews, straight from Apple's own public APIs. You only pay per app and per review delivered.

Pricing

from $2.00 / 1,000 apps

Rating

0.0

(0)

Developer

Plainfetch Studio

Plainfetch Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Search or look up any app on the iOS/macOS App Store and get back its full details — price, rating, version history, description, screenshots — plus its most recent customer reviews, without touching a browser. App Store Scraper is an App Store API alternative built directly on Apple's own official, public APIs: the iTunes Search API, the Lookup API, and the customer-reviews feed. Give it search terms or app ids and get one dataset item per app, plus one item per review, ready to filter, sort, or feed into another tool.

What can you do with it?

  • ASO and competitor research. Pull a competitor's rating, price, category, description and screenshot set, or run a search term the way a shopper would and see exactly which apps rank for it.
  • Monitor app ratings and releases. Track rating, ratingCount and version/updatedAt for a list of apps over time — run it on a schedule and diff the results to catch a new release or a rating drop.
  • Review mining for product feedback. Fetch an app's most recent reviews to spot recurring complaints, feature requests, or praise — rating, title and text for every review, in the language reviewers actually wrote it in.
  • Feed AI agents and downstream tools. Call this Actor from the Apify API, an integration, or an MCP-connected AI agent so it can look up an app's details or read its reviews as one step in a larger workflow.

What data do you get?

Each run produces two kinds of dataset item, distinguished by type.

One app item per app:

FieldTypeDescription
name / titlestringThe app's name (title is a duplicate of name, kept for consistency with review items).
developerstring | nullThe developer/seller name, e.g. "Duolingo".
price / currencynumber | null0 for a free app; isFree is true/false derived from it.
rating / ratingCountnumber | nullThe app's overall App Store rating and how many ratings it has.
version / updatedAtstring | nullThe current version and when it was released.
descriptionstring | nullThe full App Store description.
genres / primaryGenrestring[] / string | nullThe App Store category (or categories) the app is listed under.
screenshotsstring[]Screenshot image URLs, straight from Apple.
urlstring | nullThe app's App Store page.
reviewsCompleteboolean | nullWhether this app's reviews (if requested) were fetched in full — null if reviews weren't requested. See below.
reviewsIncompleteReason / reviewsErrorstring | null / object | nullWhy reviewsComplete is false — see below.
errorobject | nullSet when a requested search term or app id could not be delivered — see Limitations.

Every requested search term or app id leaves exactly one row — never silently dropped. A term or id skipped entirely, before it was ever attempted, still gets its own app row with every other field blank, and is never charged. The two reasons it can be skipped read differently, on purpose:

  • Your spending cap was already reached — your own limit doing exactly what you set it to do, not a failure of this Actor. That row carries no error at all: it says reviewsIncompleteReason: "spending-cap-reached" (with reviewsComplete: false, since nothing was read for it, its reviews included) and counts as delivered in the run summary.
  • This Actor's circuit breaker had already tripped (three blocked or rate-limited answers in a row) — the source would not have answered any further, so that row carries a clear error and counts as failed.

One review item per review:

FieldTypeDescription
ratingnumber | null1 to 5.
titlestringThe review's title.
textstring | nullThe review's body text.
versionstring | nullThe app version the reviewer was using.
datestring | nullWhen the review was posted.
appIdstringWhich app this review is for.

This Actor never emits who wrote a review. No reviewer nickname, no reviewer profile URL, no author field of any kind — only what they rated and wrote. See Limitations.

An app's reviews can end up incomplete, and the app row says so honestly. With includeReviews: true, reviewsComplete: true means one thing: every review there was to get was got — the feed ran out, or Apple's own 10-page ceiling was reached, which is all Apple publishes. reviewsComplete: false means reviews were left unread, and reviewsIncompleteReason says why: "max-reviews-reached" (your own maxReviewsPerApp stopped the read — not a failure, and everything fetched is still charged), "interrupted" (a network or blocked error, with the detail in reviewsError), or "spending-cap-reached". The app row itself is always delivered either way; only its reviews may be incomplete. Every review already fetched before the cutoff is still in the dataset and still charged.

What real output looks like

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. Here is real output from a run with

{"searchTerms": ["duolingo"], "maxAppsPerSearch": 1, "includeReviews": true, "maxReviewsPerApp": 2}
, trimmed for readability: two of the app's real reviews are shown below, with their real, unedited title/text — one of the app's real reviews at the time of writing used stylised Unicode lettering that renders poorly in a code block, so a plainer real review is shown instead of it; only the choice of which reviews to display is trimmed, never a review's own text. The app row's description, releaseNotes, screenshots and languages are also shortened here (the real item carries the app's full description and release notes, its complete screenshot set, and all 32 supported languages). One more field is not a literal capture either: the app row's reviewsComplete: false and reviewsIncompleteReason: "max-reviews-reached" are derived from this Actor's own logic for maxReviewsPerApp: 2 against an app with far more reviews than that — the same values the code produces for real, not copied verbatim from one specific run and not hand-edited. Reviews are fetched (and appear in the dataset) before the app row they belong to — that is what lets the app row report reviewsComplete honestly instead of guessing:

[
{
"type": "review",
"appId": "570060128",
"reviewId": "14566250893",
"rating": 2,
"title": "Loot chest are terrible",
"text": "Stop forcing me to tap repeatedly for a chest. I don’t care about what is in it. It is just annoying trash that gets in the way of learning",
"version": "7.140.0",
"date": "2026-09-18T17:24:18-07:00",
"country": "us"
},
{
"type": "review",
"appId": "570060128",
"reviewId": "14566216737",
"rating": 5,
"title": "Good app",
"text": "I love Duolingo but I wish they did gettar",
"version": "7.140.0",
"date": "2026-09-18T17:11:09-07:00",
"country": "us"
},
{
"type": "app",
"appId": "570060128",
"bundleId": "com.duolingo.DuolingoMobile",
"name": "Duolingo: Language Lessons",
"title": "Duolingo: Language Lessons",
"developer": "Duolingo",
"developerId": "570060151",
"url": "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128?uo=4",
"iconUrl": "https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/c7/ee/1d/c7ee1d8c-9928-98bf-318a-0713e0351998/AppIcon-0-0-1x_U007epad-0-1-85-220.png/512x512bb.jpg",
"price": 0,
"currency": "USD",
"isFree": true,
"rating": 4.7232,
"ratingCount": 5456627,
"ratingCurrentVersion": 4.7232,
"version": "7.140.0",
"releasedAt": "2012-11-13T08:00:00Z",
"updatedAt": "2026-09-14T15:53:43Z",
"releaseNotes": "Our mascot owl, Duo, is trading in his usual diet of mice for bugs this week...",
"description": "Learn a new language, chess & more with the world's most downloaded education app!...",
"genres": ["Education", "Social Networking"],
"primaryGenre": "Education",
"contentRating": "4+",
"sizeBytes": 515881984,
"minimumOsVersion": "17.0",
"languages": ["AR", "BN", "CS", "NL", "EN", "FR", "DE"],
"screenshots": [
"https://is1-ssl.mzstatic.com/image/thumb/PurpleSource211/v4/6e/ef/30/6eef3023-de04-3b29-21f8-a993245b9abd/iPhone6.5_-_Default_-_first_screen_adapt_Var_2_01.jpg/320x480bb.jpg"
],
"country": "us",
"searchTerm": "duolingo",
"reviewsComplete": false,
"reviewsIncompleteReason": "max-reviews-reached",
"reviewsError": null,
"error": null
}
]

reviewsComplete: false here because the read stopped at maxReviewsPerApp: 2 while this app still had millions of reviews available — nothing went wrong, and both reviews are delivered and charged; incompleteReason just tells you it is not the whole feed.

How much does it cost?

You pay $0.002 per app delivered and $0.0005 per review delivered. A search term or app id that fails — not found, blocked, or a network error — is never charged. No start fee.

RunCost
5 apps, no reviews5 × $0.002 = $0.01
5 apps, 50 reviews each5 × $0.002 + 250 × $0.0005 = $0.135
20 apps, 100 reviews each20 × $0.002 + 2,000 × $0.0005 = $1.04

Real example: the run above (

{"searchTerms": ["duolingo"], "maxAppsPerSearch": 1, "includeReviews": true, "maxReviewsPerApp": 2}
) delivered 1 app and 2 reviews, for $0.003.

Input

See the Input tab for the full configuration. The minimal input is one search term or one app id:

{
"searchTerms": ["duolingo"]
}
  • searchTerms / appIds — provide at least one of either. appIds accepts a numeric App Store id ("570060128" or 570060128) or an App Store URL containing one ("https://apps.apple.com/us/app/duolingo/id570060128"). Duplicate entries are processed once: the same id listed twice is looked up once, and an app found by both a search term and an explicit id is delivered — and charged — once.
  • country (optional, default "us") — two-letter App Store storefront code, e.g. "gb", "de". Controls which country's catalogue, pricing and reviews are read.
  • maxAppsPerSearch (optional, default 50, 1 to 200) — how many apps to fetch per search term.
  • includeReviews (optional, default false) — also fetch each app's most recent reviews.
  • maxReviewsPerApp (optional, default 100, 0 to 500) — how many of the most recent reviews to fetch per app. Ignored when includeReviews is off.
  • requestDelayMs (optional, default 250) — courtesy pause before each request to Apple's APIs.

Limitations — read this first

This Actor never returns reviewer names. Apple's customer-reviews feed includes a reviewer nickname and profile URL for every review; this Actor drops both before anything else touches the response. No review item ever carries an author, nickname, or profile URI, no matter what Apple's feed includes.

Apple exposes at most 500 of the most recent reviews per app per country (10 pages of 50) — this is a hard ceiling of Apple's own feed, not a limit this Actor imposes; maxReviewsPerApp cannot get you more. The Search API returns at most 200 apps per search term. Apple rate-limits the Search API to roughly 20 calls per minute per IP address by its own documentation — the default requestDelayMs (250ms) and the built-in concurrency cap (5) are deliberately gentle to respect that; raising them risks a rate-limited or blocked response, which this Actor never attempts to get around (no proxy rotation, no fingerprint spoofing, no CAPTCHA solving). Three consecutive blocked or rate-limited responses stop the run entirely, with a clear message in the log — and a search term or app id skipped that way, or by your own spending cap, still leaves its own uncharged app row instead of vanishing.

iOS/macOS App Store only — not Google Play. This Actor reads Apple's App Store APIs exclusively; it does not cover Android or the Google Play Store.

FAQ

Is this legal? We can't give you legal advice, but here is exactly what the Actor does: it calls Apple's own public, documented APIs — the iTunes Search API, the Lookup API, and the customer-reviews feed — the same data these APIs return to any client that asks. It does not log in, does not get around any block, and never emits a reviewer's name or profile. You are responsible for the search terms and app ids you submit and for how you use the results.

Where does the data come from? Directly from itunes.apple.com's public Search, Lookup and customer-reviews endpoints — no third-party database, no cache.

How do I use this from the API or an AI agent (MCP)? Call it like any other Apify Actor: via the Apify API, the JavaScript or Python client, an integration, or an MCP-connected AI agent that has access to your Apify Actors. Pass the same searchTerms/appIds input and read the results back from the default dataset.

What happens if I hit my spending cap? The run stops cleanly: it finishes the app or review already being processed, writes everything it has, and reports chargeLimitReached: true in the run summary. Nothing already produced is lost, and nothing beyond the cap is charged.

Changelog

23 September 2026 — A search term or app id skipped because your spending cap was already reached no longer carries an error. That row used to be delivered with error: {category: "other", message: "Skipped: the spending limit for this run was reached."}; it now carries error: null, says why in reviewsIncompleteReason: "spending-cap-reached" (with reviewsComplete: false), and still counts as delivered and is still never charged. Your own limit is not a failure of this Actor, and error now means one thing only: this row could not be delivered. A row skipped because the Actor's circuit breaker tripped is unchanged — it still carries an error. If you filter rows on error !== null to spot cap-skipped units, filter on reviewsIncompleteReason === "spending-cap-reached" instead.

0.1 — Initial release.