DEV Community

Tiandu Tech
Tiandu Tech

Posted on

How to scrape App Store, Google Play and Chrome Web Store reviews in one run

If your product ships as an iOS app, an Android app and a Chrome extension, its reviews sit in three stores with three page layouts. Copying them by hand is slow. Running three separate scrapers leaves you with three exports and three sets of field names to merge.

This guide pulls reviews from all three stores with one input list and one run, and gets back one dataset with the same fields for every store. We'll use the App Store, Google Play & Chrome Web Store Reviews Scraper on Apify. It has no Actor fee; you only pay for Apify platform usage.

Heads-up about Apple (October 2026): Apple's public review feed currently returns empty pages at times. When that happens the run says so in its summary and log instead of silently returning nothing. Google Play and the Chrome Web Store are not affected.

What you need

  • A free Apify account (needed to run anything on Apify).
  • The IDs or URLs of the apps and extensions you care about.

Step 1: Find your IDs

You can paste either the store URL or the bare ID. The store is detected automatically.

Store What to paste Example
Apple App Store numeric app ID or apps.apple.com URL 310633997 (WhatsApp)
Google Play package name or play.google.com URL com.whatsapp
Chrome Web Store 32-letter extension ID or chromewebstore.google.com URL ddkjiahejlhfcafbddmgiahcphecmpfh (uBlock Origin Lite)

The Apple ID is the number after id in the App Store URL. The Google Play package name is the id= value in the Play URL. The Chrome extension ID is the 32-character string at the end of the Web Store URL.

Step 2: Build the input

Here is an input that mixes all three stores:

{
  "apps": [
    "310633997",
    "com.whatsapp",
    "ddkjiahejlhfcafbddmgiahcphecmpfh"
  ],
  "countries": ["us", "gb"],
  "language": "en",
  "maxReviewsPerApp": 100
}
Enter fullscreen mode Exit fullscreen mode

What each field does:

  • apps (required): your mixed list of IDs or URLs.
  • countries: two-letter codes. Apple and Google Play reviews are fetched per country. Chrome Web Store reviews aren't split by country, so this is ignored for extensions.
  • language: used by Google Play and the Chrome Web Store. For Chrome, only reviews in this language are returned. Apple's language follows the country.
  • maxReviewsPerApp: cap per app per country (per extension for Chrome). Apple never returns more than 500 per app per country.

Two optional switches, both off by default:

  • sentiment: true adds a simple positive / neutral / negative label. It's a rule (English keywords plus star rating), not an ML model.
  • includeReviewerName: true adds a masked nickname, first character plus ***.

Step 3: Run it

Option A: in the browser

Open the Actor page (https://apify.com/tiandu-tech/apify-002-app-reviews), paste the JSON into the input's JSON view (or fill in the form), and click Start. When the run finishes, the reviews appear as a table in the run's Output tab (the table view is named Reviews). Use Export there to download them as JSON, CSV or Excel.

Option B: from Python

Install the official client:

pip install "apify-client>=3.3,<4"
export APIFY_TOKEN=...   # from Apify Console → Settings → API & Integrations
Enter fullscreen mode Exit fullscreen mode
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run_input = {
    "apps": ["310633997", "com.whatsapp", "ddkjiahejlhfcafbddmgiahcphecmpfh"],
    "countries": ["us", "gb"],
    "language": "en",
    "maxReviewsPerApp": 100,
}

run = client.actor("tiandu-tech/apify-002-app-reviews").call(run_input=run_input)
print("Run status:", run.status)

reviews = list(client.dataset(run.default_dataset_id).iterate_items())
print(f"Got {len(reviews)} reviews")

by_store = {}
for r in reviews:
    by_store[r["store"]] = by_store.get(r["store"], 0) + 1
print(by_store)   # e.g. {'google': ..., 'chrome': ..., 'apple': ...}
Enter fullscreen mode Exit fullscreen mode

call() waits for the run to finish. In apify-client 3.x it returns a typed Run object, so you read run.status and run.default_dataset_id. The older 2.x client returned a plain dict; with 2.x use run["status"] and run["defaultDatasetId"] instead.

Never hard-code the token in your script; read it from an environment variable as above.

Option C: plain HTTP

Apify's run-sync-get-dataset-items endpoint runs the Actor and returns the items in one call (good for small runs):

curl -X POST \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"apps":["com.whatsapp","ddkjiahejlhfcafbddmgiahcphecmpfh"],"maxReviewsPerApp":20}' \
  "https://api.apify.com/v2/acts/tiandu-tech~apify-002-app-reviews/run-sync-get-dataset-items?format=json"
Enter fullscreen mode Exit fullscreen mode

Step 4: Read the output

Every review has the same fields regardless of store:

Field Notes
store apple, google or chrome
appId app ID, package name or 32-letter extension ID
country null for Chrome
language review language
reviewId unique within a store
rating 1–5
title null for Chrome; Google Play reviews have no title either
text review body; emails and phone numbers are redacted
appVersion version the reviewer was using
thumbsUp helpful count
reviewedAt ISO 8601 timestamp
developerReply reply text, if any

Because the schema is shared, you can drop the whole dataset into one spreadsheet or DataFrame and group by store, appId or appVersion straight away.

Things to know

  • Duplicates across countries are removed. The same reviewId is kept once, and country is the first country it was seen in. The run summary reports how many were removed.
  • Empty results are explained. A wrong ID or an app without reviews shows up in the summary rather than failing silently.
  • Resilience: network errors, HTTP 429 and 5xx are retried up to 3 times with back-off. If a store's page format changes and two tasks in a row fail to parse, the rest of that store's tasks are skipped so no wrong data is written.
  • Privacy: reviewer names are off by default, and the Actor never outputs avatars, profile links or user IDs. You're still responsible for following the data-protection rules that apply to you.

Wrap-up

That's it: one input list, one run, one schema. Export to CSV for a quick read, or load the dataset into Python (the companion post shows how to find pain points in it).

Try it here: https://apify.com/tiandu-tech/apify-002-app-reviews

A runnable example project (collect + analyze) is on GitHub: https://github.com/DongmeiHerman/app-reviews-pain-points

Top comments (0)