Scrape App Store & Google Play Reviews: Endpoints, Caps, Geo
App reviews are the cheapest product research you can buy - if you can get past the pagination caps, the token walls and per-country storefronts. Here is the whole map.
App reviews are the cheapest customer research going: unfiltered feature requests, bug reports tied to a specific version, and a running sentiment read on every competitor in your category. The catch is access. Both stores show a handful of reviews on the page and hide the rest behind feeds, tokens and per-country storefronts. This guide maps how to scrape App Store and Google Play reviews - the real endpoints, the pagination caps nobody warns you about, and the geo and rate-limit realities that decide whether your pipeline survives past a few hundred rows.
Apple, the easy way: the RSS feed
Apple exposes a public JSON feed of customer reviews that needs no token. It is the fastest way to start and returns clean, structured records - rating, title, body, author, app version. The limitation is a hard ceiling: the feed serves at most 10 pages of roughly 50 reviews, so about 500 reviews per app per storefront, skewed to the most recent. For monitoring fresh feedback that is often enough; for a full history it is not.
import requests
def apple_rss_reviews(app_id, country="us", pages=10):
out = []
for page in range(1, pages + 1): # feed caps out around page 10
url = (f"https://itunes.apple.com/{country}/rss/customerreviews/"
f"page={page}/id={app_id}/sortby=mostrecent/json")
# route through a residential exit in the target storefront's country
proxy = f"http://USER-country-{country}:PASS@gate.quantumproxies.io:8000"
r = requests.get(url, proxies={"https": proxy}, timeout=20)
entries = r.json().get("feed", {}).get("entry", [])
for e in entries[1:]: # first entry is app metadata, skip it
out.append({
"rating": e["im:rating"]["label"],
"version": e["im:version"]["label"],
"title": e["title"]["label"],
"text": e["content"]["label"],
"author": e["author"]["name"]["label"],
})
if len(entries) <= 1:
break
return out
Apple, the deep way: the app-store API and its token
To go past 500, you use the same endpoint the App Store web page calls (the AMP / MZStore API). It returns richer records - review id, edit flag, developer responses - but it demands a bearer token that you first scrape from the app's public web page, then replay. Reviews come in batches of roughly twenty, and you paginate deeper with an offset; the larger the offset, the older the reviews tend to be, because Apple does not let this endpoint sort by date directly.
The real constraint here is rate limiting, and it arrives fast from a single IP. The fix is not magic - it is a deliberate delay plus exponential backoff, and spreading requests across IPs. Practitioners who add both have pulled on the order of 15,000 reviews for one app without tripping the limiter. That is exactly where a rotating residential pool pays off: each batch can exit from a different clean IP, so the per-IP counter never climbs into block territory.
import time, requests
# token is scraped once from the app's App Store web page, then reused
HEADERS = {"Authorization": "Bearer TOKEN_FROM_APP_PAGE",
"Origin": "https://apps.apple.com"}
def apple_deep_reviews(app_id, country="us", target=2000):
reviews, offset = [], None
while len(reviews) < target:
params = {"l": "en-US", "offset": offset} if offset else {"l": "en-US"}
url = (f"https://amp-api.apps.apple.com/v1/catalog/{country}/apps/"
f"{app_id}/reviews")
proxy = f"http://USER:PASS@rotating.quantumproxies.io:8000"
r = requests.get(url, headers=HEADERS, params=params,
proxies={"https": proxy}, timeout=25)
if r.status_code == 429: # rate limited
time.sleep(8); continue # back off, gateway rotates the IP
data = r.json()
reviews += data.get("data", [])
offset = data.get("next", "").split("offset=")[-1] or None
if not offset:
break
time.sleep(1.5) # be a polite client
return reviews

Google Play: hydrated JSON, not HTML
Play reviews are not sitting in the page HTML. The store loads them through an internal batch endpoint that returns nested JSON, paginated with a continuation token rather than page numbers, and filtered by sort order (newest, rating, helpfulness). Reconstructing those requests by hand is fiddly, so most teams lean on the well-maintained open-source google-play-scraper libraries (Node and Python), which wrap the endpoint and expose country and lang parameters. As with Apple, per-country results differ, so set both explicitly.
# pip install google-play-scraper
from google_play_scraper import reviews, Sort
result, token = reviews(
"com.example.app",
lang="en", # review language
country="us", # storefront
sort=Sort.NEWEST,
count=200, # per call; loop with continuation_token for more
)
for r in result[:3]:
print(r["score"], r["reviewCreatedVersion"], r["content"][:80])
At real volume the Play endpoint throttles by IP too, and the JSON structure shifts periodically. If you would rather not own that maintenance, a Scraper API that renders and returns the hydrated data as clean JSON removes both problems - it carries the proxying and the parsing so you consume a stable shape. The same trade-off logic we describe for scraping product reviews at scale applies directly here.
One field pair trips people up: language and country are not the same knob. The storefront (country) decides which reviews exist at all; the language parameter decides which of them you get back. In a bilingual market like Canada or Switzerland you often want both languages, so set them independently rather than assuming a country implies a single language. On Apple's side, the richer records also expose developer responses - the public reply a vendor posts under a review - which is a quietly valuable signal for how competitors triage complaints and which issues they choose to answer publicly.
Geo storefronts are the whole point
Both stores are organised by country storefront, keyed by a two-letter code. The US reviews of an app tell you nothing about how it lands in Germany, Japan or Brazil - different languages, different complaints, different feature gaps. To read each storefront honestly you request from an exit IP in that country; a datacenter IP in the wrong region gets you an inconsistent or blocked response. With residential exits across 200+ countries you can loop the same app through every market and build a per-country sentiment map - the raw material of serious ASO work.

From reviews to ASO signal
The extraction is the boring half. The payoff is what you compute on top: cluster review text into recurring themes, track sentiment by app version to catch the release that tanked your rating, watch competitors for feature requests your product already answers, and compare complaint patterns across storefronts. Tie every review to its version field and you get a regression timeline no analytics dashboard gives you. Related reputation work - Trustpilot review mining - stacks neatly alongside app-store data for a full customer-voice picture.
Get residential IPs for every app storefront
Frequently asked questions
How do I scrape App Store reviews in Python?
Start with Apple's public RSS customer-reviews JSON feed - no token, structured output, but capped at roughly 500 recent reviews per app per storefront. To go deeper, call the AMP app-store API with a bearer token scraped from the app's web page, paginate with an offset, and add delay plus backoff. Route each storefront through a residential IP in that country.
Is there an official App Store reviews API?
Apple's public RSS feed is the closest thing to an official, tokenless review source, but it is capped. The richer AMP endpoint is what the store's own web page uses and requires a scraped bearer token. Neither is a documented developer product for bulk third-party review collection, so treat rate limits and terms with care.
How do I scrape Google Play reviews?
Play serves reviews from an internal batch endpoint returning nested JSON, paginated by a continuation token and filterable by sort order. The maintained open-source google-play-scraper libraries wrap it and expose country and lang. Set both, loop the continuation token for volume, and spread requests across IPs because the endpoint throttles per address.
Why do I need proxies to scrape app reviews?
Two reasons. Rate limiting: both stores throttle a single IP quickly, so rotating residential exits keep the per-IP counter low enough to pull thousands of reviews. Geography: reviews are storefront-specific, so reading a country's reviews accurately means requesting from an IP in that country. Datacenter IPs in the wrong region get inconsistent or blocked responses.
App-store data is a goldmine gated by three simple obstacles - caps, tokens and storefronts. Know which endpoint to hit, page it correctly, and exit from the right country on clean IPs, and you turn scattered star ratings into a per-version, per-market customer-voice feed.