App Store & Google Play Reviews Scraper API | iOS + Android
Pricing
from $0.10 / 1,000 reviews
App Store & Google Play Reviews Scraper API | iOS + Android
Scrape App Store and Google Play reviews in one run: ratings, text, dates, versions, developer replies, sentiment and topics, app details and top charts. One stable schema, CSV/Excel-ready. Multi-country, star/date/keyword filters, new-reviews-only monitoring. From $0.10 per 1,000 reviews.
Pricing
from $0.10 / 1,000 reviews
Rating
0.0
(0)
Developer
Aaron Tuttle
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 days ago
Last modified
Categories
Share
Scrape App Store and Google Play reviews in one run, in one stable schema, from $0.10 per 1,000 reviews. Ratings, review text, dates, app versions, developer replies, free sentiment and topic tags, app details, search results and top charts, ready for CSV, Excel, Google Sheets or your API.
| Both stores, one run | App Store (iOS) | Google Play (Android) |
|---|---|---|
| Reviews: stars, title, text, date, reviewer name, link | ✅ | ✅ |
| App version and helpful votes per review | ✅ | ✅ |
| Developer replies (text and date) | Partly (Apple's reviews feed leaves them out) | ✅ |
| Sentiment + topics per review (free, no AI service) | ✅ | ✅ |
| App details: rating, histogram, price, version, category… | ✅ | ✅ + installs, data safety |
| Search by name, top charts per category | ✅ | ✅ |
| Many countries in one run | ✅ + sweep presets (top10, top25, all) | ✅ + many languages |
| Same fields for both stores (items or flat rows) | ✅ | ✅ |
Paste app URLs, Apple app ids or Android package names (or search by name), pick countries, click Start.
💸 Pricing
Pay per result. Compute is included, there are no platform fees, and summaries, sentiment/topic tags and the competitor comparison are free. Prices drop as your Apify plan's discount tier goes up:
| Event | Free plan | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|
| Review | $0.00015 | $0.00013 | $0.00012 | $0.0001 | $0.0001 | $0.0001 |
| App details (per app × country) | $0.002 | $0.002 | $0.0015 | $0.001 | $0.0008 | $0.0006 |
| Search result or top-chart entry | $0.0006 | $0.0005 | $0.0004 | $0.0003 | $0.0003 | $0.0002 |
| Run start | $0.001 | $0.001 | $0.001 | $0.001 | $0.001 | $0.001 |
That is $0.15 per 1,000 reviews on the free plan and from $0.10 per 1,000 reviews on Gold and above.
| Example | Free plan | Gold |
|---|---|---|
| 1,000 reviews | $0.15 | $0.10 |
| 1 Google Play app with 200 reviews + app details | $0.033 | $0.022 |
| 10 Google Play apps × 200 reviews + app details | $0.32 | $0.21 |
| Daily monitoring of 5 apps, ~20 new reviews a day, for 30 days | ≈ $0.12 | ≈ $0.09 |
| 100 apps, details only | $0.20 | $0.10 |
| Top 100 of one chart | $0.061 | $0.031 |
Never charged: apps that can't be found, storefronts where an app isn't sold, requests the stores refuse after all retries, reviews outside your date / star / keyword / reply filters, reviews already delivered before (monitoring mode), and duplicate reviews across countries. To cap a run, set Apify's Maximum cost per run: the scraper stops cleanly at the limit, across all event types and parallel sessions. Free-plan accounts are limited to 5 apps and 50 reviews per app per run (Apify Store rule); the log says so.
🚀 Quick start
1. Reviews of one app from both stores (the prefilled input):
{ "apps": ["https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580", "https://play.google.com/store/apps/details?id=com.spotify.music"], "countries": "us", "maxReviewsPerApp": 200 }
2. Export reviews to Excel: complaints only (1–2★) from the last 30 days, as flat rows. Run it, then click Export → Excel (or CSV) on the results:
{ "apps": ["com.spotify.music", "324684580"], "countries": "us, gb, de", "maxRating": 2, "reviewsNewerThan": "30 days", "outputFormat": "rows" }
3. Only new reviews, every day: schedule this as a task and connect Slack or a webhook (see Monitor new app reviews daily):
{ "apps": ["com.spotify.music", "324684580"], "onlyNewReviews": true, "includeAppDetails": false, "reviewSort": "newest", "maxReviewsPerApp": 200 }
How to scrape App Store reviews
- Paste App Store URLs (
https://apps.apple.com/us/app/…/id324684580) or numeric Apple ids into Apps. iOS bundle ids work too when Stores is set to App Store. - Set Countries. Each App Store storefront has its own reviews, so more countries means more reviews. For a sweep, use a preset:
top5,top10,top25,top50orall(every storefront). Reviews that show up in several storefronts are delivered once, and the run reports reviews per country. - Choose Max reviews per app (per country), Review order and any filters, then click Start.
Apple shows at most the 500 most recent reviews per app per country (see Why fewer reviews than requested?). App Store reviews have a title, app version and helpful votes.
How to scrape Google Play reviews
- Paste Google Play URLs (
https://play.google.com/store/apps/details?id=com.spotify.music) or package names (com.spotify.music). - Set Languages (e.g.
en, de): Google Play returns a different set of reviews per language. Thousands of reviews per app are possible. - Use Only reviews newer than with Newest first so paging stops at the date you need.
Google Play reviews include the app version, thumbs-up count and the developer's reply with its date.
Export App Store and Google Play reviews to CSV, Excel or Google Sheets
- Set Output format to Flat rows: one row per record, with the same columns on every row and in every run, so spreadsheets, BI imports and pivot tables keep working.
- After the run, use Export for CSV, Excel, JSON or XML, or the dataset API URL in Google Sheets (
=IMPORTDATA(...)withformat=csv), Make, Zapier or n8n. - The dataset has ready-made views: Overview, Reviews, App details, Search results & top charts, Per-app summary, Competitor comparison and Flat rows.
Monitor new app reviews daily
Turn on Only new reviews (monitoring). The scraper remembers, per store × app × country, which reviews it has already delivered (in your account's key-value store app-reviews-monitor), and delivers and charges only new ones. The first run is the baseline: it delivers what it fetches. Later runs that find nothing new succeed with 0 reviews and cost only the run start. The run's OUTPUT record and the per-app summaries report newReviewsCount.
Recipe:
- Create a task with your apps,
"onlyNewReviews": true,"reviewSort": "newest"and, usually,"includeAppDetails": false(details are charged on every run). - Schedule it (Apify Console → Schedules) daily or hourly.
- Get the new reviews where you work:
- Slack: add the Slack integration to the task, or a webhook on Run succeeded that posts
{{resource.defaultDatasetId}}items to a Slack incoming webhook. - Webhook / your backend: an Apify webhook on
ACTOR.RUN.SUCCEEDEDcalls your URL; fetchhttps://api.apify.com/v2/datasets/{defaultDatasetId}/items?clean=true. - Email, Sheets, Jira, Zendesk: Make, Zapier or n8n with the Apify app, trigger "Task run finished".
- Slack: add the Slack integration to the task, or a webhook on Run succeeded that posts
- Optional:
"maxRating": 2to alert on complaints only,"developerReplyFilter": "withoutReply"for reviews still waiting for an answer, or"includeKeywords": ["refund", "crash"]. Filtered-out reviews are remembered too, so they never come back as "new".
Use Monitor name (monitorKey) to keep separate monitors apart, for example one per team.
Compare competitor app reviews
List 2 or more apps (any mix of stores) and keep Competitor comparison on. You get one free comparison item with, per app: store rating, average rating of the fetched reviews, % of 1–2★ reviews, sentiment counts, top topics in negative reviews, developer reply rate, median reply time (hours), and average rating by week and by app version. In flat rows mode it becomes one row per app × metric, ready for a pivot table.
{ "apps": ["com.spotify.music", "com.apple.android.music", "deezer.android.app"], "maxReviewsPerApp": 500, "reviewsNewerThan": "90 days" }
Every review also carries sentiment (positive, neutral, negative: from the stars, nudged by a small word list with negation) and topics (crash-bug, login-account, ads, pricing-subscription, performance, ui-ux, support, feature-request, privacy), from keyword dictionaries in English, Spanish, German, French and Portuguese. They're computed locally, cost nothing, and can be turned off.
✅ Built for the problems other review scrapers have
Why fewer reviews than requested? The scraper says why, in the run log and, with app details on, in the app item's warnings:
- Apple's cap: Apple shows at most the 500 most recent reviews per app per country. Asking for 2,000 App Store reviews in one country gets 500 at most. For more, add countries or use a sweep preset (
top25,all): each storefront has its own 500, and duplicates are removed. - Your filters: reviews outside your date, star, keyword or reply filters are dropped, and they're free.
OUTPUT.reviewsFilteredcounts them. - The app has fewer reviews in that country or language.
- Your cost limit: the run stops cleanly at Maximum cost per run and says so.
No schema drift. Every review, app, listing and summary item has exactly the same fields in the same order for both stores, in every run. Missing data is null, never a missing key. New fields are only ever added at the end (as sentiment and topics were), and flat rows have a fixed column list (below).
The right app and country. Every item carries store, appId, appTitle and country, and the country always comes from your Countries setting, so you can check exactly what you got.
One error never crashes the run. Requests that get a 429, 403, 5xx or network error are retried on a fresh session with capped backoff. An app that still fails becomes an error item, not charged, and the rest of the run continues. Runs resume after restarts without charging anything twice.
Dates and versions. Dates are ISO 8601 (UTC). App versions are filled whenever the store publishes them.
📊 Output fields
Review (type: "review"), same fields for both stores:
| Field | Description |
|---|---|
store | ios or android |
appId, appTitle | Apple id / package name and app name |
country, language | Storefront and language the review was fetched for |
reviewId | The store's review id |
userName | Reviewer's public display name |
rating | Stars, 1–5 |
title, text | Review title (App Store) and text |
date | Review date, ISO 8601 |
version | App version the review was written for |
thumbsUp, voteCount | Helpful votes |
developerReplyText, developerReplyDate | Developer's reply |
url | Link to the review / reviews page |
scrapedAt | When it was scraped |
sentiment | positive, neutral or negative (null if tagging is off) |
topics | Topic ids, e.g. ["crash-bug", "ads"] (null if tagging is off) |
App details (type: "app"): title, developer and developer id, rating, rating count and 1–5 star histogram, price, currency, free / in-app purchase flags, installs (Android), version, released / updated dates, release notes, category, content rating, size, minimum OS, store URL, icon, screenshot count, data safety summary (Android; privacy is null for App Store apps), warnings.
Per-app summary (type: "summary", free, one per app × country): average rating, counts by star, % negative, average rating by version, top words in 1–2★ reviews, sentiment counts, topic counts, top negative topics, developer reply rate, oldest / newest review date, and newReviewsCount in monitoring mode.
Listing (type: "listing"): listingType (search or top-chart), query or collection/category, rank, appId, title, developer, rating, price, currency, free, url. Comparison (type: "comparison"): see above. Error (type: "error"): app, country and what went wrong; never charged.
Flat rows (Output format: rows): every row has these columns, in this order, in every run. Columns are only ever added at the end.
recordType, store, appId, appTitle, country, language, reviewId, userName, rating, title, text, date, version, thumbsUp, developerReplyText, developerReplyDate, developer, developerId, ratingCount, price, currency, free, installs, category, contentRating, released, updated, releaseNotes, listingType, query, collection, rank, summaryMetric, summaryKey, summaryValue, url, error, scrapedAt, sentiment, topics
recordType is review, app, listing, summary, comparison or error. Summary and comparison metrics use summaryMetric / summaryKey / summaryValue (e.g. averageRatingByWeek / 2026-W40 / 3.8). topics is one cell like crash-bug; ads.
A review item (Google Play):
{"type": "review","store": "android","appId": "com.spotify.music","appTitle": "Spotify: Music and Podcasts","country": "us","language": "en","reviewId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d51","userName": "Priya S","rating": 1,"title": null,"text": "Keeps crashing on my phone since the latest update. Ads every two songs and shuffle is broken.","date": "2026-10-04T15:02:44.000Z","version": "9.0.88.100","thumbsUp": 48,"voteCount": null,"developerReplyText": "Hi Priya, sorry about the crashes. Please reach out to us on the Spotify Community so we can take a closer look.","developerReplyDate": "2026-10-05T08:10:00.000Z","url": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d51","scrapedAt": "2026-10-06T09:00:00.000Z","sentiment": "negative","topics": ["crash-bug", "ads"]}
Input reference
| Input | Default | What it does |
|---|---|---|
apps | Spotify on both stores | App Store / Google Play URLs, Apple ids, package names (bundle ids with Stores = App Store) |
searchTerms | none | Find apps by name; the top maxSearchResults per store are fetched |
stores | both | both, ios or android |
countries | us | Country codes, e.g. us, gb, de; App Store sweep presets top5, top10, top25, top50, all |
languages | en | Languages for app details and Google Play reviews |
includeAppDetails | true | One app details item per app × country (charged) |
includeReviews | true | Review items (charged per review) |
maxReviewsPerApp | 200 | Per app, country and language |
reviewSort | newest | newest, rating or helpfulness |
reviewsNewerThan | none | Date (2026-01-31) or period (30 days) |
minRating, maxRating | 1, 5 | Star range |
includeKeywords, excludeKeywords | none | Keep / drop reviews containing these words (case- and accent-insensitive) |
developerReplyFilter | any | any, withReply or withoutReply |
addSentimentAndTopics | true | Free sentiment and topics on every review |
includeSummary | true | Free per-app summary per country |
includeComparison | true | Free comparison item when 2+ apps are covered |
onlyNewReviews | false | Monitoring: deliver and charge only reviews not delivered before |
monitorKey | default | Name of the monitor (keeps independent monitors apart) |
includeSearchResults | false | Also deliver search result lists (charged per entry) |
maxSearchResults | 20 | Apps per search and entries per top chart |
topCharts | none | Charts as collection:category, e.g. topselling_free:GAME |
outputFormat | items | items (JSON) or rows (flat, spreadsheet-ready) |
proxyConfiguration | off | Apify Proxy, if you see many retries |
maxConcurrency | 4 | Parallel sessions (1–10) |
maxRetries | 6 | Retries per request on a fresh session |
More input examples
Find competitors by name and get their details and reviews, plus the search result lists:
{ "searchTerms": ["budget planner", "expense tracker"], "stores": "both", "maxSearchResults": 10, "includeSearchResults": true, "maxReviewsPerApp": 100 }
App Store sweep: the 25 biggest storefronts, newest 100 reviews each, reviews only:
{ "apps": ["324684580"], "stores": "ios", "countries": "top25", "maxReviewsPerApp": 100, "includeAppDetails": false }
Top charts only:
{ "topCharts": ["topselling_free:GAME", "topgrossing:FINANCE", "topfreeapplications:6014", "topgrossingapplications"], "countries": "us, jp", "maxSearchResults": 50 }
Google Play chart names: topselling_free, topselling_paid, topgrossing, optionally with a category such as GAME, GAME_PUZZLE, FINANCE, PRODUCTIVITY, SOCIAL. App Store feeds: topfreeapplications, toppaidapplications, topgrossingapplications, newapplications, newfreeapplications, newpaidapplications, optionally with a numeric genre id (6014 Games, 6015 Finance, 6005 Social Networking, 6007 Productivity).
🔌 Integrations: API, Make, Zapier, n8n, MCP
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });const run = await client.actor('AaronOptimus/app-store-reviews-scraper').call({apps: ['com.spotify.music', 'https://apps.apple.com/us/app/spotify-music-and-podcasts/id324684580'],countries: 'us',maxReviewsPerApp: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python:
from apify_client import ApifyClientclient = ApifyClient("MY_APIFY_TOKEN")run = client.actor("AaronOptimus/app-store-reviews-scraper").call(run_input={"apps": ["com.spotify.music", "324684580"],"countries": "us","maxReviewsPerApp": 100,})items = client.dataset(run["defaultDatasetId"]).list_items().items
- Make, Zapier, n8n: use the Apify app/node: "Run Actor" or "Run task", then "Get dataset items". Pair with Only new reviews for alerts.
- Webhooks and Slack: Apify integrations on the task (Slack, email, webhooks, GitHub, Google Drive).
- AI agents (MCP): call the scraper as a tool through Apify's MCP server: "get the latest 1-star reviews of app X and their top topics" becomes one structured tool call.
🎯 Use cases
- ASO and product teams: ratings by version and by week, the complaints behind a rating drop, iOS vs Android side by side.
- Competitor monitoring: weekly comparison of your category's apps; top negative topics and reply rates.
- Support and QA: new 1–2★ reviews without a developer reply, routed to the right team.
- Investors and analysts: review velocity, rating trends and installs across a portfolio and markets.
- Research and AI: a clean, tagged corpus of reviews with ratings, dates and versions.
💡 Tips
- Big lists: raise Parallel sessions to 8–10, turn off app details if you only need reviews, and use Only reviews newer than with Newest first.
- Sweeps are polite on purpose: App Store requests are spaced out across all parallel sessions, so a
top50orallsweep takes a few minutes per app. - Rate limits: proxy is off by default because both stores accept moderate datacenter traffic. If the log shows many retries, turn on Apify Proxy or lower Parallel sessions.
- App Store privacy labels aren't included (
privacyisnullfor App Store apps); Google Play apps get the data safety summary.
❓ FAQ
How many reviews can I get? Google Play: thousands per app, country and language (150 per page, paginated). App Store: up to the 500 most recent per app per country, so a top25 sweep can return up to 12,500 per app.
Is Apple's reviews feed reliable? Mostly. Apple's public reviews feed is tried first on every run. On days when it comes back empty or unavailable for an app (it did briefly in early October 2026), the scraper falls back to the reviews shown on the public App Store web page: about 10 per device view, so 10–40 per app per country, chosen by Apple, with developer replies but without app version or helpful votes. The app item's warnings and the log say when that happened, and OUTPUT.appleWebPageFallbacks counts it.
Does it sort by rating on the App Store? Apple only offers "most recent" and "most helpful". For Highest rating first, the most recent reviews are fetched and sorted by rating locally.
How does "Only new reviews" decide what's new? A review is new if its id wasn't delivered (or filtered out) by an earlier run with the same monitor name, and it isn't older than the newest review seen before minus 3 days (stores sometimes publish reviews late). Edited reviews keep their id, so they aren't sent again.
How accurate are sentiment and topics? They're keyword-based: fast, free, transparent and consistent between runs, but not an AI model. Sentiment leans on the stars, so a 1★ review is always negative and a 5★ review always positive. For nuanced analysis, feed the review text to your LLM of choice; the tags are a good first filter.
What happens when a store blocks a request? It's retried on a fresh session with capped backoff (and a fresh IP with Apify Proxy). If an app still fails, it's delivered as an error item and not charged; the rest of the run continues.
Can I search for apps by name? Yes. Search terms are searched in the selected store(s) and the top Max results per search apps are fetched with details and reviews. Turn on Include search results to also get the ranked result list.
Is it legal? The scraper only reads publicly available store pages and feeds: no login, no CAPTCHA solving, no private APIs. Reviewer names are the public display names the stores show to everyone. You're responsible for using the data in line with the stores' terms and your local laws, including data-protection rules if you store reviewer names.
🛠 Support
Found a problem or need a feature? Open an issue on the Issues tab. See the Changelog for updates.