App Store & Google Play Reviews Scraper | $0.01/App, No Cap avatar

App Store & Google Play Reviews Scraper | $0.01/App, No Cap

Pricing

from $6.00 / 1,000 app storefront sweeps

Go to Apify Store
App Store & Google Play Reviews Scraper | $0.01/App, No Cap

App Store & Google Play Reviews Scraper | $0.01/App, No Cap

Reviews, metadata and keyword rankings for iOS and Android apps, in one common schema, across every storefront. Full review sweep that does not lose reviews on the way. No login, no cookies.

Pricing

from $6.00 / 1,000 app storefront sweeps

Rating

0.0

(0)

Developer

Alex Morain

Alex Morain

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

4 days ago

Last modified

Share

App Store & Google Play Reviews Scraper

An app store reviews scraper and a google play reviews scraper in one Actor. Give it an iOS app id, an Android package name or a store URL, and it returns every review the store serves, plus the app's store listing, plus its rank for the search terms you track. iOS and Android come out in the same schema, with the same field names and the same date format.

Pricing is $0.01 per app on one storefront, reviews included, however many there are. A 5,000-review app costs three cents to sweep, not fifty. Reviews are not billed per unit here, so depth is free.

No login, no cookies, no browser. Both stores are read over plain HTTP through endpoints that need no token.

Why most iOS review scrapers quietly return nothing

Apple publishes a public RSS review feed. It is the obvious source, it is what most iOS scrapers are built on, and it does not work. It caps at ten pages, it caps at roughly 500 reviews, and worse, it serves empty pages scattered between full ones. A scraper that paginates the sane way, stopping when a page comes back empty, returns nothing at all on real apps. Page one is often the empty one.

That failure is silent. The run succeeds, the dataset is empty or short, and nothing in the log says the feed lied. You find out when the analysis you built on it says an app with forty million ratings has a hundred reviews.

Measured on 19 August 2026, from a bare IP, no proxy:

AppStorefrontPublic RSS feedThis scraper
SpotifyUS0 reviews across all 10 pages1,200+, still paginating at offset 5,000
WhatsAppUS100, or 0 if it stops on the first empty page600+
DoctolibFR150deep pagination confirmed

This Actor does not read the RSS feed. It reads the catalog API that apps.apple.com itself calls, through Apple's own first-party proxy, which injects the bearer token server-side so the request goes through unauthenticated. Twenty reviews per page, offset pagination, depth measured past 5,000 on a single storefront. It never stops on an apparently empty page: it advances the offset as long as Apple returns rows and a next pointer, so a hollow page in the middle costs nothing.

Google Play gets the same discipline. The Actor calls the internal batchexecute RPC the Play web UI uses, 100 reviews per page, and follows the continuation token to the end instead of stopping at a round number. Measured throughput: 8,000 reviews in 76 seconds from a bare datacenter IP, no rate limiting, continuation token still alive at the end.

There are two ways to lose reviews on the way. Stopping too early, and being throttled into stopping. This Actor handles both: exhaustive pagination on one side, exponential backoff on Apple's per-IP 429 on the other.

What unlimited reviews per app actually changes

The going rate on this market is per review. It sounds cheap until you sweep something real. An app with 5,000 reviews on one storefront costs $0.50 at $0.10 per 1,000 reviews. Five competitors across three countries and you are into double digits before you have looked at the data.

Here the billable unit is the app-storefront pair, at $0.01, and the reviews inside it are free. The same 5,000-review app costs $0.01 plus the $0.02 run start. The deeper you go, the further the two models diverge. See the scenario table under Pricing for the arithmetic per 1,000 reviews.

The practical consequence: you stop rationing depth. Raise maxReviewsPerApp to whatever the analysis needs, add storefronts, add competitors. The bill moves with the number of apps you look at, not with how much they have to say.

How to scrape the App Store and Google Play

From the Apify Console

  1. Open the Input tab. Two apps are already prefilled, one from each store, so you can press Start immediately and see the output shape before committing to anything.
  2. Replace them with your own. Paste the store URL straight from your browser, or use the App Store numeric id (310633997) or the Google Play package name (com.whatsapp). Mixed lists are fine, the Actor sorts out which store each entry belongs to.
  3. Set the Storefronts. Both stores are partitioned by country: a US review never appears in the French store. Start with us, add countries once you have seen the data.
  4. Leave Reviews and App metadata both ticked. They are covered by the same billable unit, so taking both costs exactly what taking one costs.
  5. Raise Max reviews per app and storefront if you want the full backlog. The default is 500, which is a sample, not a sweep. The price does not change with this number.
  6. Press Start, then export the dataset as JSON, CSV, Excel or XML from the Storage tab.

From the App Store scraper API

Every run is also an API call. Get your token from Settings → Integrations in the Console, then use one of the snippets in Code examples below. The synchronous endpoint blocks until the run finishes and returns the dataset in the response body, which is the shortest path from zero to rows.

Which fields should I fill?

If you want to...Fill inLeave alone
Read what users say about one appapps, one entry in countrieseverything else
Compare an app across marketsapps, several countrieseverything else
Get the full review backlog, not a samplemaxReviewsPerApp at a high valueeverything else
Monitor new feedback dailymode: new-only, plus a scheduleeverything else
Track App Store search positionsadd rankings to include, fill keywordsapps can stay empty
Run a competitor app analysisevery competitor in one apps listeverything else
Cut a run short for a quick lookmaxReviewsPerApp at 100everything else

Only apps really matters, and even that can be empty if you run keyword rankings alone. Everything else has a working default.

Input reference

FieldTypeWhat it doesExample
appsarray of stringsThe apps to collect. Accepts an App Store numeric id, a Google Play package name, a full App Store URL or a full Google Play URL, freely mixed. Unreadable entries are skipped with an explanation in the log and the rest of the list still runs.["310633997", "com.spotify.music"]
countriesarray of stringsISO 3166-1 codes of the storefronts to sweep. Case-insensitive. Every app is swept on every storefront listed. Empty means us.["us", "fr", "gb"]
includearray of stringsAny combination of reviews, metadata and rankings. Reviews and metadata share one billable unit. Rankings are billed separately, per keyword and storefront.["reviews", "metadata"]
modestringall returns everything the store serves on every run. new-only keeps a persistent registry per app and storefront and returns only reviews it has never seen."all"
maxReviewsPerAppintegerUpper bound on reviews per app and per storefront. Does not affect the price. Default 500.5000
keywordsarray of stringsSearch terms to track. Used only when rankings is in include. Works with an empty apps list.["music streaming"]
rankingDepthintegerHow many ranked apps to record per keyword and storefront, 1 to 200. Default 50. Depth does not affect the price.50
proxyConfigurationobjectOff by default and it should stay off. Both stores are read over plain HTTP and need no proxy in normal use. Turn it on only if you sweep hundreds of app-storefront pairs in one run and see rate limits in the log.{"useApifyProxy": false}

A full input:

{
"apps": [
"310633997",
"com.spotify.music",
"https://apps.apple.com/fr/app/id925339063"
],
"countries": ["us", "fr"],
"include": ["reviews", "metadata", "rankings"],
"mode": "all",
"maxReviewsPerApp": 5000,
"keywords": ["music streaming", "meditation"],
"rankingDepth": 50,
"proxyConfiguration": { "useApifyProxy": false }
}

Output fields

All records land in one dataset. Every record carries a type field, so you can split them with a single filter: review, metadata or ranking. The dataset also ships three ready-made views, one per type, selectable in the Storage tab and through the API with ?view=reviews, ?view=metadata or ?view=rankings.

Review fields (iOS and Android app reviews, one schema)

FieldTypeDescriptionExample
typestringAlways review for these rows."review"
storestringapple or google."apple"
app_idstringApp Store numeric id, or Android package name. Always a string, both stores."310633997"
countrystringStorefront this review was collected from, lowercase."us"
review_idstringStore-side review id. Stable, and what the delta mode deduplicates on."13657831289"
ratinginteger1 to 5. Clamped to that range on both stores.5
titlestring or nullReview title. App Store only, Google Play does not have review titles, so it is null there."Potential improvements"
bodystring or nullReview text, as posted, in the storefront's language."I love the app and it's my main..."
authorstring or nullDisplay name of the reviewer."Ed Bradway"
versionstring or nullApp version the review was left on. Google Play only, null on App Store rows."9.1.64.1676"
posted_atstring or nullISO 8601 UTC, second precision, Z suffix. Normalized on both stores, never an epoch, never a localized string."2026-01-21T04:48:38Z"
is_editedboolean or nullWhether the review was edited after posting. App Store only, null on Google Play rows.false
reply_bodystring or nullThe developer's public reply. Google Play only."Thanks for the feedback..."
reply_atstring or nullWhen the developer replied, same ISO 8601 UTC format. Google Play only."2026-08-02T09:12:00Z"

Four fields are store-specific and the table says which: title and is_edited come from Apple, version and the reply pair come from Google. They are always present as keys, set to null on the other store, so a CSV export has stable columns and a dataframe has stable dtypes.

App metadata fields (app metadata API for both stores)

FieldTypeDescriptionExample
typestringAlways metadata for these rows."metadata"
storestringapple or google."google"
app_idstringNumeric id or package name."com.spotify.music"
countrystringStorefront the listing was read from."us"
namestring or nullApp name as shown on that storefront."Spotify: Music and Podcasts"
developerstring or nullPublisher name."Spotify AB"
rating_averagenumber or nullAverage star rating, unrounded.4.3448367
rating_countinteger or nullNumber of ratings.36244267
review_countinteger or nullNumber of written reviews. On the App Store this equals rating_count, Apple does not split the two.1850955
versionstring or nullCurrent version on that storefront. Reliable on the App Store, sometimes null on Google Play."26.34.74"
pricenumber or nullListing price. 0.0 for a free app.0.0
currencystring or nullCurrency of price. Real storefront currency on the App Store; Google Play rows are labelled USD."USD"
genrestring or nullPrimary category."Music & Audio"
installsstring or nullInstall bucket as Google publishes it. Google Play only, null on App Store rows."1,000,000,000+"
descriptionstring or nullFull store description text."With the Spotify music and podcast app..."
icon_urlstring or nullDirect URL to the app icon. 512px on the App Store."https://play-lh.googleusercontent.com/..."
urlstring or nullCanonical store listing URL."https://play.google.com/store/apps/details?id=com.spotify.music"

Keyword ranking fields (app store keyword ranking)

One row per app per position, for each keyword and each storefront.

FieldTypeDescriptionExample
typestringAlways ranking for these rows."ranking"
storestringapple. App Store only in this version."apple"
countrystringStorefront the search was run in."us"
keywordstringThe search term, exactly as you submitted it."music streaming"
positionintegerRank in the result list, starting at 1.2
app_idstringNumeric App Store id of the ranked app."324684580"
namestring or nullName of the ranked app."Spotify: Music and Podcasts"
developerstring or nullIts publisher."Spotify"
rating_averagenumber or nullIts average rating on that storefront.4.77453
rating_countinteger or nullIts number of ratings on that storefront.41912880

Example output

Real rows, collected on 5 September 2026, trimmed for length.

[
{
"type": "metadata",
"store": "apple",
"app_id": "310633997",
"country": "us",
"name": "WhatsApp Messenger",
"developer": "WhatsApp Inc.",
"rating_average": 4.68457,
"rating_count": 18529394,
"review_count": 18529394,
"version": "26.34.74",
"price": 0.0,
"currency": "USD",
"genre": "Social Networking",
"installs": null,
"description": "WhatsApp from Meta is a free messaging and calling app used by over 2 billion people across 180+ countries...",
"icon_url": "https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/05/ee/c3/05eec37b/AppIcon.png/512x512bb.jpg",
"url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997?uo=4"
},
{
"type": "review",
"store": "apple",
"app_id": "310633997",
"country": "us",
"review_id": "10031881920",
"rating": 4,
"title": "Potential improvements",
"body": "I love the app and it's my main communication method. I just have some ideas that would make the app experience better. 1. It would be useful to have the possibility to filter the group chats and individual chats...",
"author": "Lol_hahahahahah",
"version": null,
"posted_at": "2023-06-14T06:43:29Z",
"is_edited": false,
"reply_body": null,
"reply_at": null
},
{
"type": "metadata",
"store": "google",
"app_id": "com.spotify.music",
"country": "us",
"name": "Spotify: Music and Podcasts",
"developer": "Spotify AB",
"rating_average": 4.3448367,
"rating_count": 36244267,
"review_count": 1850955,
"version": null,
"price": 0.0,
"currency": "USD",
"genre": "Music & Audio",
"installs": "1,000,000,000+",
"description": "With the Spotify music and podcast app, you can play millions of songs, albums and original podcasts for free...",
"icon_url": "https://play-lh.googleusercontent.com/IzQgYCcnCFCD08GR-3bdtcT8xzOvrNkC84avGT5CwTX2VIqmTmKKJcP_Cd4JoBOdmCMlTndlOzV6hrthg2fOWA",
"url": "https://play.google.com/store/apps/details?id=com.spotify.music"
},
{
"type": "review",
"store": "google",
"app_id": "com.spotify.music",
"country": "us",
"review_id": "5dc32489-93a6-440a-8d62-18a0b42106a4",
"rating": 5,
"title": null,
"body": "very good",
"author": "Ronik Ronik",
"version": "9.1.64.1676",
"posted_at": "2026-09-04T13:28:17Z",
"is_edited": null,
"reply_body": null,
"reply_at": null
},
{
"type": "ranking",
"store": "apple",
"country": "us",
"keyword": "music streaming",
"position": 2,
"app_id": "324684580",
"name": "Spotify: Music and Podcasts",
"developer": "Spotify",
"rating_average": 4.77453,
"rating_count": 41912880
}
]

Code examples: Python, JavaScript and cURL

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"apps": ["310633997", "com.spotify.music"],
"countries": ["us", "fr"],
"include": ["reviews", "metadata"],
"mode": "all",
"maxReviewsPerApp": 5000,
}
run = client.actor("alexmorain/app-store-play-store-scraper").call(run_input=run_input)
reviews, listings = [], []
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["type"] == "review":
reviews.append(item)
elif item["type"] == "metadata":
listings.append(item)
print(f"{len(reviews)} reviews, {len(listings)} store listings")
# Straight into pandas, both stores in one frame, no merging step.
import pandas as pd
df = pd.DataFrame(reviews)
df["posted_at"] = pd.to_datetime(df["posted_at"])
print(df.groupby(["store", "country"])["rating"].mean())

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('alexmorain/app-store-play-store-scraper').call({
apps: ['310633997', 'com.spotify.music'],
countries: ['us', 'fr'],
include: ['reviews', 'metadata'],
mode: 'all',
maxReviewsPerApp: 5000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const reviews = items.filter((i) => i.type === 'review');
const oneStar = reviews.filter((r) => r.rating === 1);
console.log(`${reviews.length} reviews, ${oneStar.length} of them one-star`);

cURL

Run synchronously and get the dataset back in the same response:

curl -X POST "https://api.apify.com/v2/acts/alexmorain~app-store-play-store-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{
"apps": ["310633997", "com.spotify.music"],
"countries": ["us"],
"include": ["reviews", "metadata"],
"maxReviewsPerApp": 1000
}'

Ask for only the reviews, as CSV, using the dataset view:

curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?view=reviews&format=csv&token=<YOUR_APIFY_TOKEN>" \
-o reviews.csv

What people use it for

Watching your own reviews across every country store

Your app is live in twenty markets and the store console shows you one country at a time. Put your app id in apps, list every storefront you ship to in countries, and one run gives you the whole picture in one table with a country column. Twenty storefronts is twenty billable units, twenty cents plus the two-cent run start, whatever the review volume behind them. Schedule it daily in new-only mode and it becomes a feed of what changed rather than a re-download of the same corpus.

Competitor app analysis

Put five or ten competitors in apps in one go, keep metadata ticked, and you get their ratings, rating counts, install buckets, current versions and full descriptions alongside every review their users left. The reviews are where the useful part is: the complaints that repeat across three competitors are the feature gap, and the compliments that repeat are what you are up against. Because reviews are not metered, going ten thousand deep on a competitor costs the same cent as going a hundred deep, which is what makes this kind of sweep practical at all.

ASO keyword tracking and app store optimization data

Tick rankings, put your target search terms in keywords, and each run records the ranked list of apps for each term on each storefront, position by position, up to 200 deep. Two cents buys ten keywords. Run it on a schedule and the dataset becomes a position history: you see the day you moved from 14 to 6 on your main term, and you see the competitor who took the slot above you. This is the segment nobody serves well on this market, and it is the same run as your review collection, so the ASO data and the voice-of-customer data arrive together.

Catching a regression after a release

You ship a version, and the question is whether it broke something. Reviews carry the app version on Google Play, so filter version to the new build and look at the rating distribution against the previous one. On the App Store, filter on posted_at after the release date instead. A daily new-only run wired to a webhook gives you this within hours of the release rather than at the end of the sprint, which is the difference between a hotfix and a bad month.

Feeding a sentiment or topic model

Review text is good training and evaluation material, and it is annoying to collect at volume. Here the bodies come out clean, in one schema, with a normalized UTC timestamp and an integer rating that works as a label out of the box. Because the price does not follow the row count, building a corpus of a hundred thousand reviews across twenty apps costs twenty cents plus the run start. The store field lets you check whether your model behaves the same on iOS and Android text, which it usually does not.

Market research on a category

Search a category term with rankings at depth 200, take the app ids that come back, feed them into apps on a second run, and you have the full picture of a category: who ranks, what their ratings are, what their users complain about. The rating_count and installs fields give you the rough size of each player. This is a two-run pipeline and it costs well under a dollar for a fifty-app category.

Why this scraper

One schema for iOS and Android app reviews. An Apple review and a Google review come out with the same field names, the same types and the same date format. Ratings are integers 1 to 5 on both. Timestamps are ISO 8601 UTC with a Z suffix on both, never an epoch on one side and a localized string on the other. Ids are strings on both, because Apple and Google do not type them the same way. You do not write a merge step.

A review sweep that does not lose reviews. Exhaustive pagination on both stores, no early stop on an empty page, no arbitrary depth ceiling other than the one you set. This is the whole reason the Actor exists, and the RSS comparison table at the top is the evidence.

Every storefront. The country code is a real parameter on all three surfaces: reviews, listings and rankings. French reviews for a French storefront, Japanese rankings for the Japanese store. Nothing is US-only.

No login, no cookies, no browser. Plain HTTP against endpoints that need no token, which is why there is no session to expire, no account to get banned and no headless browser inflating the runtime. It also keeps the platform cost near zero, which is what makes the flat per-app unit sustainable rather than a promotional trick.

It degrades in the open. An entry it cannot parse is skipped with an explanation in the log and the run continues. One app failing on one storefront does not stop the other pairs. If everything fails, the run ends as FAILED, not as a green run with an empty dataset. The log prints the billing plan before spending anything: how many app-storefront units and how many keyword units the run is about to charge.

You are not billed for empty pairs. The app-storefront unit is charged when the first row for that pair is actually pushed. An app that does not exist on a storefront returns nothing and costs nothing.

Pricing

Pay per event, three events, nothing else. Platform compute is included, so the events are the whole bill.

EventPriceCharged
Actor start$0.02Once per run.
App on a storefront$0.01Per app and per storefront that returns data. Covers the store listing and the complete review sweep, however many reviews that is.
Keyword ranking$0.002Per keyword and per storefront. Covers up to 200 ranked positions.

What that works out to per 1,000 reviews

The right column is the same job at a per-review price of $0.10 per 1,000 reviews, which is roughly the going rate on this market.

ScenarioReviews collectedCost herePer 1,000 reviewsSame job, metered per review
1 app, 1 storefront, small app500$0.03$0.060$0.05
1 app, 1 storefront, mid-size app5,000$0.03$0.006$0.50
1 app, 1 storefront, large app50,000$0.03$0.0006$5.00
1 app, 5 storefronts25,000$0.07$0.0028$2.50
10 competitors, 1 storefront20,000$0.12$0.006$2.00
10 competitors, 5 storefronts100,000$0.52$0.0052$10.00
20 keywords, 3 storefronts, no apps0$0.14n/an/a

The crossover is around 300 reviews per app-storefront pair for a single-app run, and around 100 once the run start is spread over several apps. Below that, metering per review is cheaper and you should use whatever is cheapest. Above it, the flat unit wins, and it wins by more the deeper you go: at 50,000 reviews the ratio is roughly 165 to 1.

A run stops on its own when it reaches the maximum charge you set for it, and says so in the status message. It never silently spends past your cap.

Limits and what this scraper does not do

Read this before you buy. It is shorter than the feature list and more useful.

Keyword rankings are App Store only. Google Play rankings are not implemented in this version. If you need Play Store search positions, this Actor is not it yet.

The default review cap is 500. maxReviewsPerApp defaults to 500, per app and per storefront. That is a sample. A full backlog needs you to raise it, and raising it does not cost more, but nobody gets the full sweep by accident.

Reviews are not filterable by date or rating at the source. Neither store's endpoint accepts those filters here. The Actor sweeps and you filter downstream, or you use mode: new-only to get only what is new since the last run.

Google Play reviews come back newest first, sorted by the store. Apple serves its own order. If you need strict chronology, sort on posted_at yourself.

Google Play reviews are requested in English. The hl language parameter is fixed to en while the storefront gl follows your countries. You get that country's reviews, in the language they were written, but the request itself is not localized.

Some Google Play listing fields can come back null. The listing is parsed out of the page's embedded data blocks, and Google moves those paths around. The parser returns null for a field whose path moved instead of failing the run. version is the one that goes missing most often. Review collection is unaffected, it uses a different surface.

No in-app purchase list, no ratings histogram, no similar-apps graph, no changelog, no screenshots. The metadata row is the set of fields documented above and nothing more.

No Apple Search Ads placements. The ranking source is Apple's official search endpoint, which returns organic results only and can lag the live UI slightly. It is a good ASO tracker, not a paid-placement monitor.

The delta registry keeps the last 8,000 review ids per app and storefront. In new-only mode, an app that receives more than 8,000 reviews between two runs can re-serve older ones. Daily runs on any normal app are nowhere near that.

No developer replies on the App Store. Apple's review surface used here does not carry them. reply_body and reply_at are populated on Google Play only.

FAQ

How do I export App Store reviews to CSV? Run the Actor, open the run's Storage tab, pick the Reviews view and export as CSV. From the API, call https://api.apify.com/v2/datasets/<DATASET_ID>/items?view=reviews&format=csv. The view keeps the review columns and drops the metadata and ranking rows, so the file opens cleanly in Excel or Sheets. JSON, XML and Excel are available at the same endpoint by changing format.

Can I get reviews from all countries? Yes. List the ISO country codes in countries and every app is swept on every storefront you name. Each app-storefront pair is one billable unit at $0.01, so twenty countries for one app is twenty cents plus the run start, regardless of how many reviews come back.

How many reviews does the App Store API return? The public RSS feed caps at about 500 and serves empty pages that make naive scrapers stop at zero. The catalog endpoint this Actor uses paginates 20 at a time and was still returning reviews at offset 5,000 on Spotify US during testing. In practice your ceiling is maxReviewsPerApp, not the store.

Can I scrape both iOS and Android apps in the same run? Yes, that is the point of the common schema. Mix App Store ids, Google Play package names and store URLs in one apps list. The Actor works out which store each entry belongs to and both come back with identical field names.

Do I need a proxy or an Apify Proxy subscription? No. Both stores are read over plain HTTP with no token and no cookie, and a normal run needs no proxy at all. The proxy option exists for very large sweeps, hundreds of app-storefront pairs in a single run, where Apple's per-IP rate limit starts to bite. Leave it off otherwise, it only slows the run down.

How do I track my app store keyword ranking over time? Add rankings to include, put your terms in keywords, set a rankingDepth, and schedule the Actor daily or weekly. Each run appends ranking rows with keyword, country, position and the app at that position. Point every scheduled run at the same dataset, or join the runs afterwards on keyword and run date, and you have a position history.

Can I get only new reviews instead of the whole backlog every time? Set mode to new-only. The Actor keeps a persistent registry of review ids per app and storefront and returns only what it has not seen. The first run in this mode still returns everything, since nothing has been seen yet. Combine it with a schedule and a webhook for a live feed of new feedback.

Does the price go up if an app has a million reviews? No. The unit is the app on a storefront, at $0.01, and the reviews inside it are not metered. What a large app costs you is run time, not money, which is what maxReviewsPerApp is for.

Can I get the app description, icon and install count? Yes, they are in the metadata rows: description, icon_url and, on Google Play, installs. Keep metadata in include. It shares the billable unit with reviews, so it is free if you are already collecting reviews.

What happens if one app in my list is wrong? It is skipped, the log says why, and the rest of the list runs. The same applies to an app that does not exist on one of your storefronts: that pair returns nothing, is not charged, and the other pairs continue. A run only ends as FAILED when every single pair failed.

Can I use this scraper as an app metadata API? Yes. Set include to ["metadata"], list your apps and storefronts, and call the synchronous endpoint run-sync-get-dataset-items. You get the listings back in the response body. It is one billable unit per app and storefront, same as a full sweep.

Is scraping app store reviews legal? The Actor reads public store pages and public endpoints, the same data any visitor sees, and collects no personal data beyond the public display names attached to public reviews. What you may do with that data depends on your jurisdiction and your purpose. If you are processing it at scale in the EU or handling it as personal data, talk to your own counsel first.

Where do I report a problem? The Issues tab on the Actor page. Google occasionally rotates the internal RPC id behind the Play reviews endpoint. When that happens the Actor raises an explicit error saying so, rather than pretending the app has no reviews. Report it and it gets fixed.

Integrations

Webhooks. Wire a webhook on the Actor's run success to push the dataset id to your own endpoint, then pull the rows from there. Combined with mode: new-only and a daily schedule, this is a review feed: your service gets called only when there is something new, and only the new reviews are in the dataset.

Exports. Datasets export as JSON, CSV, Excel, XML and RSS from the Console or the API, with the three named views to split reviews, metadata and rankings cleanly. The API endpoint accepts format and view as query parameters, so the export is a single URL you can put in a cron job.

Anything Apify connects to. Runs and datasets are reachable from Zapier, Make, n8n, Google Sheets, Airbyte and Keboola through the standard Apify integrations, plus the official Python and JavaScript clients shown above for anything custom.

MCP and AI agents. The Actor runs over the Apify MCP server, so an agent can call it as a tool, pass an app id and read the reviews back without any glue code. The common iOS and Android schema helps here more than anywhere else: an agent gets one field layout to reason about instead of two, and the flat per-app price means an agent exploring a category cannot run up a bill proportional to how much it read.