Google Play Reviews - App Ratings, Replies & Countries avatar

Google Play Reviews - App Ratings, Replies & Countries

Pricing

from $1.00 / 1,000 reviews

Go to Apify Store
Google Play Reviews - App Ratings, Replies & Countries

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 $1.00 / 1,000 reviews

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

0

Monthly active users

7 days ago

Last modified

Security

Limited permissions

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.

All filters run before the Max reviews budget is counted and before anything is billed, so reviews that do not match are never charged. Reviews are always de-duplicated by their unique review id (across countries too), so there is no separate unique-only switch. Each review carries position, its 1-based rank in the order Google Play served it for that app and country in this run; it changes with sort order and is ignored by Incremental mode change detection. Google Play does not expose a device type or a "reviewed in" label on the reviews feed, so those are not offered.

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 Google Play links: app pages, search pages, developer pages, category pages or collection pages. 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.

FieldExample
reviewId"00000000-0000-0000-0000-000000000000"
appId"com.example.app"
appNamenull unless Enrich with app details is on
country"us"
language"en"
rating5
body"Full review text appears here."
author"Reviewer Name"
authorId"100000000000000000000"
authorImage"https://play-lh.googleusercontent.com/..."
thumbsUp12
appVersion"1.0.0"
reviewDate"2026-01-01T00:00:00+00:00"
reviewTimestamp1767225600
reviewUrlGoogle 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

  1. Pick a mode: search (by app name or keyword) or url (paste Google Play links or bare package ids).
  2. Choose the countries to sweep, the sort order, the review language, and an optional minimum/maximum rating.
  3. Optionally turn on Enrich with app details, and set Max reviews to control run size and cost.
  4. 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
}

URL shapes accepted in URL mode:

ShapeExample
App page with hl/glhttps://play.google.com/store/apps/details?id=com.instagram.android&hl=en&gl=us
App page, id onlyhttps://play.google.com/store/apps/details?id=com.instagram.android
App page, other localehttps://play.google.com/store/apps/details?id=com.instagram.android&hl=de&gl=de (hl/gl seed language and country)
Shared review linkhttps://play.google.com/store/apps/details?id=com.instagram.android&reviewId=x (the app is read from id)
Show all reviews linkhttps://play.google.com/store/apps/details?id=com.instagram.android&showAllReviews=true
Legacy hosthttps://market.android.com/details?id=com.instagram.android
Search pagehttps://play.google.com/store/search?q=instagram&c=apps&hl=en&gl=us
Developer page (numeric id)https://play.google.com/store/apps/dev?id=5700313618786177705
Developer page (name)https://play.google.com/store/apps/developer?id=Instagram
Category pagehttps://play.google.com/store/apps/category/SOCIAL
Collection pagehttps://play.google.com/store/apps/collection/topselling_free

Search, developer, category and collection pages expand to the top apps on the page, at most Apps per search term per URL (default 1). An app link whose package does not exist (HTTP 404) is skipped with a warning in the log. Behaviour change: URL mode run with Google Play URLs left untouched now scrapes one example of each shape above (previously it had no default and needed your own links). Replace the list with your own links to scrape specific apps.

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 ApifyClient
client = 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.

Output views

The dataset has four views: Reviews (the main table, including position), Changes (incremental changeType, changedFields, first/last seen), App details (the app-level fields when enrichment is on) and Developer replies (reviews that have a developer reply). Multi-app or multi-country runs also store a run summary under the OUTPUT key of the key-value store.

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 classified NEW, UPDATED (with changedFields), or UNCHANGED (suppressed and not billed unless emitUnchanged is on). Rating, review text, author, thumbs-up count, app version and developer replies are all compared; app-level metadata attached by fetchDetails (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.
  • Ignore fields when detecting changes (ignoreFieldsForChanges, incremental mode only) lists output field names (for example thumbsUp, developerReply or developerReplyDate; review rows are flat, so dotted paths are accepted but not needed) left out of the changed/unchanged decision and out of changedFields; they still appear in each row. Changing the list never turns already-tracked reviews into UPDATED.
  • EXPIRED is 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, AND emitExpired is 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. REAPPEARED never happens "by default": it only fires for a review that a PRIOR complete scan already marked EXPIRED, and a LATER run finds again.
  • stateKey names or shares the tracked campaign; leave it empty to derive one automatically from mode, queries/urls, countries, language, sort order, rating filters and fetchDetails (Max reviews, Max pages and delivery options do not affect it).
  • Combining resumeFromRunId with incrementalMode only 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.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where review pages should be created.
  4. maxNotifyListings caps 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

ParameterTypeDefaultDescription
modestringsearchsearch (by app name) or url (paste app links).
queriesarrayno default (prefill: ["Instagram"])App names or keywords to look up (search mode).
appsPerQueryinteger1Top matching apps to take per search term (search mode).
urlsarrayone example of each URL shape listed aboveGoogle Play app, search, developer, category or collection links, or bare package ids (url mode).
countriesarrayno 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.
languagestringenReview language / locale code.
sortBystringnewestnewest, mostHelpful, rating, or mostRelevant (Google Play's relevance order, the same order as mostHelpful).
minRatingintegerno default (optional)Keep only reviews at or above this star rating (1-5).
maxRatingintegerno default (optional)Keep only reviews at or below this star rating (1-5).
appIdOrUrlstringno default (optional)Single-app shortcut: one app link or package id. Switches the run to URL mode and replaces the Start URLs list, so only this app is scraped.
ratingintegerno default (optional)Exact star rating (1-5); shortcut for setting Min and Max rating to the same value.
keywordsarrayno default (optional)Keep only reviews whose text contains at least one of these words (case-insensitive).
appVersionarrayno default (optional)Keep only reviews written on one of these app versions.
startDatestringno default (optional)Keep reviews from this day on (YYYY-MM-DD, UTC). With newest-first sorting the walk stops once it passes the start date.
endDatestringno default (optional)Keep reviews up to this day (YYYY-MM-DD, UTC).
recentDaysinteger0Keep only reviews from the last N days (0 = no limit).
fetchDetailsbooleanfalseAttach app metadata to each review from that app.
maxItemsinteger20Total review cap. 0 means no limit.
maxPagesintegerno default (optional)Safety bound on review pages read per country (about 40 reviews per page). Leave empty to walk every page Google Play serves, up to a hard limit of 1000 pages per country. Max reviews is capped at 1000000.
resumeFromRunIdstringno default (optional)Run id (or dataset id) of a previous run. Reviews it already collected are skipped.
incrementalModebooleanfalseRecurring monitoring: classifies each review as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED against the previous run of the same campaign.
stateKeystringno default (optional; auto-derived)Name this monitoring campaign explicitly, instead of an automatic hash of your search/filter settings.
emitUnchangedbooleanfalseAlso return (and bill for) reviews unchanged since the last run.
emitExpiredbooleanfalseAlso return (and bill for) a tombstone row for reviews the previous run saw that this run no longer finds.
ignoreFieldsForChangesarraynone (optional)Incremental mode only: output field names (for example thumbsUp) ignored when deciding whether a review changed.
proxyobject{"useApifyProxy": true}Connection settings.
mcpConnectorsarrayno default (optional)Send a summary of each review to apps you authorized under Integrations.
notionParentPageUrlstringno default (optional)Notion connector only: page under which review pages are created.
maxNotifyListingsinteger50Cap 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 connection uses Apify datacenter proxies, which were measured to load Google Play app pages, search pages and the reviews feed the same as residential, so no residential proxy or paid proxy add-on is required for normal runs. A paid Apify plan is still needed for any Apify proxy access: Apify free plans do not include proxies, and a run whose proxy connection is refused for the account stops with a clear message (see the FAQ). If you supply your own proxy URLs, they are used as given.

When the default connection becomes unavailable mid-run, the log prints "The selected connection is unavailable to this run." and the run continues on a backup connection. Once pages are served that way it logs "Served over the backup connection (the default connection was unavailable)." Any cost of the backup connection is billed to the user's own proxy usage; no extra Actor charge applies.

FAQ

How much does it cost?

You pay per review returned (one billed unit for each review row delivered to the dataset), plus a detail-enrichment charge of one unit per app, applied once per run only to an app whose enriched reviews you actually receive when Enrich with app details is on, never for the metadata lookup alone. Reviews removed by your filters, duplicates, unchanged incremental rows and failed requests are never billed. The Pricing tab shows the current rates. Use Max reviews to cap the cost of any run.

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". Which message you see tells you why:

  • "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required" means the account has no proxy access (or your own proxy URLs have invalid credentials).
  • "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Google Play pages." means the default and backup connections both failed; upgrade your plan or supply your own proxy URLs.
  • "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search." means a transient connection problem; try again later.

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...
🤖 Suno Scraper
Collect public Suno music data: songs with lyrics, style tags, model version, play and...
📱 TrustMate.io
Scrape complete company review histories from TrustMate.io. Paste company profile URLs...
📇 Google Maps Scraper
Extract business data from Google Maps at scale. Get names, addresses, phone numbers...
🤖 Udio Scraper
Collect public Udio tracks with the complete generation prompt, full lyrics, style tags...
🧩 Trustpilot Scraper
Scrape Trustpilot business profiles and reviews on any country domain: TrustScore, the...

👉 Browse all abotapi scrapers

💬 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.