# Google Play Reviews Scraper — $0.08/1K, Any Language (`fermaja/google-play-reviews-scraper`) Actor

Know what users love and hate about any Android app. Export every Google Play review in any language, with stars, versions, likes, developer replies and feature ratings. Filter complaints, monitor new reviews, free insights report. $0.08 per 1,000.

- **URL**: https://apify.com/fermaja/google-play-reviews-scraper.md
- **Developed by:** [Fermaja](https://apify.com/fermaja) (community)
- **Categories:** Developer tools, AI
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Play Reviews Scraper

**Know exactly what users love and hate about any Android app: yours or your competitors'.** Export every Google Play review in any language, with star ratings, app versions, likes, developer replies and the features users rated, to **CSV, Excel, JSON** or straight into your tools. **$0.08 per 1,000 reviews**, no start fee, plus a **free insights report** with every run.

> **Try it now:** the form is pre-filled with Spotify. Click **Start**, and 100 fresh reviews are ready in about 3 seconds.

![Google Play Reviews Scraper results: Spotify's most-liked 1★ and 2★ reviews of the last 30 days, with likes, app versions, feature ratings and developer replies, plus the free insights](https://api.apify.com/v2/key-value-stores/gk4Spu8MxV7bBkesf/records/output-preview.png?signature=19Nc4WjuFyA7vHE0abFmi)

*Real results: Spotify's 1★–2★ reviews of the last 30 days. 200 reviews in 3 seconds for $0.016. The most-liked complaint is about the new widget in version 9.1.92, and the insights show a 36.5% developer reply rate.*

### 🆕 What's new (October 17, 2026)

- 🎯 **Brand searches now find the brand's own app first.** Searching "Spotify", "Notion" or "Duolingo" returns `com.spotify.music`, `notion.id` and `com.duolingo` as the #1 result, exactly like the Play Store. Before, Google's large "top result" card was skipped.
- ⚡ **Date filters are now instant on huge apps.** A "last 30 days" request on Spotify (1.8 million reviews) now finishes in **3 seconds**, whatever sort order you pick.
- ✅ **Verified end to end** on single apps, keyword searches, developer pages, wrong app IDs, multi-language runs and complaint filters.

### Why teams choose it

- ⚡ **Very fast:** up to 4,000 reviews per request. 55,000 reviews from 7 apps took **14 seconds** in our tests.
- 🌍 **Every language in one run:** Google Play groups reviews by language. Pick several, or all 25 major ones, and duplicates are removed for you.
- 🎯 **Precise filters:** star ratings, date range, words the review must mention, replied or unanswered.
- 💸 **Pay only for what you keep:** filters are applied *before* charging, so you never pay for reviews you filtered out.
- 🔔 **Monitoring mode:** schedule it and get only the reviews posted since the last run, for Slack alerts or support queues.
- 📊 **Free insights report** with every run (see below).

### Who uses it

| You are… | You use it to… |
|---|---|
| 📱 **Product & UX teams** | Find which release dropped your rating and what users complain about most |
| 🔍 **Competitive intelligence** | Read your competitors' 1★ reviews: every complaint is a sales argument for you |
| 🚀 **App store optimization (ASO)** | Compare reply rates, reply speed and the features users praise or hate across your niche |
| 🎧 **Customer support** | Catch every unanswered negative review each morning |
| 📈 **Market research & investors** | Track user sentiment across a whole category over time |
| 🤖 **AI & data science** | Get large, clean, multilingual datasets for sentiment analysis, topic modelling, fine-tuning and RAG |

### How it works

1. **Tell it which apps.** Paste app IDs (`com.spotify.music`) or any Google Play link: app pages, **developer pages, categories and charts** all work. Or type keywords like `budget app` to scrape the top search results.
2. **It reads Google Play's own review feed directly**, the same data the Play Store app loads. That's why it's fast (thousands of reviews per request) and reaches the **complete history** of an app.
3. **Your filters are applied, and duplicates across languages are removed.** You're charged only for the reviews that remain.
4. **You get one clean row per review**, a **free app snapshot** (rating, installs, developer contacts…) and a **free insights report**. Download them or sync them to Google Sheets, Slack, Zapier, Make, n8n or your own API.

### Free insights report: answers, not just rows

Open **Output → Insights report** after any run. From the Spotify run shown above:

| Insight | Spotify, 1★–2★, last 30 days |
|---|---|
| Developer reply rate | **36.5%** of complaints get an answer |
| Median reply time | **48 minutes** |
| Worst-rated features | **battery efficiency 1.1★**, battery heat 1.15★, ads intrusiveness 1.33★ |
| Rating by app version | **v9.1.92: 1.13★**, the lowest of the recent versions |
| Most-liked complaint | "The new widget sucks…" (41 likes) |

You also get the star distribution, reviews per week and the store rating vs. the reviews you scraped.

### Ready-made inputs

**Complaints from the last 30 days that mention crashes or bugs**

```json
{ "appIds": ["com.spotify.music"], "ratings": ["1", "2"], "reviewsFrom": "30 days", "keywords": ["crash", "bug", "freeze"], "maxReviewsPerApp": 0 }
```

**Competitor research: the top 10 apps for a keyword**

```json
{ "searchQueries": ["budget app"], "maxAppsPerSearch": 10, "maxReviewsPerApp": 500 }
```

**Every review of one app (full history)**

```json
{ "appIds": ["com.duolingo"], "maxReviewsPerApp": 0 }
```

**All apps of a developer**

```json
{ "appIds": ["https://play.google.com/store/apps/developer?id=Spotify+AB"], "maxReviewsPerApp": 1000 }
```

**Global coverage: the 25 most common languages**

```json
{ "appIds": ["com.whatsapp"], "allLanguages": true, "maxReviewsPerApp": 200 }
```

**Daily monitor: only reviews posted since the last run**

```json
{ "appIds": ["com.yourcompany.app"], "onlyNewReviews": true, "monitorId": "daily-alerts", "maxReviewsPerApp": 500 }
```

### Example result

The most-liked review from the run above (one row of the dataset):

```json
{
  "appId": "com.spotify.music",
  "appTitle": "Spotify: Music and Podcasts",
  "rating": 1,
  "text": "The new widget sucks. More space, less information. Seriously surprised they could make it any worse. Urgh.",
  "date": "2026-10-16T22:07:52.823Z",
  "thumbsUp": 41,
  "appVersion": "9.1.92.3055",
  "hasReply": true,
  "replyText": "Hey there! Have you tried a quick reinstall? If that doesn't help, we'd recommend reaching out to our Customer Service at http://support.spotify.com. …",
  "replyDate": "2023-06-29T06:31:45.124Z",
  "reviewEditedAfterReply": true,
  "featureRatings": [
    { "feature": "visually good", "rating": 2 },
    { "feature": "playing music", "rating": 1 },
    { "feature": "social recommendations", "rating": 3 }
  ],
  "language": "en",
  "country": "us",
  "reviewUrl": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=b866bc32-ade8-41e5-95a3-2f4b433f845b"
}
```

💡 `reviewEditedAfterReply: true` tells you this user **rewrote their review after the developer had already replied** (in 2023). Google dates a review by its last edit, so this flag finds the customers who came back angry.

### All data fields

| Field | What it is |
|---|---|
| `appTitle`, `appId` | App name and package ID |
| `rating` | 1–5 stars |
| `text`, `title`, `textLength` | The review |
| `date` | When it was posted (or last edited) |
| `thumbsUp` | How many people found it helpful |
| `appVersion` | The app version the reviewer used |
| `userName`, `userImage` | Public reviewer name and avatar |
| `hasReply`, `replyText`, `replyDate`, `replyAfterHours` | The developer's answer and how fast it came |
| `reviewEditedAfterReply` | The user changed their review after the developer replied |
| `featureRatings` | Features the reviewer rated in Google's review form, e.g. `battery heat`, `ads frequency`, `offline maps` |
| `language`, `country`, `reviewUrl` | Review language, store country and a direct link |

**Free app snapshot** for every app (in the `SUMMARY` record): store rating, exact rating histogram, number of ratings and reviews, installs (including Google's exact install count), price, genre, content rating, release and update dates, version, and developer email, website, address and phone.

### Pricing

**$0.08 per 1,000 reviews** on the Free plan, and less on paid Apify plans (down to $0.05 per 1,000). **No start fee.** The app snapshot and insights report are free.

| You want | Reviews | Price |
|---|---|---|
| Quick check of one app | 100 | $0.008 |
| Last month's complaints of a big app | 200 | $0.016 |
| One app, deep dive | 10,000 | $0.80 |
| A whole niche (10 apps × 5,000) | 50,000 | $4.00 |
| Daily monitor, ~50 new reviews/day | 1,500 / month | $0.12 / month |

You only pay for reviews saved after your filters. Set a **maximum cost per run** and the Actor stops exactly there.

### Monitoring new reviews

Turn on **Only new reviews since the last run** and [schedule](https://docs.apify.com/platform/schedules) the Actor (for example every morning). It remembers the newest review it saw for each app and language, so each run saves, and charges, only fresh reviews. Then connect:

- **Slack / Microsoft Teams / email:** every new 1★ review in a channel
- **Google Sheets:** a live review log
- **Zapier, Make, n8n:** a support ticket for every unanswered complaint
- **Webhooks:** the data in your own backend

The first run saves the newest reviews (up to *Max reviews per app*) as a starting point. Keep that limit above the number of reviews the app gets between two runs; the log warns you if it was too low. Use a different **Monitor name** for each scheduled task watching the same app.

### API and integrations

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("fermaja/google-play-reviews-scraper").call(run_input={
    "appIds": ["com.spotify.music"],
    "maxReviewsPerApp": 1000,
    "ratings": ["1", "2"],
})
for review in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(review["rating"], review["text"])
```

```bash
curl -X POST "https://api.apify.com/v2/acts/fermaja~google-play-reviews-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"appIds":["com.spotify.music"],"maxReviewsPerApp":200}'
```

It also works from AI agents through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so Claude, ChatGPT or Cursor can pull reviews on request.

### FAQ

**How many reviews can I get?**
All of them. Google Play serves the full review history: for example, all 57,548 reviews of the Wikipedia app come back in a couple of minutes. Most people leave a star rating *without* text, and Google Play only publishes written reviews. That's why an app with 36 million ratings has about 1.8 million reviews.

**Why pick a language, not a country?**
Google Play splits reviews by **language**: English reviews are the same in the US, UK and India. Pick several languages, or use **All major languages**, to collect reviews from everywhere. The country setting controls the app data (price, availability).

**Can I sort by "most relevant" and filter by date?**
Yes. When you set *Reviews from*, reviews are read newest first, so the run can stop at your date instead of reading the app's whole history. To see the most-liked reviews first, sort the dataset by `thumbsUp`.

**Do I need a proxy?**
No. The Actor connects directly and switches to Apify Proxy by itself if Google ever slows it down, at no extra cost to you.

**What happens with a wrong app ID?**
It's skipped and listed as "not found" in the summary; the rest of the run continues. You're never charged for apps that don't exist.

**Can I get iOS / App Store reviews?**
This Actor is for Google Play only.

**Is scraping Google Play reviews legal?**
The Actor collects only publicly visible reviews. Reviewer names are public personal data, so if you are in the EU or handle data of EU residents, make sure you have a legitimate purpose under GDPR and don't store more than you need. When in doubt, ask a lawyer.

**Need a field or found a problem?**
Open an issue in the **Issues** tab. Issues get answered fast, and the October 17 update came directly from real runs.

# Actor input Schema

## `appIds` (type: `array`):

App IDs (<code>com.spotify.music</code>) or any Google Play link. Developer, category and top-chart links work too: we find their apps and scrape each one's reviews.

## `searchQueries` (type: `array`):

Search Google Play and scrape reviews of the top results, e.g. <code>habit tracker</code> or <code>budget app</code>. Great for competitor research.

## `maxAppsPerSearch` (type: `integer`):

How many apps to take from each keyword search, developer, category or chart link (in Google Play's order). Keyword searches return up to 30.

## `maxReviewsPerApp` (type: `integer`):

Limit for each app (and each language). Set <b>0 to get every review</b> Google Play has for the app.

## `sortBy` (type: `string`):

Same order as the Play Store's review list. When you set <b>Reviews from</b>, reviews are read newest first so the run can stop at your date.

## `languages` (type: `array`):

Google Play groups reviews by language, not country. Pick several languages to collect them all in one run (duplicates are removed).

## `allLanguages` (type: `boolean`):

Ignore the list above and collect reviews in the 25 most common Play Store languages: global coverage in one run.

## `country` (type: `string`):

Store country for app data (price, availability). Reviews are mostly the same in every country.

## `ratings` (type: `array`):

Leave empty for all ratings. Pick 1★ + 2★ to collect complaints only.

## `reviewsFrom` (type: `string`):

Only reviews posted on or after this date. Use a date or a relative period like <code>7 days</code>.

## `reviewsTo` (type: `string`):

Only reviews posted on or before this date.

## `keywords` (type: `array`):

Keep reviews whose text contains at least one of these words (not case-sensitive), e.g. <code>crash</code>, <code>refund</code>, <code>battery</code>.

## `replyFilter` (type: `string`):

Filter by whether the developer answered the review.

## `onlyNewReviews` (type: `boolean`):

Remembers the newest review it saw for every app and language, and next time saves only reviews posted after it. The first run saves the newest reviews (up to Max reviews per app) as a starting point.

## `monitorId` (type: `string`):

Keeps separate memory per monitor. Use a different name for each scheduled task watching the same app.

## `maxConcurrency` (type: `integer`):

How many apps to scrape at the same time.

## `proxyConfiguration` (type: `object`):

Not needed: by default the Actor connects directly and switches to Apify Proxy by itself if Google slows it down (free for you). Set this only to force your own proxies.

## Actor input object example

```json
{
  "appIds": [
    "com.spotify.music",
    "https://play.google.com/store/apps/details?id=com.duolingo"
  ],
  "searchQueries": [
    "habit tracker"
  ],
  "maxAppsPerSearch": 10,
  "maxReviewsPerApp": 100,
  "sortBy": "newest",
  "languages": [
    "en"
  ],
  "allLanguages": false,
  "country": "us",
  "replyFilter": "all",
  "onlyNewReviews": false,
  "monitorId": "default",
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

No description

## `report` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "appIds": [
        "com.spotify.music"
    ],
    "maxReviewsPerApp": 100,
    "languages": [
        "en"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fermaja/google-play-reviews-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "appIds": ["com.spotify.music"],
    "maxReviewsPerApp": 100,
    "languages": ["en"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("fermaja/google-play-reviews-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "appIds": [
    "com.spotify.music"
  ],
  "maxReviewsPerApp": 100,
  "languages": [
    "en"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call fermaja/google-play-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fermaja/google-play-reviews-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Rlu1GuZsagAJah4La/builds/aWJmdtzpv3I9ITmzg/openapi.json
