Google Play Reviews – App Ratings, Replies & Countries
Pricing
from $0.80 / 1,000 reviews
Google Play Reviews – App Ratings, Replies & Countries
Collect Google Play reviews and ratings for any app across country storefronts. Search by app name or use a Google Play URL. Returns one row per review with rating, text, author, date, app version, thumbs-up count, developer reply, and storefront country.
Pricing
from $0.80 / 1,000 reviews
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
Google Play Reviews Scraper: Ratings, Text & Developer Replies
Google Play Reviews Scraper turns Google Play Store reviews into a clean, structured dataset. Get the star rating, review text, author, date, app version, thumbs-up count and developer replies for any app, across as many country storefronts as you choose. Search by app name or paste Google Play links (a bare package id like com.example.app works too), then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Reviews are the primary output. Every row is one full review: rating, body, author, date, app version, thumbs-up, developer reply, plus the storefront country and language.
- Two ways in. Search by app name or keyword, or paste one or more Google Play app links. A bare package id works too, no need to build a full URL.
- Multi-country sweep. Reviews are storefront-specific, so pass a list of country codes, or use
"all"for a broad built-in set of major markets, to gather the full picture for one app. - Sort and filter. Order by newest, most helpful, or by rating, and keep only reviews within a minimum/maximum star band.
- Optional app-metadata enrichment. Attach developer, average score, ratings count, installs, category, price and more to every review from that app.
- Built for schedules. Incremental mode returns only new and changed reviews on recurring runs, and a refused run fails loudly instead of returning an empty dataset.
- Resume without re-billing. Continue an interrupted run from its own run or dataset id; reviews it already collected are skipped and not re-charged.
Use Cases
- App Store Optimization (ASO) teams: track rating trends and recurring complaint themes across storefronts to prioritize the release roadmap.
- Customer support and QA teams: catch new low-rated reviews quickly and route them into a ticketing pipeline before ratings drop further.
- Competitive analysis: compare review volume, rating trends and developer response patterns across competing apps.
- Localization and product teams: sweep multiple countries to see how the same app is received in different markets and languages.
- Data science and NLP teams: build labeled datasets of app reviews for sentiment or topic modeling.
Data You Get
Sample shape: values are illustrative placeholders, not from a live review.
| Field | Example |
|---|---|
reviewId | "00000000-0000-0000-0000-000000000000" |
appId | "com.example.app" |
appName | null unless Enrich with app details is on |
country | "us" |
language | "en" |
rating | 5 |
body | "Full review text appears here." |
author | "Reviewer Name" |
authorId | "100000000000000000000" |
authorImage | "https://play-lh.googleusercontent.com/..." |
thumbsUp | 12 |
appVersion | "1.0.0" |
reviewDate | "2026-01-01T00:00:00+00:00" |
reviewTimestamp | 1767225600 |
reviewUrl | Google Play link to that specific review |
developerReply | "Thanks for the feedback!" |
developerReplyDate | "2026-01-02T00:00:00+00:00" |
Every review also carries appName, which is null unless Enrich with app details is on. With enrichment turned on, every review from that app additionally carries appDeveloper, appDeveloperEmail, appDeveloperWebsite, appScore, appRatingsCount, appInstalls, appCategory, appContentRating, appPrice, appCurrency, appIconUrl, appUpdated and appDescription, plus an appStoreUrl back to the app's listing. With enrichment off (the default), all of those appXxx fields and appStoreUrl are absent. In Incremental mode, every row also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt; see How to Use below for exactly when each fires.
How to Use
- Pick a mode:
search(by app name or keyword) orurl(paste Google Play links or bare package ids). - Choose the countries to sweep, the sort order, the review language, and an optional minimum/maximum rating.
- Optionally turn on Enrich with app details, and set Max reviews to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Search by app name:
{"mode": "search","queries": ["Instagram", "Spotify"],"appsPerQuery": 1,"countries": ["us"],"sortBy": "newest","maxItems": 100}
Sweep several countries for one app via its link:
{"mode": "url","urls": ["https://play.google.com/store/apps/details?id=com.instagram.android"],"countries": ["us", "gb", "de", "jp"],"sortBy": "mostHelpful","maxItems": 500}
Only high-rated reviews, with app details attached:
{"mode": "url","urls": ["https://play.google.com/store/apps/details?id=com.instagram.android"],"countries": ["us"],"minRating": 4,"fetchDetails": true,"maxItems": 200}
Recurring monitoring, including reviews that disappear:
{"mode": "url","urls": ["https://play.google.com/store/apps/details?id=com.instagram.android"],"countries": ["us"],"incrementalMode": true,"stateKey": "instagram-us-daily","emitExpired": true,"maxItems": 0,"maxPages": 0}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/google-play-reviews-scraper").call(run_input={"mode": "url", "urls": ["com.instagram.android"], "countries": ["us"], "maxItems": 100})for review in client.dataset(run["defaultDatasetId"]).iterate_items():print(review["rating"], review["author"], review["body"][:80])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/google-play-reviews-scraper').call({mode: 'url', urls: ['com.instagram.android'], countries: ['us'], maxItems: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Multi-country sweeps and "all"
Reviews are storefront-specific: each country returns its own review stream for the same app. Leave Countries empty to use the country from each URL (url mode) or us (search mode), or set it to ["all"] to sweep a broad built-in set of major storefronts in one run. Max reviews is split evenly across every app/country stream so one popular storefront cannot use up the whole budget before the others get a turn.
Resume and Incremental mode (recurring monitoring)
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset id and the actor skips every review it already collected there, so you don't pay twice. - Incremental mode (
incrementalMode) is for scheduled runs against the same app/country/filter set. Each review is classifiedNEW,UPDATED(withchangedFields), orUNCHANGED(suppressed and not billed unlessemitUnchangedis on). Rating, review text, author, thumbs-up count, app version and developer replies are all compared; app-level metadata attached byfetchDetails(developer, install count, category, ...) is excluded from comparison, since it describes the app, not the individual review, and changes on its own as other users interact with the app. EXPIREDis only ever reported after a run that fully re-walked every tracked app/country stream, with no Max reviews/Max pages cut, no resume, and no checkpoint recovery mid-run, ANDemitExpiredis on. A capped, partial or resumed run cannot tell "review deleted" apart from "not reached yet", so it skips this detection entirely and leaves the previous state untouched.REAPPEAREDnever happens "by default": it only fires for a review that a PRIOR complete scan already markedEXPIRED, and a LATER run finds again.stateKeynames or shares the tracked campaign; leave it empty to derive one automatically from mode, queries/urls, countries, language, sort order, rating filters andfetchDetails(Max reviews, Max pages and delivery options do not affect it).- Combining
resumeFromRunIdwithincrementalModeonly works to bootstrap a brand-new campaign from an earlier non-incremental run's dataset. Once a campaign already has tracked state, the run fails fast instead of silently reclassifying a partial delta against a baseline it never fully built.
Send results into your apps (MCP connectors)
Optionally pipe the scraped reviews into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each review, not the full JSON. Each review becomes one entry with a heading (the app's name when Enrich with app details is on, otherwise its package id, plus the star rating) and its key fields (country, rating, author, date, app version) flattened to plain text, plus the review body. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where review pages should be created. maxNotifyListingscaps how many reviews are sent to each connector per run; it never affects the dataset.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search (by app name) or url (paste app links). |
queries | array | no default (prefill: ["Instagram"]) | App names or keywords to look up (search mode). |
appsPerQuery | integer | 1 | Top matching apps to take per search term (search mode). |
urls | array | no default (prefill: ["https://play.google.com/store/apps/details?id=com.instagram.android"]) | Google Play app links or bare package ids (url mode). |
countries | array | no default (prefill: ["us"]) | Country codes to collect reviews from. Empty uses the link's country or us. "all" sweeps a broad built-in set of major markets. |
language | string | en | Review language / locale code. |
sortBy | string | newest | newest, mostHelpful, or rating. |
minRating | integer | no default (optional) | Keep only reviews at or above this star rating (1-5). |
maxRating | integer | no default (optional) | Keep only reviews at or below this star rating (1-5). |
fetchDetails | boolean | false | Attach app metadata to each review from that app. |
maxItems | integer | 20 | Total review cap. 0 means no limit. |
maxPages | integer | no default (optional) | Safety bound on review pages read per country (about 40 reviews per page). Leave empty to walk every page Google Play serves. |
resumeFromRunId | string | no default (optional) | Run id (or dataset id) of a previous run. Reviews it already collected are skipped. |
incrementalMode | boolean | false | Recurring monitoring: classifies each review as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED against the previous run of the same campaign. |
stateKey | string | no default (optional; auto-derived) | Name this monitoring campaign explicitly, instead of an automatic hash of your search/filter settings. |
emitUnchanged | boolean | false | Also return (and bill for) reviews unchanged since the last run. |
emitExpired | boolean | false | Also return (and bill for) a tombstone row for reviews the previous run saw that this run no longer finds. |
proxy | object | {"useApifyProxy": true} | Connection settings. |
mcpConnectors | array | no default (optional) | Send a summary of each review to apps you authorized under Integrations. |
notionParentPageUrl | string | no default (optional) | Notion connector only: page under which review pages are created. |
maxNotifyListings | integer | 50 | Cap on reviews written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live review.
{"reviewId": "00000000-0000-0000-0000-000000000000","appId": "com.example.app","country": "us","language": "en","rating": 5,"body": "Full review text appears here.","author": "Reviewer Name","authorId": "100000000000000000000","authorImage": "https://play-lh.googleusercontent.com/...","thumbsUp": 12,"appVersion": "1.0.0","reviewDate": "2026-01-01T00:00:00+00:00","reviewTimestamp": 1767225600,"reviewUrl": "https://play.google.com/store/apps/details?id=com.example.app&reviewId=00000000-0000-0000-0000-000000000000","developerReply": "Thanks for the feedback!","developerReplyDate": "2026-01-02T00:00:00+00:00"}
Plan Requirement
The default proxy setting works out of the box on any Apify plan. For large multi-country sweeps or frequent scheduled runs, a proxy group with more exit rotation can help; pick it under Connection.
FAQ
How much does it cost?
You pay per review returned, plus a one-time app-detail surcharge that applies only to an app whose reviews you actually receive when Enrich with app details is on, never for the metadata lookup alone. The Pricing tab shows the current rates. Use Max reviews to cap the cost of any run.
Is it legal to scrape Google Play?
This actor collects only publicly available review data. You are responsible for how you use it: follow Google Play's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Reviews are user-generated content and may carry rights beyond the platform's own terms.
Can I get only new or changed reviews on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated reviews for the tracked app/country set, and unchanged ones are not billed.
Why is appName / appDeveloper / appScore empty on my reviews?
Those fields, along with the rest of the app-metadata block, are only attached when Enrich with app details is turned on. With it off (the default), appName is null and every other appXxx field is absent from the output.
Why did my run fail instead of returning an empty dataset?
If every request was refused, or if none of your search terms, URLs or package ids could be resolved into an app, the run stops with a clear message so a genuine block is never confused with "this app has no reviews". Retry with an Apify Residential proxy. A run that reached Google Play fine and simply found zero matching reviews still completes normally with an empty dataset.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more social media data?
Pair this actor with these related scrapers from the same team:
| 📇 Apple App Store Reviews Scrape Apple App Store reviews across 150+ country storefronts. Search by app name or URL... | 📱 TrustMate.io Scrape complete company review histories from TrustMate.io. Paste company profile URLs... |
| 🤖 Suno Scraper Collect public Suno music data: songs with lyrics, style tags, model version, play and... | 📇 Google Maps Scraper Extract business data from Google Maps at scale. Get names, addresses, phone numbers... |
| 🧩 Trustpilot Scraper Scrape Trustpilot business profiles and reviews on any country domain: TrustScore, the... | 📱 Mastodon From $1/1K. Scrape trending Mastodon profiles and related posts from any Mastodon... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.