Google Play Reviews Scraper avatar

Google Play Reviews Scraper

Pricing

Pay per usage

Go to Apify Store
Google Play Reviews Scraper

Google Play Reviews Scraper

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Felipe Lisboa

Felipe Lisboa

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

5 days ago

Last modified

Categories

Share

Scrape reviews from an app on the Google Play Store: rating, author, date, review text, thumbs-up count, app version and developer replies. Each review becomes one item in the Apify dataset.

Features

  • Flexible input: an app ID (com.instagram.android) or a Google Play URL.
  • Apify Unblocker: uses the UNBLOCKER proxy group by default, with Chromium launched with --ignore-certificate-errors (required for the Unblocker to work).
  • Lazy-load pagination: opens the "See all reviews" dialog and scrolls it, collecting each batch as Google loads it, until maxReviews is reached or no more reviews load.
  • Two data sources, merged: Google's internal review RPC responses (exact timestamps, app version, avatar) and the rendered review cards.
  • Multi-selector resilience: every field has several CSS selector strategies tried in order, each isolated in try/catch. Opening the dialog and scrolling also have fallbacks.
  • Incremental output: reviews are saved as they load, so a failed or aborted run keeps what it collected. Progress is persisted across actor migrations.

Input

FieldTypeDefaultDescription
appIdstringrequiredcom.instagram.android or https://play.google.com/store/apps/details?id=com.instagram.android
maxReviewsinteger100Max reviews to collect. 0 = no limit.
languagestringenGoogle Play language (hl)
countrystringusGoogle Play country (gl)
proxyConfigurationobject{ "useApifyProxy": true, "apifyProxyGroups": ["UNBLOCKER"] }Apify Proxy settings

language and country override any hl/gl in an input URL. If you switch to a proxy group other than UNBLOCKER, the --ignore-certificate-errors flag is harmless and can stay.

{
"appId": "com.instagram.android",
"maxReviews": 500,
"language": "en",
"country": "us"
}

Output

{
"appId": "com.duolingo",
"appName": "Duolingo: Language Lessons",
"reviewId": "7d0465c3-ff61-4a92-8ba6-780b41e3fb5d",
"author": "Rebekah Hicks",
"authorAvatar": "https://play-lh.googleusercontent.com/a-/...",
"rating": 3,
"text": "I used to really love this app, but with each new update ...",
"date": "2026-04-20T14:03:11.000Z",
"dateText": null,
"thumbsUp": 57,
"developerReply": {
"text": "Thanks for the feedback! ...",
"date": "2026-04-21T09:00:00.000Z",
"developer": null
},
"appVersion": "6.12.3",
"url": "https://play.google.com/store/apps/details?id=com.duolingo&hl=en&gl=us",
"scrapedAt": "2026-09-15T17:16:52.802Z"
}
  • developerReply is null when the developer hasn't replied.
  • date is an ISO timestamp. Reviews in the first batch come from the rendered page, so their date has day precision, dateText holds the original text, and authorAvatar and appVersion are null. Later batches come from the RPC with exact timestamps.
  • For non-English language values, date may be null for first-batch reviews; dateText always has the displayed date.
  • An app that can't be found is saved as an item with "#error": true.

How it works

  1. Opens the app page and clicks "See all reviews" (several strategies, including a language-independent structural fallback).
  2. Records every batchexecute response for the reviews RPC (oCPfdb) and parses its review arrays.
  3. Each round, extracts the rendered review cards with the selector strategies in DOM_STRATEGIES (src/main.js), merges them with RPC data by review ID, and pushes new reviews.
  4. Scrolls the dialog to trigger the next batch. It stops at maxReviews, or after several rounds with no new reviews.

To fix a field after a Google Play layout change, add a selector to its list in DOM_STRATEGIES.

Run locally

npm install
npx playwright install chromium
mkdir -p storage/key_value_stores/default
echo '{"appId":"com.instagram.android","maxReviews":50,"proxyConfiguration":{"useApifyProxy":false}}' > storage/key_value_stores/default/INPUT.json
npm start

The UNBLOCKER group needs an Apify token (APIFY_TOKEN) with Unblocker access; the example above disables the proxy for a quick local test.

Tech

Node.js 20, Crawlee PlaywrightCrawler (headless Chromium) and the Apify SDK.