# Google Play Reviews Scraper & API - Installs, Rankings, Charts (`akhil_rajesh/google-play-reviews-scraper`) Actor

Scrape Google Play reviews newest first and as deep as you need, with developer replies, app versions, filters (stars, dates, words, versions) and Slack, Discord or Teams alerts for new reviews, plus installs, data safety, developer email, keyword rankings and top charts.

- **URL**: https://apify.com/akhil_rajesh/google-play-reviews-scraper.md
- **Developed by:** [Akhil rajesh](https://apify.com/akhil_rajesh) (community)
- **Categories:** Marketing, SEO tools, MCP servers
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.07 / 1,000 reviews

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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** reads **Google Play reviews**, newest first and as deep as you need (tens of thousands per app), with **developer replies**, the **app version** each review was written for and its **helpful votes**, in any language, filtered by stars, dates, words, replies, versions or votes, and posts **new reviews to Slack, Discord or Microsoft Teams** after each scheduled run. It also gives you each app's **details** (exact installs, ratings histogram, price, in-app purchases, **data safety**, developer email, website and address), where apps **rank in Google Play search** for your keywords, and the **top charts**, each with **what moved since your last run**. Paste Play Store links, package names or app names; get JSON, CSV or Excel, or use the API. No login, API key or proxy needed. AI agents can call it as an **MCP server** too, with tools for reviews, app details, rankings and charts ([see below](#for-ai-agents-mcp-server-and-live-api)).

- **Reviews, newest first and deep.** Each review's stars, text, reviewer and picture, date, app version, helpful votes, and the developer's reply with its date. 100 reviews a page: 10,000 reviews take about a minute.
- **By language.** Google Play groups reviews by language, not country: the same English reviews show in the US, the UK and India (checked on 2026-10-19). Pick one or many languages, and each app's reviews are read in each.
- **Star filters asked from Google Play.** Only 1-star reviews, or any mix of stars, asked from Google Play directly, so you never pay for reviews you filter out. With several stars, Max reviews per app is shared evenly between them (a star with fewer reviews passes its room to the others).
- **Reviews since a date** (`2026-01-31`) or a period (`30 days`): with newest first, reading stops at the first older review.
- **Filters on what reviews say.** Only reviews that mention words or phrases you pick ("crash", "refund", "dark mode"; each review lists the ones it matched), only those the developer replied to or those still waiting for a reply, only those for app versions you pick (`9.1` matches every 9.1.x), with at least N helpful votes, or of at least N characters. You pay only for the reviews returned.
- **Only new reviews.** For a daily or hourly schedule: each run returns, and charges for, only the reviews earlier runs didn't, and stops reading where those begin.
- **Alerts in Slack, Discord or Teams.** Add a webhook URL and each scheduled run posts its new 1-2 star reviews (or the stars you pick) to your channel, with stars, text, app version, date and a link to the review. Zapier, Make, n8n or your own server get them as JSON. No extra charge.
- **A review summary per app.** Average stars of the reviews read, the share of 1-2 star reviews, the developer's reply rate, reviews per day, the app versions reviewed most, and the words most 1-2 star and 4-5 star reviews use ("ads", "crash", "premium"...).
- **App details.** Installs as shown ("1,000,000,000+") and Google Play's exact count (3,164,200,596 for Spotify), rating and rating count with the 1-5 star histogram, written review count, price and sale price, in-app purchase price range, contains ads, category, age rating, release and update dates, version and minimum Android, what's new, screenshots and video, developer email, website, address, phone and legal name, privacy policy, and the **data safety** section: data shared and collected (each type with its category, purposes and whether it's optional) and security practices.
- **Keyword rankings.** Where apps rank in Google Play search for each keyword and country, in Google Play's own order (its exact-match card first). Your apps are marked, and listed even when they don't rank. Each run adds the previous rank and the move since.
- **Top charts.** Top free, top paid and top grossing, overall or for any of 54 categories (Games, Finance, every game genre...), up to 200 positions, with each app's previous rank, its move, new entries and the apps that dropped out.
- **Honest about failures.** A package Google Play doesn't have gets a free "not found" note, never a charged empty row. When Google Play refuses or doesn't answer, the run says what didn't load; it never reports "no reviews" for a page it couldn't read.

### Why this scraper

What people most often report about Google Play review scrapers, and what this one does about it:

| Common problem | Here |
|---|---|
| Stuck at 150 reviews, or paging stops after page 1 | Follows Google Play's own page tokens to the end of the list: 6,000 Spotify reviews read in a row without a refusal |
| No app version on reviews | Every review carries the app version it was written for, and you can filter on it |
| The same reviews come back twice | Each review is stored once, also when a run is restarted: a live run rebooted in the middle of 3,000 reviews stored every one once |
| A shape that changes between runs | Every row follows the Actor's published dataset schema |
| Asked for one app or country, got another | It never substitutes another app: a package it can't find gets a free row saying why, with Google Play's suggestions |
| Only English, or only a few countries | Any review language Google Play has, and app details, rankings and charts in 175 countries |

### Use cases

- **Review monitoring and alerts.** Schedule a daily or hourly run with an alert webhook: new 1-2 star reviews land in your Slack, Discord or Teams channel as soon as Google Play lists them (its review lists ran about a day behind the reviews' dates on 2026-10-19). Add **Not replied to** to see which complaints still need an answer. A cheap alternative to review-monitoring subscriptions: 5 apps with 50 new reviews a day cost about $0.90 a month.
- **Release quality checks.** Each review carries the app version it was written for: filter on the new version (`9.1`) and compare its stars and complaints with the last.
- **Competitor analysis.** Read competitors' reviews, installs, ratings, pricing, in-app purchases and data safety declarations; compare their review summaries to see what their users ask for.
- **App store optimization (ASO).** Track where your app and your competitors rank for your keywords, country by country, and how ranks move after a release or a listing change.
- **Lead generation and market research.** Read a category's charts or a keyword's results, then run the apps found with app details on for each developer's email, website and address.
- **Sentiment analysis and AI.** Clean, deduplicated review text with stars, dates, versions and replies, ready for a spreadsheet, a database, a BI tool or a language model.

### How to use it in 4 steps

1. Add apps (Play Store links, package names or names), pick languages for reviews and countries for details, rankings and charts.
2. Set Max reviews per app, and filters if you want them (stars, a date, words, replies, versions, only new reviews).
3. For alerts, paste a Slack, Discord or Teams webhook URL, then put the run on a schedule (Schedules in Apify Console).
4. Optionally add keywords to track rankings and charts to follow.
5. Start the run, then download the results as JSON, CSV or Excel from the Output tab, or read them through the API.

### What you get

Every row has `type`: `review`, `reviewSummary`, `app`, `keywordRank`, `chart`, or `notFound` (free). The Output tab has a view for each kind, showing that kind's columns; every view lists all the run's rows, so filter on `type` (a view can't filter rows on Apify).

**Review**

| Field | Example |
|---|---|
| `appId`, `appTitle`, `language` | com.spotify.music, Spotify: Music and Podcasts, en |
| `reviewId`, `rating`, `text`, `url` | 9704fda9-c2f8-4095-9a54-b67b4ee8dd2f, 1, The song I play doesn't play., a link to the review |
| `userName`, `userImage`, `date` | Munmun Roy, the reviewer's picture, 2026-10-18T04:23:11Z |
| `appVersion`, `thumbsUp` | 9.1.88.2204, 0 |
| `developerReply`, `developerReplyDate` | Hi. Have you tried a quick reinstall?..., 2026-10-18T15:42:19Z |
| `matchedTerms` | \[play] (with Reviews that mention) |

**Review summary** (one per app and language): `reviewsRead`, `averageRating`, `ratingCounts`, `lowRatingShare`, `developerReplies`, `developerReplyRate`, `oldestReviewDate`, `newestReviewDate`, `daysCovered`, `reviewsPerDay`, `appVersions`, `topWordsLowRatings`, `topWordsHighRatings`, and the filters used (`starFilter`, `since`, `reviewFilter`).

**App details** (one per app and country)

| Field | Example |
|---|---|
| `appId`, `title`, `summary`, `url` | com.spotify.music, Spotify: Music and Podcasts, Listen to songs, play podcasts... |
| `installs`, `minInstalls`, `exactInstalls` | 1,000,000,000+, 1000000000, 3164200596 |
| `rating`, `ratingCount`, `reviewCount`, `histogram` | 4.35, 36,503,960, 1,856,519, {"1": 3719038, ..., "5": 27308004} |
| `price`, `currency`, `free`, `containsAds`, `inAppPurchases`, `inAppPurchaseRange` | 0, USD, true, true, true, $4.99 - $203.88 per item |
| `developer`, `developerEmail`, `developerWebsite`, `developerAddress`, `developerPhone`, `developerLegalName` | Spotify AB, support@spotify.com, https://www.spotify.com, Regeringsgatan 19, 111 53 Stockholm, Sweden, +46 10 334 03 65 |
| `genre`, `genreId`, `categories`, `contentRating` | Music & Audio, MUSIC_AND_AUDIO, Teen |
| `released`, `updated`, `version`, `minAndroidVersion`, `releaseNotes` | 2014-05-27, 2026-10-14T05:44:28Z |
| `dataSafety` | sharedData: Approximate location (Analytics, Advertising or marketing)...; collectedData; securityPractices: Data is encrypted in transit... |
| `privacyPolicyUrl`, `icon`, `headerImage`, `screenshots`, `video`, `description` | |

**Keyword rank**: `keyword`, `country`, `language`, `rank`, `appId`, `title`, `developer`, `rating`, `installs`, `genre`, `price`, `isTrackedApp`, `notRanked`, `previousRank`, `rankChange`, `isNew`, `droppedOut`.

**Chart**: `chart`, `category`, `country`, `rank`, `appId`, `title`, `developer`, `rating`, `installs`, `genre`, `price`, `previousRank`, `rankChange`, `isNew`, `droppedOut`, `url`.

A review row as it comes:

```json
{
  "type": "review",
  "store": "googlePlay",
  "appId": "com.spotify.music",
  "appTitle": "Spotify: Music and Podcasts",
  "language": "en",
  "reviewId": "9704fda9-c2f8-4095-9a54-b67b4ee8dd2f",
  "rating": 1,
  "text": "The song I play doesn't play.",
  "userName": "Munmun Roy",
  "date": "2026-10-18T04:23:11Z",
  "thumbsUp": 0,
  "developerReply": "Hi. Have you tried a quick reinstall? If that doesn't help, we'd recommend reaching out to our Customer Service...",
  "developerReplyDate": "2026-10-18T15:42:19Z",
  "url": "https://play.google.com/store/apps/details?id=com.spotify.music&reviewId=9704fda9-c2f8-4095-9a54-b67b4ee8dd2f"
}
```

### How to use it

#### Apps

Add apps in any form: a Play Store link (`https://play.google.com/store/apps/details?id=com.spotify.music`), a package name (`com.spotify.music`) or a name (`spotify`). A name is looked up on Google Play's search: Google's own exact match is taken when it fits; otherwise the title must hold every word you type, and the closest, most-installed one wins. The status message and each row's `matchedBy` say which app a name matched, so check it, or use links and package names to be sure.

#### Countries and languages

- **Languages** decide which reviews are read (Google Play groups reviews by language). The first language is also used for app details and search.
- **Countries** decide app details (price, availability, the age rating's system), search rankings and charts.

#### Reviews

- **Max reviews per app**: per app and language, after the filters. 0 turns reviews off.
- **Order**: newest first, or Google Play's "most relevant".
- **Star ratings**: asked from Google Play directly; with several picked, Max reviews per app is shared evenly, and rows come star by star, each newest first.
- **Reviews since**: a date (`2026-01-31`) or a period (`30 days`, `3 months`). Google Play's review lists ran about a day behind on 2026-10-19, so "2 days" gave about one day of reviews.
- **Reviews that mention**: words or phrases, any of which a review's text must contain, in any case and with or without accents. A word also matches the longer words it begins: `crash` finds "crashes" and "crashing", not "scrash". Each review lists what it matched in `matchedTerms`.
- **Developer reply**: only reviews the developer replied to, or only those without a reply.
- **App versions**: `9.1` matches 9.1 and every 9.1.x (9.1.88.2204), not 9.10. Reviews that name no version are left out.
- **Minimum helpful votes** and **Minimum review length** (characters of text).
- **How far filters read**: Google Play can't apply the word, reply, version, votes and length filters, so the run reads reviews until Max reviews per app pass them, or at most 10 times that number (at least 2,000 reviews) per app and language, and says so when it stops there. Raise Max reviews per app to read further. Only the reviews returned are charged.
- **Only new reviews**: see below.

#### Keyword rankings

Add keywords and pick how many positions to read (25 by default). Google Play's search page lists about 20-30 apps per keyword, in Google Play's own order; a brand search opens with Google's exact-match card, ranked first. Your apps (in Apps) are marked `isTrackedApp`, and an app of yours that isn't in the positions read gets a row with `notRanked: true`.

#### Top charts

Pick top free, top paid and/or top grossing, and categories (empty: all apps; "Games (all)" is every game). Up to 200 positions per chart.

### Alerts in Slack, Discord or Microsoft Teams

Paste a webhook URL in **Alert webhook URL**, pick the stars to post (1 and 2 by default), and schedule the run (daily or hourly). Setting a webhook turns on **Only new reviews**.

- **The first run** sets the baseline: it posts a short "alerts are set up" message naming the apps and languages it watches, so you know the webhook works, and no reviews.
- **Each later run** posts the reviews new since the run before, newest first: stars, text (the first 600 characters), app, language, app version, date, and a link to the review. Up to 50 reviews a run; past that, the last message counts the rest, which are all in the dataset.
- **Where to get the URL**:
  - **Slack**: create an app at api.slack.com/apps, turn on Incoming Webhooks, click Add New Webhook to Workspace, pick the channel and copy the `https://hooks.slack.com/services/...` URL.
  - **Discord**: Server Settings → Integrations → Webhooks → New Webhook, pick the channel, then Copy Webhook URL.
  - **Microsoft Teams**: in the channel, open Workflows and pick "Post to a channel when a webhook request is received", then copy its URL.
  - **Zapier, Make, n8n or your own server**: any HTTPS URL that takes JSON gets `{"text": "...", "reviews": [...], "moreReviews": 0}`, each review with its fields and a `link`.
- **Set Max reviews per app above the new reviews you expect between two runs.** A popular app gets dozens an hour (Spotify's English Google Play list had 20 new ones a few minutes after a run on 2026-10-19). When more arrive than Max reviews per app, the run returns and posts the newest, and its status says the older new ones were skipped.
- **Kept secret.** The URL is stored encrypted with the run's input and never shown in the log, the status or the output. It is only ever sent to its own address.
- **If posting fails**, the run still succeeds with its reviews in the dataset, and the status message says why (for example "HTTP 404: check the webhook URL"). Alerts cost nothing extra: you pay for the new reviews returned, as without alerts.

### Tracking changes on a schedule

Runs with the same **History name** compare with each other (empty name: one shared default history). Give each schedule its own name.

- **Rankings and charts**: each row gets `previousRank` and `rankChange` (positive is up: 5 to 2 is +3), new apps get `isNew`, and apps that left the positions read get a row with `droppedOut: true` (switch those off with Include apps that dropped out). The first run sets the baseline.
- **Only new reviews**: each run returns the reviews earlier runs with the same history didn't, newest first, and stops reading where the known ones begin. The first run returns the newest up to Max reviews per app.

The history lives in a key-value store in your account (`google-play-reviews-history` by default). Under Apify's limited permissions the Actor can only open stores it created itself, so pick a new name rather than one made elsewhere, including one made by the App Store Reviews Scraper.

### Run summary for pipelines

Each run saves `RUN_SUMMARY` in its key-value store: rows by type, what wasn't found, what didn't load and why, notes (names matched, filters that ended a list), and the requests made. The output tab links it.

### Use it via the API, from code or from an AI assistant

Start a run and get the rows in one call (replace `<YOUR_TOKEN>`):

```bash
curl -X POST "https://api.apify.com/v2/acts/akhil_rajesh~google-play-reviews-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"apps": ["com.spotify.music"], "languages": ["en", "de"], "maxReviewsPerApp": 500, "starRatings": ["1", "2"]}'
```

Or from Python with `apify-client`:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("akhil_rajesh/google-play-reviews-scraper").call(run_input={
    "apps": ["https://play.google.com/store/apps/details?id=com.duolingo"],
    "maxReviewsPerApp": 1000, "reviewsSince": "30 days",
})
for row in client.dataset(run.default_dataset_id).iterate_items():
    print(row["type"], row.get("rating"), row.get("appVersion"), row.get("text", "")[:80])
```

#### For AI agents: MCP server and live API

The Actor also runs as a **live endpoint** (Apify Standby): an **MCP server** that agents call directly, and plain HTTP endpoints. Once a Standby run is up, a request is answered in seconds; the first request starts one. Authenticate with your Apify API token in the `Authorization: Bearer <token>` header.

**MCP server** (Streamable HTTP): `https://akhil-rajesh--google-play-reviews-scraper.apify.actor/mcp`

```json
{"mcpServers": {"google-play-reviews": {"type": "http", "url": "https://akhil-rajesh--google-play-reviews-scraper.apify.actor/mcp",
  "headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
```

In Claude Code:

```bash
claude mcp add --transport http google-play-reviews https://akhil-rajesh--google-play-reviews-scraper.apify.actor/mcp --header "Authorization: Bearer <YOUR_APIFY_TOKEN>"
```

A client that can't send headers can use `https://akhil-rajesh--google-play-reviews-scraper.apify.actor/mcp?token=<YOUR_APIFY_TOKEN>`; keep that URL private, as it carries your token. Through **Apify's MCP server** (`https://mcp.apify.com`, for Claude, ChatGPT, Cursor and other clients), add the tools with `https://mcp.apify.com?tools=akhil_rajesh/google-play-reviews-scraper` (they appear as `akhil_rajesh--google-play-reviews-scraper--get_reviews` and so on), then ask in plain words, for example *"what do the newest 1-star reviews of WhatsApp complain about?"*. Add them that way rather than through Apify's generic `call-actor` tool, which returns the rows only as text and shows clients that read structured results a summary instead. Apify's MCP server doesn't offer Actors with a live endpoint to agents that pay per call with x402 or Skyfire: connect with an Apify account or API token.

| Tool | What it returns |
|---|---|
| `get_reviews` | Google Play reviews newest first (or most relevant) per language, with app versions, developer replies and filters on stars, dates, words, replies, versions, votes and length; a summary row per app |
| `get_app_details` | Exact installs, ratings with their histogram, price, data safety, developer contacts |
| `get_keyword_rankings` | Where apps rank in Google Play search for each keyword, your apps marked |
| `get_top_charts` | Top free, paid and grossing charts, overall or by category |
| `run_actor` | The Actor's whole input in one call: reviews, details, rankings and charts together |

**HTTP endpoints**, such as `GET https://akhil-rajesh--google-play-reviews-scraper.apify.actor/reviews?apps=com.spotify.music&max=50&stars=1` (defaults in brackets). The Actor's **Endpoints** tab in Apify Console lists them too, and lets you try them.

| Endpoint | Parameters |
|---|---|
| `GET /reviews` | `apps`, `languages` (en; reviews are per language), `countries` (us), `max` (100), `sort` (newest, mostRelevant), `stars`, `since`, `contains`, `reply` (withReply, withoutReply), `minLength`, `summary` (true), `minThumbsUp`, `versions` (9.1 matches 9.1.x) |
| `GET /app` | `apps`, `countries` (us) |
| `GET /rankings` | `keywords`, `countries` (us), `positions` (25), `apps` (yours, marked) |
| `GET /charts` | `charts` (top-free, top-paid, top-grossing), `categories`, `countries` (us), `positions` (100) |
| `POST /run` | The Actor's whole input as the JSON body |

**Answers** carry the `rows`, `rowsByType`, `notFound` (apps the store doesn't know: free), `notLoaded` (what the store didn't answer), `notRead` (what a limit left out: not charged) and `notes`. A request that reads nothing gets an `error` and nothing is charged: HTTP 400 for an argument it can't read (a tool error over MCP), 503 when the store didn't answer or the run was busy (send it again, after the `Retry-After` seconds when the store asked for a pause), 402 when your spending limit for the run is reached (it lifts when the run ends, after 2 minutes without requests). A 503 can also carry rows, when the platform stopped the run while a request was being read: those were stored and charged, and `notRead` names the rest. Apify itself answers 429 when an account sends too many requests at once.

**Limits per request**: an MCP tool call reads up to 5 apps, 500 reviews per app and about 350 kB of rows (about 500 reviews) within 50 seconds, and asks for 50 reviews per app unless told otherwise (MCP clients stop waiting at 60 seconds, and Apify's MCP server drops answers over about 1 MB); an HTTP request reads up to 20 apps, 1,000 reviews per app and about 6 MB within 170 seconds. What a limit leaves out is named in `notRead` and isn't charged. **A request that has started runs to its end even if you stop waiting**: Apify's Standby proxy keeps it open, so its rows are read and charged (they stay in that Standby run's dataset). Ask for what you need. Tracking (Only new reviews, rank moves) and alerts belong to scheduled runs: the live endpoint answers each request on its own, so it ignores those fields. For more reviews, or tracking, run the Actor normally.

### How much does it cost?

You pay **$0.10 per 1,000 reviews** and **$1.00 per 1,000 other rows** (app details, review summaries, keyword ranks, chart rows), less on paid Apify plans, plus a start fee of $0.00005 per run. **Platform usage is included** in runs of the Actor: there is no compute charge on top. Not-found rows are free. The live endpoint (MCP server and HTTP API) charges rows at the same prices, plus the Standby run's platform usage while it serves you and until it has been idle for 2 minutes (a short session costs a fraction of a cent).

| Apify plan | Per 1,000 reviews | Per 1,000 other rows |
|---|---|---|
| Free | $0.10 | $1.00 |
| Starter | $0.09 | $0.90 |
| Scale | $0.08 | $0.80 |
| Business and above | $0.07 | $0.70 |

| Run | Rows | Cost (Free plan) |
|---|---|---|
| One app's 100 newest reviews with its details (the default input) | 100 reviews + 2 rows | about $0.01 |
| 10,000 reviews of one app | 10,000 reviews + 2 rows | about $1.00 |
| A daily schedule of 5 apps with Only new reviews (and alerts), 50 new reviews each | 250 reviews + 5 summaries | about $0.03 a day |
| 10 keywords, 25 positions each, in one country | 250 rank rows | $0.25 |
| Top free, paid and grossing games, 100 each, in 3 countries | 900 chart rows | $0.90 |

Apify's free plan ($5 of monthly credit) covers about 50,000 reviews. A keyword's rows for your apps that don't rank (`notRanked`) count as rank rows. To cap spending, lower Max reviews per app or set a maximum cost per run in the run options; the Actor stops cleanly at the limit.

### Input

```json
{
  "apps": ["https://play.google.com/store/apps/details?id=com.spotify.music", "duolingo"],
  "countries": ["us", "in"],
  "languages": ["en", "hi"],
  "maxReviewsPerApp": 500,
  "reviewSort": "newest",
  "starRatings": ["1", "2"],
  "reviewsSince": "30 days",
  "reviewContains": ["crash", "login"],
  "developerReply": "withoutReply",
  "appVersions": ["9.1"],
  "minThumbsUp": 1,
  "onlyNewReviews": false,
  "includeReviewSummary": true,
  "includeAppDetails": true,
  "keywords": ["music player", "podcast app"],
  "rankPositions": 25,
  "charts": ["top-free", "top-grossing"],
  "chartCategories": ["MUSIC_AND_AUDIO", "GAME"],
  "chartPositions": 100,
  "historyName": "spotify-daily"
}
```

Every field is optional; an input naming nothing reads the example app's 100 newest reviews and details.

For alerts on a schedule:

```json
{
  "apps": ["com.spotify.music", "com.duolingo"],
  "languages": ["en", "de"],
  "maxReviewsPerApp": 300,
  "alertWebhookUrl": "https://discord.com/api/webhooks/...",
  "alertStars": ["1", "2"],
  "historyName": "my-apps-alerts"
}
```

### Good to know

- **Reviews are per language.** Google Play shows the same reviews in every country for one language. To read Indian reviews in Hindi, add `hi`; English reviews from India are among the `en` ones.
- **`ratingCount` and `reviewCount`.** Google Play counts star ratings and written reviews separately; only written reviews can be read. The rating is the country's, while the rating count and the histogram are worldwide (the histogram scaled to the country's average); the written review count is the country's.
- **Charts and search order.** Google Play serves its charts and search results in a different order from one request to the next: back-to-back requests on 2026-10-19 moved up to 64 of a chart's 100 apps, by up to 22 places. The Actor reads each chart and search 3 times and ranks apps by their median position, so moves of a few places between runs can still be noise; new and dropped-out apps are reliable.
- **Release dates.** `released` is an ISO date for pages in English, German, Japanese and Korean; for other languages read `releasedText`. Apps whose version depends on the device have no `version` or `minAndroidVersion`.
- **Countries.** An app Google Play doesn't sell in the first country is looked up in the others before it is called not found.
- **Search depth.** Google Play's search lists about 20-30 apps per keyword, so rankings stop there.
- **Data safety** is read once per app, in English, and added to its detail rows.
- **"Most relevant" order** is Google's own; Reviews since and Only new reviews stop early only with newest first.

### FAQ

**How many reviews can I get?** As many as Google Play keeps for the app and language: 6,000 Spotify reviews read in a row on 2026-10-19 without a refusal. Set Max reviews per app up to 100,000.

**Can it post new reviews to Slack?** Yes: paste a Slack incoming webhook in Alert webhook URL and schedule the run. Discord, Microsoft Teams and any JSON webhook (Zapier, Make, n8n) work the same way. See Alerts above.

**Can I get the reviews of one app version?** Yes: put it in App versions (`9.1` matches every 9.1.x). Each review also carries its version, and the review summary lists the versions reviewed most.

**Can I get App Store reviews too?** Yes, with the [App Store Reviews Scraper](https://apify.com/akhil_rajesh/app-store-reviews-scraper), built on the same code, with the same fields where the stores agree.

**Do I need a proxy?** No. Google Play answers Apify's servers directly. Apify's datacenter proxy or your own proxies can be used; residential proxies are refused, as they're billed per GB on top of the result price.

**Why does a name match the wrong app?** A name is matched among Google Play's search results: Google's exact match is taken when it fits; otherwise every word you type must be in the title, and the closest, most-installed one wins. If that isn't the app you meant, use its link or package name.

**Is it legal?** The Actor reads public Google Play pages that anyone can open without an account. Reviews are written under display names; use them in line with Google's terms and the privacy laws that apply to you.

### Other Actors by this developer

- [App Store Reviews Scraper](https://apify.com/akhil_rajesh/app-store-reviews-scraper): Apple App Store reviews, app details, privacy labels, keyword rankings and charts
- [Amazon.ca Product & Trending Tracker](https://apify.com/akhil_rajesh/amazon-ca-product-trending-tracker): Amazon Best Sellers, prices, search positions and reviews on 23 marketplaces, with change tracking
- [AliExpress Price Tracker & Scraper](https://apify.com/akhil_rajesh/aliexpress-price-tracker): AliExpress search results with store prices, units sold and price history
- [Yahoo Finance Scraper, API & MCP](https://apify.com/akhil_rajesh/yahoo-finance-scraper): quotes, history, options, financials and more

### Disclaimer

This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Google. It reads publicly available Google Play pages at a modest pace. Use the data in line with Google's terms and the laws that apply to you.

# Actor input Schema

## `apps` (type: `array`):

Google Play links (play.google.com/store/apps/details?id=com.spotify.music), package names (com.spotify.music) or app names (a name is looked up on Google Play's search and must hold every word you type; the row says which app it matched).

## `countries` (type: `array`):

Google Play countries for app details (price, availability), search rankings and charts. Reviews go by language, not country (see Languages). Empty: United States.

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

Review languages: Google Play groups reviews by language, so each app's reviews are read in each language picked (Max reviews per app applies to each). The first language is also used for app details and search. Empty: English. Codes such as pt-PT work too.

## `includeReviews` (type: `boolean`):

Read each app's reviews.

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

Reviews to read per app and language, after the filters (100 a page: 10,000 reviews take about a minute). 0: no reviews.

## `reviewSort` (type: `string`):

Newest first, or the store's own ranking (most relevant). Reviews since and Only new reviews stop early only with newest first.

## `starRatings` (type: `array`):

Only reviews with these stars, asked from Google Play directly: with several picked, Max reviews per app is shared evenly between them. Empty: all.

## `reviewsSince` (type: `string`):

Only reviews written on or after this date (UTC), or within this period (7 days, 3 months). With newest first, reading stops at the first older review.

## `reviewContains` (type: `array`):

Only reviews whose text mentions any of these words or phrases (crash, refund, dark mode), in any case and with or without accents. A word also matches the longer words it begins (crash: crashes, crashing). Each review lists the ones it matched (matchedTerms). Empty: every review. With this filter or the ones below, a run reads reviews until Max reviews per app match, or at most 10 times that number (at least 2,000) per app and language: only the reviews returned are charged.

## `developerReply` (type: `string`):

Only reviews the developer replied to, or only those without a reply (to find the ones still waiting). Empty: both.

## `minReviewLength` (type: `integer`):

Only reviews whose text has at least this many characters: 100 leaves out 'great app' and keeps reviews that explain. Empty or 0: any length.

## `minThumbsUp` (type: `integer`):

Only reviews at least this many people marked helpful. Empty or 0: any.

## `appVersions` (type: `array`):

Only reviews written for these app versions: 8.9 matches 8.9 and every 8.9.x (8.9.12.345), not 8.90. Reviews that name no version are left out. Empty: every version.

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

Return only reviews earlier runs with the same History name didn't return, and stop reading where those begin (newest first). For a daily schedule: each run delivers, and charges for, the new reviews only. The first run returns the newest up to Max reviews per app.

## `includeReviewSummary` (type: `boolean`):

One row per app (and language) with what its reviews said: average stars, share of 1-2 star reviews, developer reply rate, reviews per day, and the words most 1-2 star and 4-5 star reviews use.

## `alertWebhookUrl` (type: `string`):

A Slack incoming webhook (https://hooks.slack.com/services/...), a Discord channel webhook (https://discord.com/api/webhooks/...), a Microsoft Teams Workflows webhook, or any HTTPS URL that takes JSON (Zapier, Make, n8n, your server). Setting it turns on Only new reviews. Stored encrypted, and never shown in the log or the output.

## `alertStars` (type: `array`):

Which new reviews to post (up to 50 a run, newest first; the rest are counted). Empty: 1 and 2 stars. Every new review is returned in the dataset either way.

## `includeAppDetails` (type: `boolean`):

One row per app and country: installs (with Google Play's exact count), ratings with their histogram, price, in-app purchases, data safety, developer email, website and address.

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

Search terms (budget app, photo editor). One ranking per keyword and country.

## `rankPositions` (type: `integer`):

Ranks to read per keyword. Google Play's search lists about 20-30 apps per keyword.

## `charts` (type: `array`):

Charts to read, in each country.

## `chartCategories` (type: `array`):

Categories of each chart. Empty: all apps. (Games (all) is every game; Family the family section.)

## `chartPositions` (type: `integer`):

Ranks to read per chart (up to 200).

## `compareWithLastRun` (type: `boolean`):

Add each app's previous rank and move, and mark new apps. The first run sets the baseline.

## `includeDroppedOut` (type: `boolean`):

Add a row for each app in the last run's ranking or chart that isn't in this one (on top of the positions asked for).

## `historyName` (type: `string`):

Name of the key-value store that keeps the tracking history (a-z, 0-9 and hyphens). Empty: google-play-reviews-history. Use a new name to start over; under limited permissions the Actor can only open stores it created itself.

## `proxy` (type: `object`):

Google Play needs no proxy. Apify's datacenter proxy or your own proxies can be used; residential proxies are refused (billed per GB on top of the result price).

## Actor input object example

```json
{
  "apps": [
    "com.spotify.music"
  ],
  "countries": [
    "us"
  ],
  "languages": [
    "en"
  ],
  "includeReviews": true,
  "maxReviewsPerApp": 100,
  "reviewSort": "newest",
  "onlyNewReviews": false,
  "includeReviewSummary": true,
  "includeAppDetails": true,
  "rankPositions": 25,
  "chartPositions": 100,
  "compareWithLastRun": true,
  "includeDroppedOut": true,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `reviewSummaries` (type: `string`):

No description

## `apps` (type: `string`):

No description

## `keywordRanks` (type: `string`):

No description

## `charts` (type: `string`):

No description

## `notFound` (type: `string`):

No description

## `allData` (type: `string`):

No description

## `runSummary` (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 = {
    "apps": [
        "com.spotify.music"
    ],
    "countries": [
        "us"
    ],
    "languages": [
        "en"
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("akhil_rajesh/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 = {
    "apps": ["com.spotify.music"],
    "countries": ["us"],
    "languages": ["en"],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("akhil_rajesh/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 '{
  "apps": [
    "com.spotify.music"
  ],
  "countries": [
    "us"
  ],
  "languages": [
    "en"
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call akhil_rajesh/google-play-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,akhil_rajesh/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/k8XURkz6oiW8mAlWz/builds/RPqIeFiHsUg2NRuJg/openapi.json
