Apple App Store Reviews Scraper: iOS App Reviews, No Login avatar

Apple App Store Reviews Scraper: iOS App Reviews, No Login

Pricing

from $0.08 / 1,000 reviews

Go to Apify Store
Apple App Store Reviews Scraper: iOS App Reviews, No Login

Apple App Store Reviews Scraper: iOS App Reviews, No Login

Scrape Apple App Store reviews by app URL or id and country: rating, title, text, app version, reviewer nickname, date, helpful votes and review id, newest first or most helpful. Several apps and countries per run, a cap per app, a free app row with its rating and a completeness verdict.

Pricing

from $0.08 / 1,000 reviews

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Apple App Store reviews by app and country, logged out: App Store URLs or app ids in, one row per review out — the star rating, title, text, the app version the reviewer used, the reviewer's nickname and profile link, the date, the helpful votes and the review id — newest first or most helpful first, several apps and countries in one run, a cap per app. One free app row per app and country carries the app's name, developer, average rating and rating count, current version and store link, and a completeness verdict: COMPLETE (the feed's own end), TRUNCATED (Apple's 500-review limit per app, country and order), CAPPED (your limit) or PARTIAL. An unknown app, a country with no storefront, an app with no written review: free typed rows. No login, no Apple account, no API key, proxies handled for you.

Why this App Store reviews scraper

  • Several apps and countries in one run. Give App Store URLs or ids and a list of countries: every app is read in every storefront (reviews are per storefront on the App Store), each pair with its own cap (maxReviewsPerApp), and the run's cap on top (maxItems). A URL alone brings its own country.
  • Newest first or most helpful. The two orders Apple's public reviews feed serves: mostRecent and mostHelpful (the first pages of the two shared no review on our test). Each row carries its rank in the order read.
  • The feed's own record, every field. The star rating, title and text, the app version the review was written on, the reviewer's nickname and profile link, the date (UTC), the helpful votes (vote_sum, vote_count) and Apple's review id; every row carries the app id, the country and the input it answers.
  • A verdict per app and country. Apple's public feed serves up to 500 reviews per app, country and order (10 pages of 50; page 11 answers "page depth is limited to 10", measured 2026-10-22). The free app row says how many reviews were delivered from how many pages and why the walk stopped: the feed's own end (COMPLETE), Apple's 500 limit (TRUNCATED), your cap (CAPPED) or a refusal (PARTIAL). For more reviews of a big app, read it in more countries or in both orders.
  • The app's record, free. The app row carries the app's name, developer, bundle id, genre, price, average rating and rating count in that storefront, current version, store link and icon, from Apple's lookup.
  • Honest runs. An id Apple's storefront does not list is a free not_found row (checked twice), a country code with no storefront a free invalid row, an app with no written review a free empty row, a repeated app a free duplicate row. Every input gets a row; a review is charged once a run.
  • Fast and light. Plain HTTP on Apple's public JSON: 50 reviews a call, about 8 KB on the wire for the newest 50. A run of 2 apps × 60 reviews took 3 seconds of reading on our test.

Who it's for

  • App developers and product teams — the newest reviews of your app in every market you sell in, with the app version per review to see what a release changed.
  • ASO and market researchers — the reviews and ratings of a list of competitor apps across countries in one run, with the app's rating count per storefront on the free app row.
  • Data and analytics teams — typed rows keyed by app_id, country and review_id, a free row per app and country with the status and verdict, a run summary to check a pipeline against.

Quick start

The newest reviews of two apps (the Instagram URL and the TikTok id)

{
"appIds": [
"https://apps.apple.com/us/app/instagram/id389801252",
"835599320"
],
"maxReviewsPerApp": 50
}

One app in five countries, up to 500 reviews each

{
"appIds": [
"389801252"
],
"countries": [
"us",
"gb",
"ca",
"au",
"de"
]
}

The most helpful reviews of an app

{
"appIds": [
"https://apps.apple.com/us/app/tiktok/id835599320"
],
"sort": "mostHelpful",
"maxReviewsPerApp": 100
}

Output

One row per review (and one free app row per app and country):

fieldmeaning
row_typereview (one review, charged) or app (the app's record in one storefront with the walk's verdict; free).
input_indexThe 1-based position in appIds of the input this row answers.
input_valueThe input as you gave it (the URL or id).
app_idApple's numeric app id.
countryThe storefront's two-letter country code (us, gb …).
sortThe order read: mostRecent or mostHelpful.
statusAn app row: ok, empty, not_found, invalid, duplicate, failed or not_read (see the FAQ). A review row: ok.
status_detailWhy, in words, when the status is not ok.
scraped_atWhen the row was read (ISO 8601, UTC).
review_idApple's review id.
ratingThe star rating, 1 to 5.
titleThe review's title.
textThe review's text.
app_versionThe app version the review was written on.
reviewer_nameThe reviewer's App Store nickname, as Apple shows it.
reviewer_urlThe reviewer's public App Store profile link.
published_atWhen the review was written or last edited (ISO 8601, UTC).
vote_sumHelpful votes the review got (Apple's vote sum).
vote_countVotes cast on the review, helpful or not.
urlApple's review link for the app in that storefront.
rankThe review's position in the order read (1 to 500).
app_nameThe app's name in that storefront (on review rows too).
developerThe developer as the App Store names it (app row).
bundle_idThe app's bundle id (app row).
genreThe app's primary genre (app row).
priceThe app's price as the storefront shows it (Free, $2.99; app row).
average_ratingThe app's average star rating in that storefront (app row).
rating_countHow many ratings the app has in that storefront, with or without a written review (app row).
current_versionThe app's current version (app row).
app_urlThe app's App Store link in that storefront (app row).
icon_urlThe app's icon (app row).
reviews_deliveredReview rows delivered for this app and country (app row).
pages_readFeed pages read for this app and country (app row).
verdictCOMPLETE (the feed's own end), TRUNCATED (Apple's 500 limit), CAPPED (your limit) or PARTIAL (a refusal or the time limit) (app row).
verdict_detailThe verdict in words, with the numbers (app row).

Example record:

{
"row_type": "review",
"input_index": 1,
"input_value": "https://apps.apple.com/gb/app/instagram/id389801252",
"app_id": "389801252",
"country": "gb",
"sort": "mostRecent",
"status": "ok",
"status_detail": null,
"scraped_at": "2026-10-22T13:45:36Z",
"review_id": "14691542951",
"rating": 1,
"title": "Unfair bans/ no human support",
"text": "Appalling, and there Ai system is going out of order and banning so many accounts including mine, with no human support that the only way is to go through legal action.",
"app_version": "452.0.0",
"reviewer_name": "nickname-redacted",
"reviewer_url": "https://itunes.apple.com/gb/reviews/id900000001",
"published_at": "2026-10-21T02:00:01Z",
"vote_sum": 0,
"vote_count": 0,
"url": "https://itunes.apple.com/gb/review?id=389801252&type=Purple%20Software",
"rank": 3,
"app_name": "Instagram",
"developer": null,
"bundle_id": null,
"genre": null,
"price": null,
"average_rating": null,
"rating_count": null,
"current_version": null,
"app_url": null,
"icon_url": null,
"reviews_delivered": null,
"pages_read": null,
"verdict": null,
"verdict_detail": null
}

Pricing

Pay for the reviews a run delivers, plus one run start; no platform usage is billed to you. The review price falls with your Apify plan.

eventunitFreeStarterScaleBusiness
Review (review)per 1,000$0.10$0.085$0.0767$0.0767
Run start (start)per run$0.0011$0.0011$0.0011$0.0011

A review is $0.10 per 1,000 on the Free plan ($0.0001 a review). Each run that delivers a charged review also pays the run start, $0.0011 once; a run that delivers no charged review pays nothing at all. So the 500 newest reviews of one app in one country (all Apple's feed serves) cost $0.0511 on the Free plan and $0.0436 on Starter, and 1,000 reviews $0.1011 / $0.0861; several apps and countries in one run share one start. The free app row of every app and country, an app Apple does not list in a storefront (not_found), an app with no written review (empty), a value that is no App Store app or country (invalid), a repeated app (duplicate), an app left at the cap or the time limit (not_read) and a refusal the run could not pass (failed) are never charged. A review is charged once a run. A run that stops early (a timeout, an abort) is charged for the reviews it delivered. maxItems counts the charged rows; before the first request the log names the price of each row at your plan and the most the run can cost. Enterprise plans have their own rates: the Actor's Pricing tab shows the price for your plan.

Usage patterns

  • Apps and countries — appIds takes App Store URLs (https://apps.apple.com/gb/app/instagram/id389801252, itunes.apple.com links too) or numeric ids (389801252, id389801252). countries takes two-letter storefront codes (us, gb, de …; uk is read as gb): every app is read in every country given. With no countries, each app is read in the country of its URL, or us for a bare id.
  • What a row is — row_type = review: one review with the feed's record; rank is its position in the order read (1 to 500); sort the order. row_type = app: the free record of one app in one storefront — the lookup's name, developer, rating and version — and the walk: reviews_delivered, pages_read, the verdict with its verdict_detail, and the status with its reason.
  • How far an app goes — maxReviewsPerApp = 0 (the default) reads every review Apple's public feed serves for the app, country and order: up to 500 (10 pages of 50). maxReviewsPerApp = 100 is the first 100 in the order asked. maxItems caps the charged rows of the whole run. The app row's verdict says where the walk stopped and why.

Input configuration

fieldtypedefaultwhat it does
appIdsarrayThe apps to read: App Store URLs (https://apps.apple.com/us/app/instagram/id389801252) or numeric app ids (389801252, id389801252). A URL brings its own country unless countries is set. Up to 1,000 app and country pairs a run; a value that is no App Store app gets a free invalid row, an app given twice for the same country a free duplicate row.
countriesarrayTwo-letter country codes of the App Store storefronts to read (us, gb, de, jp …; uk is read as gb). Every app is read in every country given; reviews are per storefront. Empty: the country in the app's URL, else us. A code Apple has no storefront for gets a free invalid row.
sortmostRecent / mostHelpful"mostRecent"mostRecent: the newest reviews first. mostHelpful: the reviews other users voted most helpful first. Apple's public feed serves up to 500 reviews per app, country and order.
maxReviewsPerAppinteger0Stop each app and country after this many review rows (0 = all Apple's feed serves: up to 500 per app, country and order).
maxItemsinteger0Stop the run after this many review rows across every app and country (0 = no limit). App rows are free and not counted; an app left unread at the cap gets a free not_read row.

Errors

A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:

  • the status message starts with INPUT REJECTED;
  • the dataset holds one row, {"error": true, "code": "…", "message": "…"}, and no results;
  • the key-value store record ERROR holds the same object.

From code, check error on the first row before reading results.

An app with no written review in a storefront is not an error: it gets one free app row with status empty, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.

FAQ

Why at most 500 reviews per app and country?

Apple's public reviews feed serves 10 pages of 50 per app, storefront and order, and answers page 11 with "CustomerReviews RSS page depth is limited to 10" (measured 2026-10-22). Every scraper that reads it logged out stops there. For more reviews of a big app, read it in more countries (each storefront has its own reviews) and in both orders (the newest and the most helpful are different reviews). The app row says TRUNCATED when the limit, not the app's last review, ended the walk.

Which status is which?

An app row's status is ok (reviews served), empty (no written review in that storefront), not_found (Apple's storefront does not list the id, checked twice), invalid (a value that is no App Store app, or a country code with no storefront), duplicate (the same app and country twice: read once), failed (a refusal or an error; free) or not_read (left at maxItems, the charge limit or the run's time limit). A review row's status is ok.

Does it read the developer's replies?

No. Apple's public reviews feed does not carry the developer's response, so it is not on the row.

Is the reviewer's nickname on the row?

The nickname and the profile link are on every review row as Apple shows them publicly. They are personal data: process them under your own lawful basis.

Does it need an Apple account or API key?

No. Everything is read from Apple's public reviews feed and lookup, logged out.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/app-store-reviews-scraper').call({"appIds": ["https://apps.apple.com/us/app/instagram/id389801252", "835599320"], "maxReviewsPerApp": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/app-store-reviews-scraper').call(run_input={'appIds': ['https://apps.apple.com/us/app/instagram/id389801252', '835599320'], 'maxReviewsPerApp': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/app-store-reviews-scraper --input '{"appIds": ["https://apps.apple.com/us/app/instagram/id389801252", "835599320"], "maxReviewsPerApp": 50}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~app-store-reviews-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"appIds": ["https://apps.apple.com/us/app/instagram/id389801252", "835599320"], "maxReviewsPerApp": 50}'

Support

apify@hyperbach.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.