Google Play Reviews Scraper | Android App Reviews avatar

Google Play Reviews Scraper | Android App Reviews

Pricing

from $0.05 / 1,000 review delivereds

Go to Apify Store
Google Play Reviews Scraper | Android App Reviews

Google Play Reviews Scraper | Android App Reviews

Scrape Google Play Store reviews by app, country and language. Export ratings, text, app versions and developer replies to JSON/CSV. Filter dates, stars and keywords for Android feedback monitoring.

Pricing

from $0.05 / 1,000 review delivereds

Rating

0.0

(0)

Developer

tingyou333 zhuang

tingyou333 zhuang

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 hours ago

Last modified

Share

Ready-to-use example: Open the preconfigured workflow. Review or change the target before starting; runs use your own account credits.

Practical tutorial: How to export low-star Google Play reviews for release feedback.

Scrape Google Play Store reviews by app, country and language. Export ratings, text, app versions and developer replies to JSON/CSV. Filter dates, stars and keywords for Android feedback monitoring.

Useful for: Monitor Android release feedback; find low-star complaints; compare apps across countries and languages.

Why choose this Actor: Batch apps and locales, filter reviews and suppress duplicates. Supported input envelopes and output projections help migrate existing review workflows.

Try a small sample

  1. Click Try for free, then open Input and switch to JSON.
  2. Paste the example below and click Start. It uses a small result limit.
  3. Open the dataset to inspect results, then export JSON, CSV or Excel. Source restrictions can still cause partial or failed runs.
{
"appIds": [
"com.whatsapp"
],
"maxReviews": 20
}

Cost at a glance

Primary billing unit: Review delivered. Rates below are per 1,000 primary events.

Free planStarter / BronzeScale / SilverBusiness / Gold and higher
$0.08$0.07$0.06$0.05

Platform compute, proxy, transfer and storage are additional. Other event types, where enabled, are listed in the Pricing tab. “Try for free” uses available account credits; it does not make usage unlimited or unmetered.

Coverage to know: The source controls available reviews and reply fields. Filters can require more requests than the number of reviews ultimately delivered.

For Apple App Store reviews, see our companion Actor. It runs and bills separately.

Guides and full reference

Workflows · Pricing details · Inputs · API · FAQ

Form prefills, schema defaults and empty API input can differ. Use explicit targets and limits; see the technical reference for source and default behavior.

Locale selection and detailed ratings

The Input form offers 52 country and 54 language suggestions, with separate multi-country and multi-language fields. Custom values remain available; the source determines which combinations return data. Country selects a storefront and language selects a review language, not automatic translation.

criterias preserves Google's available category ratings as { "criteria": "vaf_app_quality_ads_presence", "rating": 1 } objects. These category-specific ratings are separate from the overall 1–5 review score. Missing ratings are not fabricated; an empty list means no parsed category ratings were supplied. Malformed entries generate warnings while valid siblings are retained.

Common workflows

Compare two Android apps

{
"appIds": [
"com.whatsapp",
"org.telegram.messenger"
],
"maxReviews": 40
}

Collect English and German locale results

{
"appIds": [
"com.whatsapp"
],
"languages": [
"en",
"de"
],
"maxReviews": 40
}

Keep reviews with developer replies

{
"appIds": [
"com.whatsapp"
],
"includeRepliesOnly": true,
"maxReviews": 20
}

Output at a glance

Illustrative field subset below; these are example values, not a captured customer review or a claim about source coverage. Native and compatibility output profiles can differ.

{
"type": "review",
"appId": "com.whatsapp",
"reviewId": "example-review-id",
"content": "Example feedback used to illustrate the output format.",
"score": 4,
"country": "us",
"language": "en",
"replyContent": null,
"coverage": "complete",
"warnings": []
}

Google Play review totals are not a promise of retrievable written reviews. Locale queries do not classify the actual language of each review. Pages, source access and your global cap can limit results. Replies and version fields may be null.

Pricing

Pay per delivered event, with automatic discounts based on your Apify subscription plan. These are result fees in USD, not separate subscriptions sold by this Actor. All tiers have the same Actor features. Apify compute, storage, transfers and any proxy usage are charged additionally.

Billable event (1,000 events)FreeStarterScaleBusiness
Review delivered$0.08$0.07$0.06$0.05

Platinum and Diamond currently use the Business rate. The Pricing tab is the source of truth for the active schedule and your applicable plan.

  • Review delivered: One delivered review after filtering and output mapping. Error rows have no result fee. Apify platform usage is additional.

Example on the Free plan: 10 / 1,000 / 10,000 events cost $0.0008 / $0.08 / $0.8 in result fees, plus platform usage.

There is no additional developer setup or monthly rental fee. A run with no billable results can still consume platform resources. Start small, cap results and review run costs before scheduling a larger workload. Requested counts are ceilings, not guaranteed deliveries.

Input reference

Fields below are grouped like the Input form. Optional fields need not be supplied. Compatibility input envelopes and transformations are explained in the technical reference.

Targets and collection

FieldTypeDefaultMeaning
appIdOrUrlstringNot setSingle-app compatibility input, e.g. com.whatsapp or a Play Store app URL.
appIdsarrayNot setMultiple Google Play package IDs in one run.
startUrlsarrayNot setCompatibility input containing Google Play app detail URLs.
countrystring"US"Google Play country code used by the review RPC, e.g. US, GB, KR. Select a suggested locale or enter a custom code. Locale selection does not detect the language of each review.
countriesarrayNot setOptional multi-country extension. When supplied, each app is queried for each country and review IDs are deduplicated.
languagestring"en"Google Play query locale, e.g. en or de. all sweeps the documented fixed locale list in round-robin pages; maxReviews is a global cap, not per language. This does not classify review text language. Select a suggested locale or enter a custom code. Locale selection does not detect the language of each review.
languagesarrayNot setExplicit query locales, or ["all"] for the fixed locale sweep. Queried round-robin; unvisited sources are reported when the global limit is reached.
deviceTypestring"mobile"Google Play device review context.
keywordsarrayNot setReturn reviews containing at least one keyword, case-insensitive.
appVersionarrayNot setOptional exact app-version allow-list.
sincestringNot setISO date/timestamp for scheduled incremental monitoring.
recentDaysinteger0Return reviews from the most recent N days; 0 disables this filter.
startPageinteger1Compatibility page offset. Earlier pages are fetched only to obtain Google's continuation token, then discarded.
pagesToScrapeinteger-1Maximum RPC pages per app/country after startPage. -1 means continue until maxReviews/maxItems or source exhaustion.
reviewsPerPageinteger100Requested reviews per Google Play RPC call.
requestDelayMillisinteger0Optional delay before each RPC attempt.
untilstringNot settheagents-compatible LOWER date bound: returns reviews newer than this date. Combined with since using the later bound. Use endDate for an upper bound.
neatratInputobjectNot setExplicit Neatrat migration: paste the original input object here. Do not combine with native fields (unchanged platform defaults are ignored). outputSchema remains top-level and independent. Preserves language arrays and defaults mostRelevant / 5 pages / 10000 reviews. Missing language uses en query locale; text-language filter equivalence is unproven.
wolvesInputobjectNot setExplicit thewolves migration: paste the original input object here. Do not combine with native fields (unchanged platform defaults are ignored). outputSchema remains top-level and independent. Requires explicit positive maxItems: competitor has UI prefill only, no documented API default. No explicit page limit; native safety bounds apply.
theagentsInputobjectNot setExplicit theagents migration: paste the original input object here. Do not combine with native fields (unchanged platform defaults are ignored). outputSchema remains top-level and independent. Requires explicit positive maxItems: competitor has UI prefill only, no documented API default. No explicit page limit; native safety bounds apply.

Filters and ordering

FieldTypeDefaultMeaning
sortstring"NEWEST"Compatibility sort: NEWEST, RATING or HELPFULNESS/MOST_RELEVANT.
sortBystringNot setAlternative compatibility sort used by another major Actor.
ratingintegerNot setReturn reviews with exactly one star rating from 1 to 5.
ratingFilterarrayNot setReturn only reviews whose score is in this 1-5 allow-list. Numeric arrays such as [1,2] are supported for migration compatibility.
endDatestringNot setCompatibility upper date bound in YYYY-MM-DD or ISO format.
includeRepliesOnlybooleanfalseReturn only reviews that have a developer reply.
uniqueOnlybooleantrueDeduplicate by reviewId across pages/apps/countries.
ratingsarrayNot setAdditional allowed ratings, merged with ratingFilter.

Result limits and cost

FieldTypeDefaultMeaning
maxReviewsintegerNot setCompatibility maximum number of saved reviews across the run. -1 uses maxItems or the safety ceiling. Defaults to 1000 only when neither limit is supplied.
maxItemsintegerNot setAlternative compatibility maximum. When supplied with maxReviews, the lower positive limit wins.
maxRequestRetriesinteger2Retries transient HTTP/rate-limit/network failures.

Compatibility and transformations

FieldTypeDefaultMeaning
customMapFunctionstringNot setJavaScript function applied after output formatting to each review. Must return one JSON object. Isolated runtime with no network, file system or Python access; 50ms CPU and 16MB per row, 10s total. Not a filter.
outputSchemastring"extended"Explicit migration format. Missing source values stay null; extended preserves diagnostics.

Connection and advanced settings

FieldTypeDefaultMeaning
proxyConfigurationobjectNot setAccepted for migration compatibility. The validated public RPC path does not require or use a proxy.

Output reference

The table describes native fields; fields can be absent or null when the source does not provide them. Error rows and selected compatibility profiles have different shapes. Nested objects remain structured in JSON; CSV exports may serialize them.

FieldTypeMeaning
typestringType
appIdstringApp ID
reviewIdstringReview ID
id['string', 'null']Compatibility review ID
userName['string', 'null']User
userImage['string', 'null']User image
content['string', 'null']Review
text['string', 'null']Compatibility review text
score['integer', 'null']Score
scoreText['string', 'null']Compatibility score text
thumbsUpCount['integer', 'null']Helpful votes
thumbsUp['integer', 'null']Compatibility helpful votes
reviewCreatedVersion['string', 'null']Review app version
at['string', 'null']Review date
date['string', 'null']Compatibility review date
replyContent['string', 'null']Developer reply
replyText['string', 'null']Compatibility developer reply
repliedAt['string', 'null']Reply date
replyDate['string', 'null']Compatibility reply date
appVersion['string', 'null']App version
version['string', 'null']Compatibility app version
url['string', 'null']Review URL
inputSource['string', 'null']Compatibility input source
countrystringCountry
languagestringLanguage
sortstringSort
deviceTypestringDevice
sourceUrlstringSource URL
coveragestringCoverage
retrievalMethodstringRetrieval method
warningsarrayWarnings
scrapedAtstringScraped at
errorCodestringError code
messagestringMessage

API and automation

The API tab provides snippets for this Actor. For scheduled or larger collections, start a run asynchronously and poll its status instead of holding a synchronous request open. Keep your API token in an environment variable.

import os, time, requests
base = "https://api.apify.com/v2"
headers = {"Authorization": "Bearer " + os.environ["APIFY_TOKEN"]}
actor_input = {'appIds': ['com.whatsapp'], 'maxReviews': 20}
response = requests.post(
base + "/acts/YaQpO5GGTRCoNPtD7/runs",
headers=headers, json=actor_input, timeout=30,
)
response.raise_for_status()
run = response.json()["data"]
for _ in range(720):
if run["status"] not in ("READY", "RUNNING", "TIMING-OUT", "ABORTING"):
break
time.sleep(5)
response = requests.get(base + "/actor-runs/" + run["id"], headers=headers, timeout=30)
response.raise_for_status()
run = response.json()["data"]
else:
raise TimeoutError("Polling ended; inspect the existing run before starting another.")
if run["status"] != "SUCCEEDED":
raise RuntimeError(run.get("statusMessage", run["status"]))
response = requests.get(
base + "/datasets/" + run["defaultDatasetId"] + "/items",
headers=headers, params={"format": "json", "limit": 1000, "offset": 0}, timeout=30,
)
response.raise_for_status()
rows = response.json()
print(rows) # Paginate with offset for larger datasets; inspect per-row coverage.

Scheduled monitoring and integrations

  1. Save a working input as an Apify Task.
  2. Attach a Schedule in your timezone; keep runs sharing an incremental state key sequential.
  3. Add a successful-run webhook or connect your downstream workflow to the dataset export/API.
  4. Inspect missing/partial data before sending alerts or treating absence as removal.

Use the platform Integrations/API options to connect external workflows such as Make, n8n or a data warehouse. An external sentiment or summarization step is separate from this Actor and may have its own charges. The platform also supports Actor tools through Apify MCP; availability and client setup depend on your integration.

FAQ

Where is the package name?

Copy the id parameter from the Google Play URL; for example, id=com.whatsapp.

Why are fewer reviews returned than the store rating count?

A rating count can include ratings without written reviews, and source pagination, locales and filters change the retrievable subset.

Can I reuse an existing integration?

Select the matching input envelope and outputSchema. Compatibility covers the documented fields; it does not promise identical source ordering or availability.

Can I export without writing code?

Yes. Run from the Input form, open the dataset and use the export controls for JSON or CSV. Select your preferred output profile before running when migrating an integration.

Does a successful run guarantee every field?

No. Inspect coverage, warnings and source-specific status fields. Optional enrichment may be missing even when usable rows were delivered.

Troubleshooting

SymptomWhat to check
Empty datasetValidate the target, source availability and filters; try the small quick-start input.
Fewer rows than requestedCheck source limits, pagination and filtering. Increasing a cap cannot create unavailable source records.
Partial fieldsInspect coverage/warnings and the relevant source or enrichment status.
Access or throttling errorsCheck the run log and documented proxy configuration; retry at a lower request volume.
Migration mismatchCheck the explicit input/output profile and technical field mapping below.
Unexpected billSeparate result events from platform resources; inspect enrichment, result caps and the Pricing tab.

Technical reference

Migration compatibility

The Actor accepts the common input families used by leading Google Play review Actors:

  • appIdOrUrl, deviceType, sortBy, rating, startPage, pagesToScrape, reviewsPerPage, maxReviews, ratingFilter, keywords, endDate, recentDays, uniqueOnly, appVersion
  • appIds, country, language, sort, startUrls, maxItems, customMapFunction

customMapFunction executes an isolated JavaScript function on each output row.

One schema-level migration difference is explicit: one tracked competitor defines language as an array while another defines the same key as a string. Apify validates a field as one type, so this Actor preserves the string-shaped language contract and adds languages for array-shaped multi-locale workflows. For native workflows, rename language to languages. For competitor defaults as well as original array keys, use the explicit envelope below; numeric ratingFilter arrays are preserved.

Extensions

  • Multiple app IDs and countries in one run
  • Multiple languages through languages
  • since for scheduled incremental review monitoring
  • Developer-reply-only filtering
  • Explicit RPC request/retry/source diagnostics
  • Stable structured output with source locale and coverage metadata

Output

Review rows include review ID, user name/image, text, score, helpful votes, app version, timestamp, developer reply/reply timestamp, app/country/language and source telemetry.

For drop-in migration from the major appIds/startUrls competitor family, rows also expose compatibility aliases such as id, text, date, replyText, replyDate, version, thumbsUp, scoreText, url, inputSource and criterias alongside the canonical fields.

Source boundary

The validated path uses Google Play's public oCPfdb review RPC. It requires no account or private endpoint. Source behavior can change, so the Actor reports source failures and retry counts explicitly.

Date and output compatibility

theagents until is a LOWER date bound (reviews newer than that date), combined with since using the later bound. endDate remains the upper bound. recent/top alias newest/mostRelevant; ratings merges with ratingFilter. Neatrat output date is date-only and has different rating/reviewer/body/position fields: select outputSchema=neatrat for its field layout. Use languages for Neatrat language-array migration through the input form; language remains a string in the schema. language=all now expands to the fixed query-locale list documented below.

Output profiles and custom JavaScript

The default outputSchema=extended preserves the existing output. Google Play supports wolves, theagents and neatrat. These are explicit field projections, not a guarantee of identical source pagination or data availability. Missing source fields remain null.

customMapFunction runs after output projection and before delivery. Example: (row) => ({...row, exported: true}). It must synchronously return one JSON object per row. Async functions, filtering and non-object results fail the run before delivery. Each row has 50 ms CPU, 16 MB memory and 256 KB stack limits; total mapping budget is 10 seconds. The interpreter has no network, filesystem or host callbacks.

Multiple locales and bounded coverage

Use language: "all" or languages: ["all"] to query these fixed locales: en de fr es it pt-BR pt-PT ja ko zh-CN zh-TW zh-HK af am bg ca hr cs da el en-GB es-419 et fi fil fr-CA he hi hu is id lt lv ms nl no pl ro ru sk sl sr sv sw th tr uk zu vi. This sweeps query locales, not all review text languages or historical reviews. Explicit languages: ["en", "de"] remains supported. Sources are scheduled one page at a time in round-robin order; output is source-page order, not a globally sorted merge. maxReviews remains global. A small cap can stop before later sources are visited. SOURCE_DIAGNOSTICS records all sources including unvisited ones, pages, accepted rows and stop reason. Repeated cursors terminate with limited coverage. Source locale does not classify actual text language.

The fixed locale list is based on Google's published locale table (https://support.google.com/googleplay/android-developer/table/4419860?hl=en-GB); this table does not prove that each review endpoint returns distinct data for every locale. Refer to the run diagnostics for actual coverage.

Explicit input migration

Keep existing native calls unchanged. Native defaults remain NEWEST, pagesToScrape=-1, maxReviews=1000 (when neither quantity limit is supplied). Input profiles are independent of outputSchema, which remains extended unless selected explicitly.

For Neatrat, replace the entire input JSON with one wrapper around the original object. No language key rename or manual default copying is needed:

{"neatratInput":{"appIdOrUrl":"com.whatsapp","language":["en","de"]}}

In the form, paste the original object into Neatrat original input and clear unrelated native fields, including any prefilled appIds. Using the JSON tab and replacing the whole document is the shortest reliable migration. Do not submit the old language array at the top level: that field deliberately remains a string.

EntrySort when omittedPages when omittedQuantity when omitted
Native (no envelope)NEWEST-11000 unless maxItems supplied
neatratInputmostRelevant / HELPFULNESS510000
wolvesInputNEWESTno explicit page limit, native ceiling appliesMust provide positive maxItems
theagentsInputNEWESTno explicit page limit, native ceiling appliesMust provide positive maxItems

The last two declared competitor schemas supply only prefill:1000, not a maxItems default. Their omitted API quantity behavior is unproven. Add maxItems only if the original input omitted it, then wrap:

{"wolvesInput":{"appIds":["com.whatsapp"],"maxItems":1000},"outputSchema":"wolves"}
{"theagentsInput":{"appIds":["com.whatsapp"],"maxItems":1000,"until":"2026-09-01"},"outputSchema":"theagents"}

Only one envelope is allowed. Inside it, use that competitor's fields, types and enum values; unknown or cross-profile fields fail as INVALID_INPUT before fetching. Explicit nested settings win over that profile's defaults. Native extension workflows should continue using the native entry. customMapFunction inside wolvesInput/theagentsInput still executes after the explicitly selected output projection.

Top-level native fields matching the existing Schema defaults are ignored in envelope mode because Apify injects them automatically; this is also reported in OUTPUT.warnings. Other top-level native fields fail rather than merge. Even an explicitly supplied top-level value identical to a default cannot override an envelope: put settings inside the envelope. outputSchema is the sole independent top-level control. OUTPUT.inputProfile and OUTPUT.resolvedInput show the selected profile and resolved sort/page/quantity controls for inspection.

Limits remain explicit: -1 is bounded by 100000 reviews and 10000 pages per query source; maxReviews/maxItems is global. Neatrat language arrays route query locales, not a proven equivalent of its described text-language filter. Empty/omitted Neatrat language uses en as this implementation's query fallback, not a verified competitor default. Page offsets and page limits are per source; raw page sizes, locale coverage, position semantics and cross-source global ordering are not guaranteed equal to competitors. The other actors' omitted page behavior is not proven by their schemas; this entry uses the documented native bounded traversal.

Support

Open an issue from this Actor’s Issues tab with the run ID, expected result and a redacted input. Do not include tokens, cookies or private credentials. Include the output profile and affected field when reporting a migration mismatch.

Presentation update

The current listing adds workflow examples, grouped input documentation, output-field explanations and plan-based result discounts. Source-specific limitations above still apply. This is an independent tool and is not affiliated with the source platform.

How to export low-star Google Play reviews for release feedback

Reading every app review manually is difficult. A small filtered export can help a product team inspect recent complaints before deciding whether a larger analysis is useful.

Disclosure: I maintain the paid Apify Actor in this tutorial. This is a documented workflow for my own product. Available account credits may cover a trial, but collection is metered.

Configure one app and one locale

Open the Actor, go to Input and choose JSON. This example requests up to five one- or two-star reviews from WhatsApp's US/English feed:

{
"appIds": [
"com.whatsapp"
],
"country": "us",
"language": "en",
"ratingFilter": [
1,
2
],
"maxReviews": 5
}

The package name is the id value in a Google Play app URL. Replace com.whatsapp with your target. Country selects the source locale; language is a collection setting, not automatic translation. Keep these explicit for a reproducible comparison.

Inspect the result before drawing conclusions

After the run finishes, open the dataset and confirm that returned scores are one or two. Export CSV for manual triage or JSON for an analysis pipeline. Retain review IDs, timestamps, app version where available, text and developer replies rather than reducing the output to an average score.

A useful manual worksheet separates the review's actual statement, your proposed issue category, and your confidence. A complaint is not proof of a confirmed bug; missing app versions and replies should remain unknown. Don't classify sentiment or assign root causes as if the scraper had verified them.

Verification and limitations

A September 11, 2026 owner cloud sample returned five reviews for this configuration. It is a small functional check, not proof of comprehensive coverage or customer adoption. Source data changes, and filtering can require more requests than the number of results ultimately delivered.

The verified Free-plan result fee is $0.08 per 1,000 reviews: five results correspond to $0.0004 before platform compute, storage, transfer and proxy usage. Refer to the live Pricing tab for your applicable plan. A zero-result run can still use platform resources.

Low-star feedback is deliberately biased. It is useful for finding possible problems, but cannot establish the percentage of users experiencing them. For broader research, compare it with an unfiltered sample using the same date and locale settings. For recurring exports, use explicit date boundaries and deduplicate review identities downstream.

Try it

Open the Google Play review exporter. Start with five rows, inspect the original text and only then expand the scope. Report reproducible issues through the Actor's Issues tab without including credentials.