If you've ever pulled App Store reviews programmatically, you've hit a wall you may not have noticed: you can only get 500 reviews per app. Not 500 per request — 500, total, forever.
Apple's public customer-reviews RSS feed is paginated at 50 entries and stops at page 10. Request page 11 and you get nothing back. Every App Store review tool inherits that ceiling, because they all read the same feed.
Here's the part that isn't widely known: the ceiling is per storefront, not per app.
Each country is its own feed
Apple runs ~175 country storefronts, and each one paginates independently. Same app, same endpoint shape, different us / gb / de in the path:
curl "https://itunes.apple.com/us/rss/customerreviews/page=1/id=310633997/sortBy=mostRecent/json"
curl "https://itunes.apple.com/de/rss/customerreviews/page=1/id=310633997/sortBy=mostRecent/json"
curl "https://itunes.apple.com/br/rss/customerreviews/page=1/id=310633997/sortBy=mostRecent/json"
No key, no auth, no scraping — this is Apple's own public feed.
I measured it against WhatsApp across 10 storefronts. Result: 4,250 unique reviews in 3.2 seconds, zero duplicates. Versus the 500 you'd get from the US alone. That's 8.5× on ten countries; sweep all ~175 and the ceiling moves to roughly 87,500.
The more interesting output
Depth was what I went looking for. The per-country breakdown turned out to be the more useful thing:
| Storefront | Rating | Ratings count |
|---|---|---|
| 🇲🇽 Mexico | 4.78 | 5,893,510 |
| 🇧🇷 Brazil | 4.78 | 8,313,182 |
| 🇬🇧 UK | 4.71 | 4,116,608 |
| 🇺🇸 US | 4.69 | 18,293,098 |
| 🇰🇷 Korea | 4.68 | 127,839 |
| 🇮🇳 India | 4.62 | 7,960,859 |
| 🇩🇪 Germany | 4.60 | 3,530,320 |
| 🇫🇷 France | 4.56 | 3,432,960 |
| 🇯🇵 Japan | 4.55 | 254,035 |
Same app, same week: 4.78 in Mexico, 4.55 in Japan. If you only ever query the US store, that spread is invisible to you — and it's exactly the thing an international product team wants to know. Which markets are we losing, and what are people saying there?
Doing it yourself
The mechanics are simple; the tedium is in the details. Roughly:
const PAGE_SIZE = 50, MAX_PAGES = 10;
async function reviewsFor(appId, cc) {
const out = [];
for (let page = 1; page <= MAX_PAGES; page++) {
const url = `https://itunes.apple.com/${cc}/rss/customerreviews/page=${page}/id=${appId}/sortBy=mostRecent/json`;
let json;
try { json = await (await fetch(url)).json(); } catch { break; } // past the ceiling Apple stops returning JSON
const entries = json?.feed?.entry;
if (!entries) break;
// page 1 can lead with an app-summary entry that has no im:rating — skip it
const reviews = [].concat(entries).filter((e) => e['im:rating']);
if (!reviews.length) break;
out.push(...reviews.map((e) => ({
country: cc,
rating: Number(e['im:rating'].label),
title: e.title?.label,
body: e.content?.label,
version: e['im:version']?.label,
})));
if (reviews.length < PAGE_SIZE) break;
}
return out;
}
Things that will bite you: page 1 sometimes leads with an app-summary entry that has no rating; Apple returns non-JSON rather than an empty feed past the ceiling, so you need the try/catch to stop cleanly; and not every app exists in every storefront — China commonly returns nothing, which is app availability, not an error.
Or one call
I packaged this as App Store Reviews API — storefront sweeping, dedup, per-country rating breakdown, rating filters:
{
"apps": ["310633997"],
"countries": ["all"],
"maxReviewsPerCountry": 500
}
A few use cases worth stealing whether you build it or not:
Global complaints, filtered. minRating: 1, maxRating: 2 across every storefront gives you a worldwide bug-and-churn report you can hand straight to an LLM.
Rating drift monitoring. includeReviews: false returns just the per-country ratings — cheap enough to run on a schedule and alert when a market starts sliding.
Competitive teardown. Several apps, several countries, one dataset.
What this can't do
- 500 per storefront is Apple's limit, not a tool's. Nothing gets past it for a single country. Sweeping storefronts is the only lever.
- Recent-first. This is the live picture, not full review history.
- No Google Play here. Play has no equivalent public API, so it needs actual scraping — a different risk profile, deliberately out of scope.
The whole thing runs on Apple's documented public endpoints, which is why it's fast, doesn't need proxies, and doesn't break when a page layout changes. The rest of the suite is at apify.com/fetchbase.
Curious whether anyone has found a documented way past the 10-page cap — if you have, I'd genuinely like to know.
Top comments (0)