# Google Play Store Scraper — Apps, Reviews & Dev Email (`bovi/google-play-scraper`) Actor

Scrape app listings and reviews from Google Play. Get title, developer, installs, ratings, description, and developer email. Run with package names or search terms, no Google login. Pricing: $9.90 per 1,000 apps on Free.

- **URL**: https://apify.com/bovi/google-play-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** SEO tools, Developer tools, AI
- **Features:** Limited permissions
- **Stats:** 11 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.60 / 1,000 app data

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 Store Scraper — Apps, Reviews & Dev Email

For mobile growth managers, indie developers, and ASO agencies, this Actor scrapes public Google Play listings and up to 20 review rows per app. No Google account, API key, or login is required; each package returns one metadata record plus optional review records.

- Extract title, developer, installs, star average, per-star counts, category, and description.
- Read developer email and website when the listing publishes them, to contact that publisher.
- Compare ratings and install text for one package on another country and language.
- Download up to 20 review rows (author, stars, text, date, helpful votes, and version).
- Resolve a search keyword to package IDs, then scrape each listing.

### What you get

Metadata comes from `AF_initDataCallback` on the public app details page. Each kept review is another row and copies app columns, except `description` and `whats_new` are null. Filter on `record_type`.

| Family | Fields | What is stored |
|---|---|---|
| 📱 Listing | `record_type`, `app_id`, `title`, `page_url` | `app_meta` or `review`; Android package; details URL with `hl` and `gl`. |
| 🏢 Developer | `developer`, `developer_id`, `developer_email`, `developer_website` | Name, numeric id, email, and site. Email and site are null when absent. |
| 🏷️ Category | `category`, `category_id` | Label and store key (sample: Music & Audio, `MUSIC_AND_AUDIO`). |
| ⭐ Ratings | `rating_avg`, `rating_count`, `rating_1`, `rating_2`, `rating_3`, `rating_4`, `rating_5` | 0–5 average, total count, and one integer per star. |
| 📊 Listing figures | `installs`, `installs_min`, `price_usd`, `price_original`, `has_iap` | Install text, numeric floor, listing price, non-USD text, in-app purchase flag. |
| 📝 Copy | `content_rating`, `description`, `whats_new` | Age label (Everyone, Teen, Mature 17+), plain text with HTML removed, changelog. |
| 🕒 Dates and icon | `updated`, `released`, `icon_url`, `scraped_at` | ISO 8601 UTC update and release, icon URL, run time `YYYY-MM-DDTHH:MM:SSZ`. |
| 💬 Reviews | `review_id`, `review_author`, `review_rating`, `review_text`, `review_date`, `review_helpful`, `review_version` | On `review` rows; null on `app_meta`. Rating kept for 1, 2, 3, 4, or 5. |
| 🔎 Quality | `parse_confidence`, `warnings` | 0.0–1.0 score and reason strings for anything not found. |

> **Note:** Not affiliated with Google LLC or the Google Play Store.

> **Note:** If no price is parsed, `price_usd` is stored as 0. If a price is parsed in a currency other than USD, `price_usd` is the micro-amount divided by 1,000,000 and `price_original` is that figure plus the currency code. `has_iap` is true only when in-app purchase text is present.

A review is kept only when `review_id` is a string that does not start with `[` or contain `http`, and has text or a 1–5 rating. Other review objects are dropped.

App row: 0.30 title (`title_missing`), 0.10 developer (`developer_missing`), 0.05 category (`category_missing`), 0.10 on rating (`rating_missing`), 0.10 description (`description_missing`). Review row: 0.20 missing id, 0.05 missing author, 0.20 missing rating, 0.05 outside 1–5, 0.15 missing text, 0.10 missing date. These strings are `warnings`.

### Sample output

One `app_meta` row from a successful run, shortened by dropping whole fields not shown. Values that remain are unchanged except `developer_email`, which is shown as "<hidden for privacy>" so an email address is not published here.

```json
{
  "record_type": "app_meta",
  "app_id": "com.spotify.music",
  "title": "Spotify: Music and Podcasts",
  "developer": "Spotify AB",
  "developer_email": "<hidden for privacy>",
  "rating_avg": 4.349236,
  "rating_count": 36606899,
  "rating_1": 3722688,
  "rating_2": 1067555,
  "rating_3": 1310907,
  "rating_4": 3107162,
  "rating_5": 27398563,
  "installs": "1,000,000,000+",
  "installs_min": 1000000000,
  "price_usd": 0,
  "has_iap": true,
  "parse_confidence": 1
}
```

### Pricing

Pay per event. Each figure below is that plan’s live price. `app-data-item` (primary) is charged once per `app_meta` record (Free $0.0099, which is $9.90 per 1,000 and $99 per 10,000). `developer-contact` is charged once per `app_meta` record whose `developer_email` is present, and is not charged on review rows or when the email is null. `review-item` is charged once per kept review row. `apify-actor-start` is charged when the Actor starts; the count is one event per GB of memory, minimum one.

| Event | Plan | USD per event |
|---|---|---|
| App data (`app-data-item`) | Free | $0.0099 |
| App data (`app-data-item`) | Bronze | $0.009801 |
| App data (`app-data-item`) | Silver | $0.009702 |
| App data (`app-data-item`) | Gold | $0.009603 |
| App data (`app-data-item`) | Platinum | $0.009504 |
| App data (`app-data-item`) | Diamond | $0.009405 |
| Developer email (`developer-contact`) | Free | $0.0009 |
| Developer email (`developer-contact`) | Bronze | $0.000891 |
| Developer email (`developer-contact`) | Silver | $0.000882 |
| Developer email (`developer-contact`) | Gold | $0.000873 |
| Developer email (`developer-contact`) | Platinum | $0.000864 |
| Developer email (`developer-contact`) | Diamond | $0.000855 |
| App review (`review-item`) | Free | $0.0059 |
| App review (`review-item`) | Bronze | $0.005841 |
| App review (`review-item`) | Silver | $0.005782 |
| App review (`review-item`) | Gold | $0.005723 |
| App review (`review-item`) | Platinum | $0.005664 |
| App review (`review-item`) | Diamond | $0.005605 |
| Actor start (`apify-actor-start`) | Free | $0.00005 |
| Actor start (`apify-actor-start`) | Bronze | $0.0000495 |
| Actor start (`apify-actor-start`) | Silver | $0.000049 |
| Actor start (`apify-actor-start`) | Gold | $0.0000485 |
| Actor start (`apify-actor-start`) | Platinum | $0.000048 |
| Actor start (`apify-actor-start`) | Diamond | $0.0000475 |

10 results = $0.099 on Free. That figure is 10 `app-data-item` events only. A started run also pays `apify-actor-start` (one event on Free at 1 GB is $0.00005). Emails and reviews are extra events at the prices above.

On this pay-per-event Actor, platform usage (compute, Apify Proxy traffic including residential, and storage) is included in the event prices and is paid by the Actor developer. You are not billed a separate platform-usage line for those resources. The Apify Free plan includes $5 of monthly platform usage credit. After one Free actor-start event, that credit covers 505 `app-data-item` events on Free and nothing else: floor((5 − 0.00005) / 0.0099) = 505; review events or developer-email events spend the same credit faster.

### How to use

1. Sign in with your own Apify account and open this Actor.
2. Enter package names, search terms, or both. Direct packages stay in order; each search then appends package IDs that are not already listed.
3. Set country, language, and whether to include reviews. Change the prefilled proxy if you do not want the residential group.
4. Start the run. Use the input example below.
5. Open the dataset when the run finishes, then the OUTPUT record in key-value storage for `appsFailed` and `failedDetails`.
6. Repeat the run through Apify Schedules. A daily schedule is a reasonable starting point for listing and rating checks. Treat that cadence as a starting point only.

```json
{
  "appIds": ["com.spotify.music", "com.whatsapp"],
  "searchTerms": ["meditation app"],
  "country": "US",
  "lang": "en",
  "includeReviews": true
}
```

Export the dataset as JSON or CSV, or read the items with the Apify dataset API.

### Input parameters

The form prefills `appIds` with `com.spotify.music` and Apify Proxy with the RESIDENTIAL group. Defaults below are what the run uses when a field is omitted.

| Parameter | What it does | Default |
|---|---|---|
| `appIds` | Android package names. Blank entries are skipped. Details URL: https://play.google.com/store/apps/details?id=<package>\&hl=<lang>\&gl=<country>. | Empty list |
| `searchTerms` | Each term is a Play Store app search. Package-shaped IDs from that page are added, skipping duplicates. No max-results field. | Empty list |
| `country` | Storefront as `gl`, after uppercasing. Examples: US, GB, DE, FR, JP, CA, AU. Other strings are still sent. | `US` |
| `lang` | Locale as `hl`, after lowercasing. Examples: en, de, fr, ja, pt. Selects description and review language. Other strings are still sent. | `en` |
| `includeReviews` | When true, up to 20 review rows per app, each kept review as its own row. When false, only `app_meta` rows. | `true` |
| `proxyConfiguration` | When non-empty, detail, search, and review requests use this Apify Proxy URL. If setup fails, the run logs a warning and continues with no proxy. | Empty object if omitted; the form prefills RESIDENTIAL |

### Limits and edge cases

| Condition | What you see | What to do |
|---|---|---|
| `appIds` and `searchTerms` are both empty | No dataset rows. OUTPUT is `{"error": "no_input"}`. Actor start still applies when the run has started. | Pass at least one package or one search term. |
| Detail fetch fails (HTTP 403, 429, or 503; body under 5,000 characters; a sorry or unusual-traffic page; or no `ds:5` block) | Package skipped. `failedDetails` gets `app_id` and `reason` trimmed to 200 characters. Rows already pushed stay. | Retry that package. Adjust `proxyConfiguration`, or clear it to run without a proxy. |
| Review request fails | The app metadata row is still pushed. No review rows. The log records a warning. | Rerun with `includeReviews` true. Metadata does not depend on the review request succeeding. |
| A search fetch fails | That term adds no packages. Other terms and `appIds` continue. | Check the log, then pass known packages in `appIds`. |
| Broad search term | Every package ID parsed from the search page is scraped. Each success is an app-data charge, plus email and review events when those apply. | Use `appIds` when you already know the packages. |
| `includeReviews` is false | Only `app_meta` rows. No `review-item` charges. | Turn it on before the run if you need reviews. |
| More than 20 review rows | The review request asks for 20 and does not page further. At most 20 review rows per app. | No input raises that cap. |
| Review id missing, or no text and no 1–5 rating | That review is not pushed. | Expect fewer than 20 rows even when the request succeeds. |
| Same package from `appIds` and search | Scraped once. | No action. |
| Proxy setup throws | A warning is logged and the run continues without a proxy. | Fix the proxy object or leave it empty. |

`appsProcessed` in OUTPUT counts packages whose detail fetch did not fail. `appsFailed` is the length of `failedDetails`. `totalItems` is the number of dataset rows pushed. `scrapedAt` is the run timestamp.

These rows are public data from Play Store pages. Whether that collection is legal for a given use depends on Google’s terms and the law that applies to you.

### FAQ

#### How much does it cost to scrape Google Play?

Pay per event at the plan prices in Pricing, including the Free worked example and the $5 credit count.

#### Why is my Google Play scrape empty?

See Limits and edge cases for an empty input or a failed fetch. A search can add package IDs you did not expect, or none when that request fails. For a specific app, pass the package from the `id` parameter of a Play details URL.

#### What if reviews or developer emails do not come back?

See Limits and edge cases for the 20-review cap and for reviews that are dropped or whose request fails. `developer_email` is null when the listing has no email, and that app is not charged the developer-email event. Description on a review row is null; read it from the `app_meta` row for that `app_id`.

#### Do I need a Google login or a proxy?

No Google account, API key, or login is required. `proxyConfiguration` is optional. The form prefills Apify Proxy with the RESIDENTIAL group; omit the field, or leave it empty, to run without a proxy.

#### Is scraping Google Play allowed?

This Actor reads public data on Play Store pages and a public review endpoint without a Google login. Whether that is legal or allowed under Google’s terms, or lawful for your use case, depends on those terms and the law that applies to you. This page does not decide that question.

### Related actors

- [AI Chatbot App Update Tracker](https://apify.com/bovi/ai-chatbot-app-update-tracker) — tracks updates for the ChatGPT, Claude, and Gemini apps. This Actor returns `updated` and `whats_new` for a Google Play package you name.
- [AI Chatbot ASO Keyword Tracker](https://apify.com/bovi/ai-chatbot-aso-keyword-tracker) — tracks App Store keyword rankings. This Actor returns the Google Play listing side: title, category, rating distribution, and installs.

### Usage statistics

This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.

A copy of the exact record for your run is saved as `USAGE_STATS` in your own Apify key-value store.

To opt out, set `disableUsageStats` to `true` in the input. Nothing is sent then.

[Full list of collected fields](https://api.apify.com/v2/key-value-stores/v9rgHjMKLDGtHf8tD/records/index.html)

# Actor input Schema

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

Android package names (e.g. com.spotify.music, com.whatsapp). Find the package name in the Play Store URL: play.google.com/store/apps/details?id=com.spotify.music

## `searchTerms` (type: `array`):

Keyword queries to search the Play Store (returns matching app IDs, then scrapes each). Example: \["meditation", "task manager"]

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

Two-letter ISO country code for the Play Store storefront. Examples: US, GB, DE, FR, JP, CA, AU.

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

If enabled, fetches up to 20 user reviews per app embedded in the Play Store page. Each review is a separate output record.

## `lang` (type: `string`):

BCP-47 language code for the Play Store locale. Examples: en, de, fr, ja, pt. Affects description and review text language.

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

Apify Proxy settings. RESIDENTIAL group recommended for Google Play.

## Actor input object example

```json
{
  "appIds": [
    "com.spotify.music"
  ],
  "searchTerms": [],
  "country": "US",
  "includeReviews": true,
  "lang": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing Google Play Scraper records (title, developer, category, rating_avg, rating_count, installs, price_usd, updated, review_rating, review_author, review_date, parse_confidence).

# 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"
    ],
    "searchTerms": [],
    "country": "US",
    "includeReviews": true,
    "lang": "en",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/google-play-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"],
    "searchTerms": [],
    "country": "US",
    "includeReviews": True,
    "lang": "en",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/google-play-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"
  ],
  "searchTerms": [],
  "country": "US",
  "includeReviews": true,
  "lang": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/google-play-scraper --silent --output-dataset

```

## MCP server setup

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