Google Play Store Review Scraper & Developer Replies avatar

Google Play Store Review Scraper & Developer Replies

Pricing

from $2.99 / 1,000 results

Go to Apify Store
Google Play Store Review Scraper & Developer Replies

Google Play Store Review Scraper & Developer Replies

Google Play Store Review Scraper — Scrape Google Play reviews with ratings, review text, dates, usernames, app details, and developer replies. Analyze user feedback, app sentiment, ratings, recurring issues, and developer responses for product and competitor research.

Pricing

from $2.99 / 1,000 results

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

1

Monthly active users

8 hours ago

Last modified

Share

Google Play Reviews Scraper — Ratings, Text and Developer Replies

Google Play Reviews Scraper pulls Android app reviews from any Play Store listing and attaches the developer's reply to each one — rating, reviewer, review text, isAnswered, developerReplyText, developerRepliedAt and a derived responseTimeHours. A replyStatus filter (all / unanswered / answered) turns the feed into a reply-status worklist instead of a flat review dump. Built for support teams triaging unanswered complaints, product managers auditing reply SLAs, and competitive analysts benchmarking how fast a rival responds.

What is Google Play Reviews Scraper?

Google Play Reviews Scraper is an Apify Actor that reads the same review feed the Play Store app renders for any listing and returns it as typed JSON rows — one row per review, with the developer's reply (if any) parsed onto that same row and, optionally, mirrored onto its own linked row. No Google account, Play Console login, or API key is required — everything returned is already visible to anyone who opens the app's public listing page.

Key capabilities:

  • 🎯 Discover reviews by Play Store URL or bare package name (appTargets / startUrls)
  • ⭐ Filter by star rating server-side — Play itself returns only the selected stars, one pagination pass per rating
  • ↩️ Filter by reply status — keep only unanswered reviews, only answered ones, or everything with the flag attached
  • 🧵 Emit a linked child row per developer reply, separate from the review row, plus a mirrored per-run dataset
  • 📊 Emit one reply-rate summary row per app — answered/unanswered counts, reply rate, per-star buckets, response-time stats
  • 🔍 Narrow further on keywords, review age, posting date, app version and storefront language
  • Export as JSON, CSV or Excel, or read the dataset through the Apify API

What data can I extract with Google Play Reviews Scraper?

Every review is one row carrying the review itself, the linked developer reply fields, and run accounting.

FieldExample ValueUse Case
reviewId"gp:AOqpTOF...9x"Deduplication and joining to the linked reply row
type"review"Separating review rows from reply, summary and error rows
isChildfalsetrue on the linked developer-reply row
parentIdnullOn a reply row, the reviewId of the review it answers
rating1Star rating, 1–5
reviewer"Verona T."Reviewer attribution as Play displays it
date"2026-07-18"Review date, YYYY-MM-DD
reviewedAt"2026-07-18T09:14:02Z"UTC ISO timestamp of the review
body"My design exported completely blurry."Review text for analysis or triage
isAnsweredtrueWhether a developer reply was parsed for this review
developerReplyAuthor"Canva"Who replied
developerReplyText"Hi Verona, thanks for the report..."The reply body
developerRepliedAt"2026-07-18T15:02:41Z"UTC ISO reply timestamp
responseTimeHours5.81Hours between the review and the reply
helpfulCounts3Up-votes from other Play Store users
reviewedIn / language"en"Storefront language short code — both fields carry the same value
userImage"https://play-lh.googleusercontent.com/..."Reviewer avatar URL
position1Position among the rows this run pushed, in push order
appId"com.canva.editor"Package name the row belongs to
timestamp1784370842Review epoch seconds
reviewUrl"https://play.google.com/store/apps/details?id=com.canva.editor&reviewId=..."Deep link back to the review on Play
scrapedAt"2026-07-19T12:00:00Z"Run collection timestamp

Two fields exist internally but are not on the pushed row: the nested developerReply object ({author, text, repliedAt}, mirrors the flat reply fields, null on unanswered reviews and on reply rows) and developerRepliedTimestamp (the reply's epoch seconds) are both written to every review/reply row but sit outside the dataset's default table view — open the row as JSON to see them. The app version a review was written on is filterable via the appVersion input but is not exposed as an output field — it is read from the feed only to test against your filter, then dropped before the row is pushed.

Developer reply and reply-rate data

Every review row already carries the flag and the flat reply fields above. Turn on emitReplyRows (default: on) and each answered review also produces a separate linked rowtype: "reply", isChild: true, parentId set to the original review's reviewId — carrying the same reply text, author and timestamp, plus a matching reviewUrl and position. These rows are also mirrored to a dedicated per-run dataset named developer-replies-<runId>. Turn on emitAppReplySummary (default: on) and each app also gets one type: "app_reply_summary" row: reviewsAnalyzed, answeredCount, unansweredCount, replyRatePct, avgResponseTimeHours, medianResponseTimeHours, responseTimeSampleSize, and a replyRateByStar object with a {reviews, answered, replyRatePct} bucket per star. reviewsAnalyzed counts every deduplicated review scanned across all requested star passes — before the replyStatus, keywords, minHelpfulVotes or other content filters are applied — so it reflects what Play returned, not what your run kept. Any rate is written as null, not computed, when its sample is under 5 reviews; replyRateProvisional flags a summary built on fewer than 20.

Targeting and filter data

starsToTriage (or its legacy alias ratingFilter) drives Play's own server-side star filter — each selected rating is a separate pagination pass, so a 1★-and-2★ run never downloads the other three stars just to discard them. replyStatus narrows to unanswered or answered reviews. minHelpfulVotes keeps only reviews other users endorsed. keywords, recentDays, endDate, appVersion and language narrow further on review content, age, posting date, app version and storefront language — every one of these is applied before a row is stored, on every scanned review, not only on the first page.

Why not build this yourself?

Google does publish an official review surface for developers — the Play Developer API's Reviews endpoint, reached through a Play Console service account. It is scoped to the reviews of apps you are the registered developer of. There is no equivalent owner-only credential that lets you pull a competitor's or a client's review feed the way this Actor does — if the app is not in your own Play Console account, the official API is not an option, whatever your use case.

Building a scraper against Play's own web client is not straightforward either. Play's review feed is served through an internal batchexecute RPC endpoint keyed to a request template (oCPfdb) embedded in the app's page HTML at a numeric slot index that drifts over Play front-end releases — a hardcoded index silently posts an empty template and returns zero reviews with no error. Sort order and device segment are separate positions inside that same nested payload, not query parameters, so wiring them up means locating the right array slot rather than passing a flag. Star, reply-status, keyword and date filters all have to run before any row limit is applied and on every page, or a naive limit-then-filter implementation quietly drops matching reviews once the early cutoff is hit.

Use the Play Developer API when the apps in question are your own and you also want to post replies, not just read reviews. Use Google Play Reviews Scraper when you need review and reply data for apps you do not manage — competitor benchmarking, agency client audits, or any portfolio wider than your own Play Console account.

How to use data extracted from Google Play reviews?

Support and app-ops teams

Build the morning worklist with replyStatus: "unanswered" and starsToTriage: ["1", "2"], add a minHelpfulVotes floor so the pile starts with complaints other users already endorsed, and sort reviewOrder: "newest" so today's fires are first. Route body, reviewer and reviewUrl straight into a helpdesk queue or a Slack alert.

Agencies managing multiple client apps

Run replyStatus: "answered" against a client's app list on a schedule and read responseTimeHours per review and avgResponseTimeHours/medianResponseTimeHours from the per-app app_reply_summary row to report on reply SLAs across every app in the account, without opening Play Console for each one.

Market research and competitive intelligence

Point appTargets at a set of competitor package names, leave replyStatus: "all", and compare replyRatePct and replyRateByStar across apps to see which competitor actually answers its 1★ reviews and which lets them sit — a responsiveness signal that ratings alone do not show.

AI agents and automated pipelines

Feed body and the existing developerReplyText for answered reviews into an LLM as a style reference, then have an agent draft first-pass replies for the still-unanswered rows this run returns. The same type-tagged rows work directly as RAG context for a support bot trained on real resolved complaints.

⬇️ Input

Point the Actor at one or more apps and choose a triage slice. Nothing is required by the schema — supply at least one app in appTargets or startUrls, or the run pushes a single type: "error" row and stops.

🎯 Targeting

ParameterRequiredTypeDefaultConstraintsDescription
appTargetsNoarrayitems: stringPlay Store app URLs or package names to build the triage worklist from. Example: com.canva.editor or https://play.google.com/store/apps/details?id=com.canva.editor

💬 Support triage

ParameterRequiredTypeDefaultConstraintsDescription
replyStatusNostring"all"enum: all, unanswered, answeredWhich reviews land in the dataset. 'Unanswered only' is the open support worklist (no developer reply yet). 'Answered only' audits what your team already replied to.
starsToTriageNoarrayitems enum: "1""5"Star buckets to pull. Drives Play's server-side star filter — one pagination pass per selected star. Leave empty for every star.
minHelpfulVotesNointeger0min 0Keep only reviews other users up-voted at least this many times. 0 = no floor.
emitReplyRowsNobooleantrueAdds a child row (type=reply, isChild=true, parentId=the review ID) carrying the reply text, author and date, mirrored to a per-run child dataset. Reply rows are never charged.
emitAppReplySummaryNobooleantrueAdds one uncharged type=app_reply_summary row per app: reviews analysed, answered/unanswered counts, reply rate %, per-star reply buckets and average/median response time, each next to its sample size.

⚙️ Fetch settings

ParameterRequiredTypeDefaultConstraintsDescription
reviewLimitPerAppNointeger100min -1Maximum stored review rows per app. -1 for no cap. Reply rows and the summary row do not count against it.
reviewOrderNostring"newest"enum: newest, mostRelevant, ratingOrder Play returns the feed in. 'Newest first' surfaces today's unanswered complaints first.
targetDeviceNostring"mobile"enum: mobile, tablet, chromebookWhich device pool Play serves reviews from. Mobile, tablet and Chromebook return genuinely different review sets.
pageSizeNointeger200min 1, max 1000Reviews to ask Play for per round-trip. Higher means far fewer requests.
startPageNointeger1min 1Pagination offset kept for compatibility with the base actor's input.
pagesToScrapeNointeger-1min -1Hard cap on requests per star pass. -1 (default) runs until the review limit is reached. When starsToTriage selects several stars, this budget resets for each one — pagesToScrape: 3 with two selected stars fetches up to 3 pages for each, not 3 total.
uniqueOnlyNobooleantrueDeduplicate by review ID across pages and star passes.

🔍 Content filters

ParameterRequiredTypeDefaultConstraintsDescription
keywordsNoarrayitems: stringKeep only reviews whose text contains any of these words (case-insensitive). Example: crash, refund, login.
recentDaysNointeger0min 0Keep only reviews posted in the last N days. 0 = no limit.
endDateNostring""datepickerKeep only reviews posted up to this date (YYYY-MM-DD). Empty = no upper bound.
appVersionNoarrayitems: stringKeep only reviews written on these app versions (e.g. 2.362.0). Empty = all versions. Not returned as an output field — see the note above.
languageNoarrayitems enum, 36 storefront languages (en - English, es - Spanish, ... lt - Lithuanian)Keep only reviews served in these storefront languages.

🧩 Legacy base-input aliases

Original key names from the base Google Play Store Review Scraper. Leave these empty unless re-running an existing base-actor input JSON — the source resolves every alias pair by checking the legacy key first, so if both a legacy key and its modern replacement are set, the legacy key wins.

ParameterRequiredTypeDefaultConstraintsDescriptionModern equivalent
startUrlsNoarrayitems: stringLegacy key. App URLs or package names, same meaning as appTargets.appTargets
maxReviewsNointegermin -1Legacy key. Maximum stored review rows per app; -1 for no cap.reviewLimitPerApp
reviewsPerPageNointegermin 1, max 2000Legacy key. Reviews requested per round-trip. Values above 1000 are clamped to 1000, Play's proven ceiling — the schema's own 2000 maximum is not the effective cap.pageSize
sortByNostringenum: mostRelevant, newest, ratingLegacy key. Feed order.reviewOrder
deviceTypeNostringenum: mobile, tablet, chromebookLegacy key. Device pool.targetDevice
ratingFilterNoarrayitems enum: "1""5"Legacy key. Star buckets to keep.starsToTriage
ratingNointegernullmin 1, max 5Legacy key. A single star rating to keep. Only consulted when neither ratingFilter nor starsToTriage is set.starsToTriage

🔒 Proxy

ParameterRequiredTypeDefaultConstraintsDescription
proxyConfigurationNoobject{"useApifyProxy": false}proxy editorOptional. Google Play serves these endpoints without a proxy; the Actor escalates to a residential proxy automatically if it hits a soft block.

Common pitfall: setting both a legacy alias and its modern replacement (e.g. both maxReviews and reviewLimitPerApp) does not average or merge them — the legacy key is checked first and wins outright if it has a value. Set one or the other, not both, unless you mean for the legacy value to override.

Example input

{
"appTargets": ["com.canva.editor"],
"replyStatus": "unanswered",
"starsToTriage": ["1", "2"],
"minHelpfulVotes": 1,
"emitReplyRows": true,
"emitAppReplySummary": true,
"reviewLimitPerApp": 100,
"reviewOrder": "newest",
"proxyConfiguration": { "useApifyProxy": false }
}

Run it from the Apify Console: open Google Play Reviews Scraper, paste one or more app links or package names into Apps to triage, set Reply status to keep and Star ratings to triage for the slice you want, and click Start.

⬆️ Output

Typed JSON, one row per review by default, plus optional linked reply rows and one summary row per app. Export as JSON, CSV or Excel, or read the dataset through the Apify API. Only type: "review" rows are charged (row_result) — reply rows, the summary row and error/accounting rows are all pushed uncharged. Filter type == "review" to isolate the charged, billable rows.

Review row (type: "review")

{
"reviewId": "gp:AOqpTOFabc123def456",
"type": "review",
"isChild": false,
"parentId": null,
"rating": 1,
"reviewer": "Verona T.",
"date": "2026-07-18",
"reviewedAt": "2026-07-18T09:14:02Z",
"body": "My design exported completely blurry.",
"isAnswered": true,
"developerReply": {
"author": "Canva",
"text": "Hi Verona, thanks for the report - could you share your device model with support?",
"repliedAt": "2026-07-18T15:02:41Z"
},
"developerReplyAuthor": "Canva",
"developerReplyText": "Hi Verona, thanks for the report - could you share your device model with support?",
"developerRepliedAt": "2026-07-18T15:02:41Z",
"developerRepliedTimestamp": 1784391761,
"responseTimeHours": 5.81,
"helpfulCounts": 3,
"reviewedIn": "en",
"language": "en",
"userImage": "https://play-lh.googleusercontent.com/a/example",
"position": 1,
"appId": "com.canva.editor",
"timestamp": 1784370842,
"reviewUrl": "https://play.google.com/store/apps/details?id=com.canva.editor&reviewId=gp:AOqpTOFabc123def456",
"scrapedAt": "2026-07-19T12:00:00Z"
}

Linked developer-reply row (type: "reply", isChild: true)

Pushed only when emitReplyRows is on and the source review has a reply. reviewId is the review's own ID with a :reply suffix; parentId is the original review's reviewId — the field that links the two rows together. Also mirrored to a per-run dataset named developer-replies-<runId>.

{
"reviewId": "gp:AOqpTOFabc123def456:reply",
"type": "reply",
"isChild": true,
"parentId": "gp:AOqpTOFabc123def456",
"rating": null,
"reviewer": "Canva",
"date": "2026-07-18",
"reviewedAt": "2026-07-18T15:02:41Z",
"body": "Hi Verona, thanks for the report - could you share your device model with support?",
"isAnswered": null,
"developerReply": null,
"developerReplyAuthor": "Canva",
"developerReplyText": "Hi Verona, thanks for the report - could you share your device model with support?",
"developerRepliedAt": "2026-07-18T15:02:41Z",
"developerRepliedTimestamp": 1784391761,
"responseTimeHours": 5.81,
"helpfulCounts": null,
"reviewedIn": "en",
"language": "en",
"userImage": null,
"position": 1,
"appId": "com.canva.editor",
"timestamp": 1784391761,
"reviewUrl": "https://play.google.com/store/apps/details?id=com.canva.editor&reviewId=gp:AOqpTOFabc123def456",
"scrapedAt": "2026-07-19T12:00:00Z"
}

Per-app reply-rate summary row (type: "app_reply_summary")

Exactly one per app, only when emitAppReplySummary is on and at least one review was analysed.

{
"reviewId": "com.canva.editor:reply-summary",
"type": "app_reply_summary",
"isChild": false,
"parentId": null,
"appId": "com.canva.editor",
"reviewsAnalyzed": 200,
"answeredCount": 191,
"unansweredCount": 9,
"replyRatePct": 95.5,
"replyRateProvisional": false,
"avgResponseTimeHours": 14.72,
"medianResponseTimeHours": 9.4,
"responseTimeSampleSize": 191,
"replyRateByStar": {
"star1": { "reviews": 40, "answered": 39, "replyRatePct": 97.5 },
"star2": { "reviews": 18, "answered": 16, "replyRatePct": 88.9 },
"star3": { "reviews": 22, "answered": 20, "replyRatePct": 90.9 },
"star4": { "reviews": 46, "answered": 44, "replyRatePct": 95.7 },
"star5": { "reviews": 74, "answered": 72, "replyRatePct": 97.3 }
},
"scrapedAt": "2026-07-19T12:00:00Z"
}

replyRatePct, avgResponseTimeHours, medianResponseTimeHours and each star bucket's replyRatePct come back null — not omitted, not zero — whenever the underlying sample is under 5 observations. replyRateProvisional is true when the whole-app sample is under 20.

Accounting row (type: "error")

Pushed, uncharged, whenever an app can't be bootstrapped, a page fetch fails past retries, no app target was supplied at all, or every scanned review was filtered out.

{
"type": "error",
"isChild": false,
"appId": "com.canva.editor",
"reviewId": null,
"errorReason": "no_rows_matched_filters",
"errorMessage": "scanned 200 review(s); none matched the triage filters",
"scrapedAt": "2026-07-19T12:00:00Z"
}

errorReason values seen in source: invalid_input (no app supplied at all), bootstrap_failed (the app page couldn't be fetched or parsed — errorReason carries the underlying cause, e.g. http_403, no_wiz_global_data), page_fetch_failed (a review page failed after a retried refetch), and no_rows_matched_filters (reviews were scanned but every one was filtered out).

The dataset's default table view surfaces 31 of the fields above as columns; developerReply (the nested object), developerRepliedTimestamp, errorMessage, replyRateProvisional and replyRateByStar are still written to every row but sit outside that default view — read the row as JSON (or switch views) to see them.

How do you filter and target specific reviews?

starsToTriage is the main precision lever, and it is not a client-side filter — each star you select becomes its own request to Play's server-side star slot, so a run targeting only 1★ and 2★ never downloads (or pays for) the other three stars. Layer replyStatus on top to split that slice into what still needs a reply versus what your team already answered. minHelpfulVotes further ranks by how many other users endorsed the complaint, which is a reasonable proxy for how much a given review actually matters.

Volume is controlled independently from targeting: reviewLimitPerApp caps total stored review rows per app (-1 for no cap — reply and summary rows never count against it), while pagesToScrape caps requests per star pass, so selecting several stars multiplies your effective page budget rather than sharing one pool across them.

Three real targeting configurations:

Angry-customer worklist, one app:

{
"appTargets": ["com.canva.editor"],
"replyStatus": "unanswered",
"starsToTriage": ["1", "2"],
"minHelpfulVotes": 5,
"reviewOrder": "newest"
}

Reply-SLA audit for the last 30 days, answered only:

{
"appTargets": ["com.canva.editor"],
"replyStatus": "answered",
"recentDays": 30,
"emitAppReplySummary": true
}

Bug reports on a specific build, in English:

{
"appTargets": ["com.canva.editor"],
"keywords": ["crash", "freeze", "won't open"],
"appVersion": ["2.362.0"],
"language": ["en - English"]
}

▶️ Want to try other Google Play scrapers?

Scraper NameWhat it extracts
Apple App Store Review ScraperiOS review text, ratings and app versions
Goodreads Review Scraper By Star Rating & Spoiler FilterBook reviews with star and spoiler filtering
Google Maps Scraper By Radius & GeoJSON TerritoryLocal business listings and reviews within a geographic boundary
Amazon Product Scraper With Keyword Rank TrackingAmazon product listings and keyword rank positions
Quora Scraper With Human Answer Quality ScoreQuora answers scored for human-quality signal

How to extract Google Play review data programmatically

Google Play Reviews Scraper is an Apify Actor — one API call in, structured JSON out.

Python example

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/google-play-store-review-scraper-developer-replies").call(run_input={
"appTargets": ["com.canva.editor"],
"replyStatus": "unanswered",
"starsToTriage": ["1", "2"],
"reviewLimitPerApp": 200,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row.get("type") == "review":
print(row["rating"], row["reviewer"], row["isAnswered"], row["body"][:80])

Filtering on type == "review" separates billable review rows from the uncharged reply, summary and error rows in the same dataset.

Export to spreadsheets or CRM

Export as CSV and the field names map straight onto typical destination columns: rating → Rating, body → Review Text, developerReplyText → Developer Reply, responseTimeHours → Response Time (h), reviewer → Author, date → Date.

Yes. Google Play Reviews Scraper collects only what any visitor already sees on a public app listing page — no login, no Play Console access, no authentication of any kind. App reviews exist on Play specifically to be read by prospective users, so collecting them at this level is broadly treated as permissible.

This output is primarily business and product data — review text, ratings, developer replies — governed by Google's terms of service and ordinary database-rights considerations around systematic reuse of a compiled dataset, not personal-data law as the primary lens. One caveat: reviewer and developerReplyAuthor are the public display name or handle the reviewer/developer chose to show on Play, which can be a real name for some users — worth a brief note, not the primary framing here.

Consult legal counsel for commercial applications involving bulk storage of reviewer identity data.

❓ FAQ

What happens if an app has zero reviews matching my reply-status or star filters?

You get a type: "error" row with errorReason: "no_rows_matched_filters" and an errorMessage stating how many reviews were scanned before every one was filtered out — never a silently empty dataset. This row is uncharged.

Can I get the developer's reply along with each review?

Yes — every review row already carries isAnswered, developerReplyAuthor, developerReplyText, developerRepliedAt and responseTimeHours. Turn on emitReplyRows (on by default) for a second, linked row per reply, connected back to its review through parentId.

How accurate is the review and reply data?

The Actor returns review and reply text exactly as it appears on the public Play Store listing at request time. Accuracy of the underlying content — a review's wording, a reply's timing — depends entirely on what Play itself is currently serving; there is no independent verification layer beyond that.

How many reviews can I get per run?

reviewLimitPerApp (or its legacy alias maxReviews) sets the ceiling per app; -1 removes the cap entirely. There is no other hard limit encoded in the Actor — a run without a cap simply continues, per star pass, until Play's own feed runs out of pages (no next cursor) or a pagesToScrape budget is set and reached.

How does the star-and-reply-status targeting actually work?

starsToTriage drives Play's own server-side star filter, so each selected rating is a separate pagination pass rather than a client-side discard of unwanted rows. replyStatus then narrows that stream to unanswered or answered reviews before any row is stored. Together they're what make this a reply-status triage tool rather than a plain review dump — see "How do you filter and target specific reviews?" above for worked examples.

Does Google Play Reviews Scraper work with Claude, ChatGPT, and AI agent frameworks?

Yes. It is callable as a standard HTTP endpoint through the Apify API, so LangChain, CrewAI, n8n or a custom tool definition can invoke it and receive typed JSON with review and reply text ready for an LLM context window or a vector store.

How does Google Play Reviews Scraper compare to other Google Play review scrapers?

Checked on the Apify Store on 2026-07-26: neatrat/google-play-store-reviews-scraper documents rating, keyword, date and version filters and a similar field set, but its published output table has no reply field at all — no developerReplyText, no reply timestamp, no reply-rate rollup. scrapesage/google-play-scraper covers app details, top charts, developer portfolios and developer contact leads alongside reviews, a broader "whole Play Store" tool, and its review row includes replyText/replyDate but no derived response-time metric or per-app reply-rate summary. moving_beacon-owner1/my-actor-1 is a minimal reviews-only scraper with four output fields (user, rating, date, review) and no reply data. This Actor's distinguishing angle is the reply itself: a linked reply row, an isAnswered/replyStatus triage filter, and a per-app reply-rate summary with response-time percentiles, none of which the three above document.

Can I use Google Play Reviews Scraper without a Google Play Developer account or API key?

Yes. No Play Console account, no Google API key, no login of any kind. The Actor reads the same public review feed the Play Store app itself renders. The only credential you need is your Apify token.

Can I see which app version a review was written on?

Not directly. appVersion filters reviews by the version they were written on, but that version value is read from Play's feed only to test against your filter — it is not written back onto the output row. If you need the per-review app version in your dataset, this is a known gap in the current output shape.

Conclusion

Google Play Reviews Scraper turns any Play Store listing into a reply-aware review dataset: rating, review text, and the developer's own response with a measured response time, filterable down to exactly the unanswered or answered slice you're triaging. It is built for support teams working a daily complaint queue, agencies auditing reply SLAs across a client's app portfolio, and competitive analysts measuring how responsive a rival actually is. Server-side star targeting and reply-status filtering mean you pay for and download only the reviews you asked for. Open it on Apify and run your first triage pass with a single app.