# Google Play Store Scraper (`parsebird/google-play-scraper`) Actor

Scrape Google Play Store apps by URL, app ID, keyword or developer: ratings, installs, prices, versions, developer contacts, screenshots and categories, plus optional reviews as nested lists or flat records.

- **URL**: https://apify.com/parsebird/google-play-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 1,000 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

**Google Play Store Scraper** extracts app data and reviews from the [Google Play Store](https://play.google.com/store/apps) by app URL, app ID, search keyword, or developer. You get ratings, rating histograms, install counts, prices, versions, release notes, developer emails and addresses, categories, screenshots, and reviews as clean JSON, CSV, or Excel.

<table><tr>
<td style="border-left:4px solid #01875F;padding:12px 16px;font-weight:600">
Mix app, search, and developer URLs with a keyword in one run, in the store country and language you choose, and get 50+ fields per app, full developer portfolios, and reviews 150 per page, nested under each app or as one record per review.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
Apify Actor: parsebird/google-play-scraper. Scrapes the Google Play Store (play.google.com): app details, ratings, installs, prices, versions, developer contacts, categories, screenshots, and reviews. Call via ApifyClient: client.actor("parsebird/google-play-scraper").call(run_input={"startUrls": ["https://play.google.com/store/apps/details?id=com.instagram.android"], "search": "habit tracker", "country": "US", "lang": "en", "price": "free", "includeReviews": true, "reviewsSort": "NEWEST", "maxReviewPages": 2, "maxItems": 50}). Inputs: startUrls (array: app URLs like https://play.google.com/store/apps/details?id=com.instagram.android, search URLs like https://play.google.com/store/search?q=workout&c=apps, developer URLs like https://play.google.com/store/apps/developer?id=Supercell or /store/apps/dev?id=5700313618786177705, bare app IDs like com.instagram.android, numeric developer IDs; hl/gl URL params override lang/country per entry; category and top-chart URLs are not supported), search (string keyword, about 30 apps per search), country (two-letter code, default US), lang (default en), price (all, free, paid; search only), includeReviews (boolean, nests reviews under each app in reviewsList), onlyIncludeReviews (boolean, one dataset record per review, no app record), reviewsSort (NEWEST, RATING, HELPFULNESS), maxReviewPages (integer, 150 reviews per page; empty = all), maxItems (integer cap on records; nested reviews don't count, flat reviews do), customMapFunction (JavaScript function string to reshape records), outputConnector/deliverTarget/deliverMode/deliverMaxItems (optional delivery to Notion, Todoist and other apps via Apify MCP connectors). Output per app: inputSource (queryIndex, mode, appId, searchQuery, developerId, filters, paginationToken), title, appId, url, summary, description, installs, minInstalls, realInstalls, score, scoreText, ratings, reviews (review count), histogram, free, price, priceText, currency, offersIAP, inAppProductPrice, containsAds, developer, developerId, developerUrl, developerEmail, developerWebsite, developerAddress, developerLegalName, developerLegalEmail, developerLegalAddress, developerLegalPhone, privacyPolicy, genre, genreId, categories, contentRating, icon, headerImage, screenshots, video, released, updated (ms timestamp), lastUpdatedOn, version, androidVersion, recentChanges, country, lang, scrapedAt, reviewsList. Review fields: id, userName, userImage, score, text, date, thumbsUp, appVersion, replyText, replyDate, appId, appCountry, appLanguage. Pricing: pay per event (record saved, app detail, search, developer request, review page after the first). Full API spec: https://apify.com/parsebird/google-play-scraper/api. Get your token: https://console.apify.com/settings/integrations.
```

### What is Google Play Store Scraper?

**Google Play Store Scraper** turns the Google Play Store into a dataset. Paste app links or app IDs, add a search keyword, or point it at a developer, and it returns the full app page data for every app it finds. It's an easy **Google Play API alternative**: you don't need a Google account, a developer account, an API key, or any code.

Use it to monitor competitors, track ratings and releases, research app store optimization (ASO) keywords, build lead lists of app developers, or analyze Google Play reviews.

### What can Google Play Store Scraper do?

- 🔗 **Any Google Play entry point.** App detail URLs, search URLs, developer URLs (`?id=Supercell`), numeric developer pages (`/dev?id=…`), bare app IDs like `com.instagram.android`, and a separate **search keyword**, all in one run.
- 📱 **Full app records everywhere.** Apps found through search or a developer page get the same full record as a direct app lookup, not a short summary.
- 🏢 **Complete developer portfolios.** Developer pages by name return every app the developer lists. In our October 2026 tests, Google LLC returned 90 apps and Microsoft Corporation 72.
- 💬 **Google Play reviews.** Fetch reviews 150 per page, sorted by newest, rating, or helpfulness, with developer replies. Nest them under each app, or save one record per review for apps with huge review counts.
- 📇 **Developer contact data.** Support email, website, address, privacy policy, and the legal name, email, address, and phone number Google Play publishes for the developer.
- 🌍 **Countries and languages.** Set the store `country` and `lang` for the run, or override them per URL with `gl` and `hl` to mix regions in one run.
- 🧩 **Custom output.** Reshape records with your own JavaScript function, or send results to Notion, Todoist, and other apps through [Apify MCP connectors](https://docs.apify.com/platform/integrations/mcp).
- 📅 **Scheduling, API, and integrations.** Run on a timer with [Apify Schedules](https://docs.apify.com/platform/schedules), call it from the [Apify API](https://docs.apify.com/api/v2), and connect Google Sheets, Zapier, Make, Slack, or webhooks with [Apify integrations](https://docs.apify.com/platform/integrations).

### What data can you extract from Google Play?

| Field | Description |
|-------|-------------|
| `title` / `appId` / `url` | App name, package name, and Google Play link |
| `summary` / `description` | Short description and full description as plain text |
| `installs` / `minInstalls` / `realInstalls` | Install badge (like `5,000,000,000+`), its lower bound, and Google Play's unrounded install count |
| `score` / `scoreText` / `ratings` / `reviews` | Average rating, rounded rating, number of ratings, and number of reviews |
| `histogram` | Number of 1- to 5-star ratings |
| `free` / `price` / `priceText` / `currency` | Price in the store's currency |
| `offersIAP` / `inAppProductPrice` / `containsAds` | In-app purchases, their price range, and ads |
| `developer` / `developerId` / `developerUrl` | Developer name, ID, and Google Play developer page |
| `developerEmail` / `developerWebsite` / `developerAddress` / `privacyPolicy` | Developer contact details and privacy policy |
| `developerLegalName` / `developerLegalEmail` / `developerLegalAddress` / `developerLegalPhone` | The developer's legal business details, when Google Play shows them |
| `genre` / `genreId` / `categories` | Primary category and all categories |
| `contentRating` / `contentRatingDescription` | Content rating (like `Teen`) and its reasons |
| `version` / `androidVersion` / `recentChanges` | Current version, minimum Android version, and "What's new" text |
| `released` / `updated` / `lastUpdatedOn` | Release date, last update as a millisecond timestamp, and as text |
| `icon` / `headerImage` / `screenshots` / `video` / `videoImage` | Image and video URLs |
| `inputSource` | Which input produced the record: `queryIndex`, `mode` (`detail`, `search`, `developer`, `review`, `unsupported`, `invalid`), the app ID, search keyword or developer ID, the `filters` used, and the review `paginationToken` |
| `reviewsList` | Reviews when **Include reviews** is on: `id`, `userName`, `userImage`, `score`, `text`, `date`, `thumbsUp`, `appVersion`, `replyText`, `replyDate`, `appId`, `appCountry`, `appLanguage` |

`reviews` is always the app's review count. The review texts are in `reviewsList`.

### How to scrape Google Play

1. Open [Google Play Store Scraper](https://apify.com/parsebird/google-play-scraper) on Apify Store and click **Try for free**.
2. Add **Google Play URLs or IDs**: app, search, or developer links, or app IDs like `com.instagram.android`. You can also enter a **Search keyword**.
3. Set the **Country** and **Language**, and a **Price filter** for searches if you need one.
4. Turn on **Include reviews** or **Only output reviews**, pick a **Review sort order**, and set **Max review pages per app**.
5. Set **Max records** to control the run size.
6. Click **Start** and wait for the run to finish.
7. Download the data as JSON, CSV, Excel, XML, or HTML from the **Output** tab, or read it with the API.

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

Google Play Store Scraper uses **pay-per-event** pricing, so you pay only for what the run does. Compute and proxy costs are included in the event prices.

| Event | When it's charged | Free | Bronze | Silver | Gold |
|-------|-------------------|------|--------|--------|------|
| `data-item` | Each record saved: an app, or a review with **Only output reviews** | $0.10 / 1,000 | $0.10 / 1,000 | $0.10 / 1,000 | $0.10 / 1,000 |
| `app-detail` | Each app page read for a full app record | $0.90 / 1,000 | $0.90 / 1,000 | $0.90 / 1,000 | $0.90 / 1,000 |
| `search-query` | Each search, from a keyword or a search URL (one search returns about 30 apps) | $2.99 / 1,000 | $2.79 / 1,000 | $2.59 / 1,000 | $2.39 / 1,000 |
| `developer-query` | Each request for a developer's app list | $2.99 / 1,000 | $2.79 / 1,000 | $2.59 / 1,000 | $2.39 / 1,000 |
| `review-query` | Each page of up to 150 reviews, **from the second page of each app**. The first page is free | $13.99 / 1,000 | $12.99 / 1,000 | $11.99 / 1,000 | $10.99 / 1,000 |

Examples on the Free plan:

- **One app:** $0.0009 + $0.0001 = **$0.001**
- **A keyword search with 30 apps:** $0.00299 + 30 × $0.001 ≈ **$0.033**
- **Google LLC's 90 apps** (2 developer requests): 2 × $0.00299 + 90 × $0.001 ≈ **$0.096**
- **One app with 1,500 nested reviews** (10 pages, the first free): $0.001 + 9 × $0.01399 ≈ **$0.13**
- **15,000 reviews as separate records** (100 pages): 99 × $0.01399 + 15,000 × $0.0001 ≈ **$2.89**

Unsupported entries, like category URLs, are saved as error records for free. You can set a maximum cost per run in Apify Console. The Actor stops before it goes over and keeps everything collected so far.

### Input

You need at least one entry in `startUrls` or a `search` keyword. If you give both, both are scraped. See the [Input tab](https://apify.com/parsebird/google-play-scraper/input-schema) for every option.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `startUrls` | array | No\* | — | App, search, and developer URLs, bare app IDs, and numeric developer IDs |
| `search` | string | No\* | — | A search keyword. Runs as its own query |
| `country` | string | No | `US` | Two-letter store country. A `gl` parameter on a URL overrides it for that entry |
| `lang` | string | No | `en` | Language of the results. An `hl` parameter on a URL overrides it for that entry |
| `price` | string | No | `all` | `all`, `free`, or `paid`. Applies to searches only |
| `includeReviews` | boolean | No | `false` | Attach reviews to every app in `reviewsList` |
| `onlyIncludeReviews` | boolean | No | `false` | Save reviews as separate records, without the app record. Implies `includeReviews` |
| `reviewsSort` | string | No | `NEWEST` | `NEWEST`, `RATING`, or `HELPFULNESS` |
| `maxReviewPages` | integer | No | — | Review pages per app, up to 150 reviews each. Empty fetches every page |
| `maxItems` | integer | No | — | Cap on records across all queries. Empty collects everything |
| `customMapFunction` | string | No | — | JavaScript function that reshapes each record before it's saved |
| `outputConnector` | string | No | — | MCP connector (Notion, Todoist, …) to send results to |
| `deliverTarget` | string | No | — | Where the connector writes, like a Notion page URL |
| `deliverMode` | string | No | `perPost` | `perPost` (one record per item) or `summary` (one roll-up per run) |
| `deliverMaxItems` | integer | No | — | Cap on records delivered in `perPost` mode |

\* Add at least one entry to `startUrls` or a `search` keyword.

#### Which URLs does Google Play Store Scraper accept?

```
https://play.google.com/store/apps/details?id=com.instagram.android
https://play.google.com/store/search?q=workout&c=apps
https://play.google.com/store/apps/developer?id=Supercell
https://play.google.com/store/apps/dev?id=5700313618786177705
com.instagram.android
5700313618786177705
```

Entries that resolve to the same query in the same region are scraped once. A bare number is read as a developer ID. To pass a developer name, use a developer URL.

**Use the developer name for big portfolios.** Google Play doesn't paginate the numeric developer page, so `dev?id=5700313618786177705` returns only the developer's first 10 or so apps. The same developer by name, `developer?id=Google+LLC`, returns the full list.

**Category and top-chart pages aren't supported.** URLs like `/store/apps/category/GAME_ACTION`, `/store/apps/top`, or `/store/apps/collection/…` are saved as free error records so you can see which input wasn't used. To cover a category, search for a keyword that describes it:

```json
{
    "inputSource": {
        "queryIndex": 0,
        "mode": "unsupported",
        "filters": { "country": "US", "lang": "en" },
        "paginationToken": null
    },
    "error": true,
    "code": "UNSUPPORTED_URL",
    "entry": "https://play.google.com/store/apps/category/GAME_ACTION",
    "message": "Google Play category and top-chart URLs are not supported. Use a search URL, a search keyword, an app detail URL or a developer URL instead."
}
```

Entries that aren't Google Play links or IDs get the code `INVALID_ENTRY`.

#### How do you scrape a single Google Play app?

```json
{
    "startUrls": ["https://play.google.com/store/apps/details?id=com.instagram.android"]
}
```

#### How do you search Google Play apps by keyword?

```json
{
    "search": "habit tracker",
    "country": "US",
    "lang": "en",
    "price": "free",
    "maxItems": 100
}
```

#### How do you scrape a developer's apps?

```json
{
    "startUrls": ["https://play.google.com/store/apps/developer?id=Supercell"]
}
```

#### How do you scrape Google Play reviews?

Turn on `includeReviews` to nest reviews under each app, and set `maxReviewPages` whenever a search or developer finds many apps. Otherwise every app pages through all of its reviews.

```json
{
    "startUrls": [
        "https://play.google.com/store/apps/details?id=com.instagram.android",
        "https://play.google.com/store/search?q=workout&c=apps",
        "https://play.google.com/store/apps/developer?id=Supercell"
    ],
    "search": "habit tracker",
    "country": "US",
    "lang": "en",
    "price": "free",
    "includeReviews": true,
    "reviewsSort": "NEWEST",
    "maxReviewPages": 2,
    "maxItems": 50
}
```

An app and its nested reviews are one dataset record, and a record can hold at most 9 MB. That is roughly 15,000 reviews, depending on their length. When an app reaches that size, `reviewsList` stops and the log shows a warning. For apps with more reviews, use `onlyIncludeReviews`: each review is its own record, so there's no ceiling, and `maxItems` caps the number of reviews.

```json
{
    "startUrls": ["com.instagram.android"],
    "onlyIncludeReviews": true,
    "reviewsSort": "NEWEST",
    "maxItems": 5000
}
```

#### How do you reshape records with a custom map function?

`customMapFunction` receives each record and returns what you want stored instead. With `includeReviews`, it gets the app before `reviewsList` is attached, so reviews pass through untouched. If the function throws, the original record is saved and the log shows a warning.

```javascript
(object) => {
    return {
        appId: object.appId,
        title: object.title,
        score: object.score,
        installs: object.installs,
    };
}
```

#### How do you send Google Play results to Notion, Todoist, and more?

1. Authorize a connector once in Apify Console → **Settings → API & Integrations → MCP connectors**. Any service whose MCP server offers non-destructive write tools works.
2. Pick it in **Send results to Notion, Todoist, …**.
3. Set **Destination target**. For Notion, paste a page URL and the Actor creates a typed database there, or paste an existing database URL to fill the columns it already has. Share the page with your connector first through Notion's **••• → Connections** menu. For Todoist, paste a project URL or ID.
4. Pick **Write mode**: `perPost` writes one record per app or review, and `summary` writes one roll-up for the run.

Lists like `screenshots` become comma-joined text, and long fields such as descriptions and reviews go into each row's page body. The connector only uses non-destructive write tools, so it can't delete or overwrite your data. Delivery runs after scraping and is best-effort: if it fails, the run still finishes with all results in the dataset, and the log explains why.

### Output example

One app with `includeReviews` on. Lists are shortened here.

```json
{
    "inputSource": {
        "queryIndex": 0,
        "mode": "detail",
        "appId": "com.instagram.android",
        "filters": { "country": "US", "lang": "en", "reviewsSort": "NEWEST" },
        "paginationToken": null
    },
    "title": "Instagram",
    "appId": "com.instagram.android",
    "url": "https://play.google.com/store/apps/details?id=com.instagram.android",
    "summary": "Create & share photos, stories, & reels with friends you love",
    "description": "Little moments lead to big friendships. Share yours on Instagram. \n—From Meta\n\nConnect with friends, find other fans, and see what people around you are up to ...",
    "installs": "5,000,000,000+",
    "minInstalls": 5000000000,
    "realInstalls": 7795853010,
    "score": 3.9899771,
    "scoreText": "4.0",
    "ratings": 169611066,
    "reviews": 4548350,
    "histogram": { "1": 31883535, "2": 5358410, "3": 7087192, "4": 13527282, "5": 111754621 },
    "free": true,
    "price": 0.0,
    "priceText": "Free",
    "currency": "USD",
    "offersIAP": true,
    "inAppProductPrice": "$0.19 - $10,000.00 per item",
    "containsAds": true,
    "developer": "Instagram",
    "developerId": "Instagram",
    "developerUrl": "https://play.google.com/store/apps/developer?id=Instagram",
    "developerEmail": "instagram-android@meta.com",
    "developerWebsite": "http://help.instagram.com/",
    "developerAddress": null,
    "developerLegalName": "Meta Platforms, Inc.",
    "developerLegalEmail": "instagram-android@meta.com",
    "developerLegalAddress": "1 Meta Way\nMenlo Park, CA 94025-1444\nUnited States",
    "developerLegalPhone": "+1 650-853-1300",
    "privacyPolicy": "http://instagram.com/legal/privacy/",
    "genre": "Social",
    "genreId": "SOCIAL",
    "categories": [{ "name": "Social", "id": "SOCIAL" }],
    "contentRating": "Teen",
    "contentRatingDescription": null,
    "icon": "https://play-lh.googleusercontent.com/yHi59jmO_lVamcyJ1i3rM1_E8bAiAspShnGjjURq05ipQQSUksO3QVEsXTegRSqul038-4YNA7O644XAcx251Q",
    "headerImage": "https://play-lh.googleusercontent.com/YY6TNgNW4DfgqQ2VKuyHxGnDjXwYolSD9G83ZQK999LKAhB3mdQUQbGu3JEELWH57dkYYYNlvnMIZN36pYASLQM",
    "screenshots": ["https://play-lh.googleusercontent.com/KWZZ4eVExx8xdzsZrw5O5Lmyz8amgpAyzm9R_Fs5StBLQrxpoO7hZsrbXU170fuP9dXOagS9vNflXbit6Aro"],
    "video": "https://play.google.com/video/lava/web/player/yt:movie:nJevVI30wjU?autoplay=1&embed=play",
    "videoImage": "https://play-lh.googleusercontent.com/YY6TNgNW4DfgqQ2VKuyHxGnDjXwYolSD9G83ZQK999LKAhB3mdQUQbGu3JEELWH57dkYYYNlvnMIZN36pYASLQM",
    "released": "Apr 3, 2012",
    "updated": 1791205105000,
    "lastUpdatedOn": "Oct 5, 2026",
    "version": "Varies with device",
    "androidVersion": "Varies with device",
    "recentChanges": null,
    "country": "US",
    "lang": "en",
    "scrapedAt": "2026-10-10T11:46:47Z",
    "reviewsList": [
        {
            "id": "9f2d0f14-a7d5-48b5-8ec3-c76472636beb",
            "userName": "parasra nishar",
            "userImage": "https://play-lh.googleusercontent.com/a/ACg8ocKp3A0ZHLx9GtLW0pKb8poQcGuRupElAFYz1tXpRznR9ODOjxk=mo",
            "score": 5,
            "text": "i happy for this platform",
            "date": "2026-10-09T11:46:35Z",
            "thumbsUp": 0,
            "appVersion": "287.0.0.25.77",
            "replyText": null,
            "replyDate": null,
            "appId": "com.instagram.android",
            "appCountry": "US",
            "appLanguage": "en"
        }
    ]
}
```

With `onlyIncludeReviews`, each review is saved as its own record with an `inputSource` whose `mode` is `review` and whose `paginationToken` is the token that fetched its page (`null` on the first page).

### Use the Google Play Store Scraper API

Call the Actor from your own code with the [Apify API client](https://docs.apify.com/api/client/python). Find your token in [Apify Console → Settings → Integrations](https://console.apify.com/settings/integrations).

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("parsebird/google-play-scraper").call(run_input={
    "search": "budget planner",
    "country": "US",
    "lang": "en",
    "maxItems": 30,
})

for app in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(app["title"], app["score"], app["installs"], app["developerEmail"])
```

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('parsebird/google-play-scraper').call({
    startUrls: ['com.spotify.music'],
    onlyIncludeReviews: true,
    reviewsSort: 'NEWEST',
    maxItems: 1000,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((review) => console.log(review.score, review.date, review.text));
```

You can also start runs over plain HTTP from the [API tab](https://apify.com/parsebird/google-play-scraper/api), or connect the Actor to AI agents through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

### Use cases

- **App store optimization (ASO).** See which apps Google Play shows for your keywords in each country, with their ratings and installs.
- **Competitor monitoring.** Schedule runs to track competitors' versions, "What's new" notes, prices, ratings, and installs.
- **Review analysis.** Collect the newest or most helpful reviews to find bugs, feature requests, and sentiment trends.
- **Lead generation.** Build lists of app developers with their emails, websites, addresses, and phone numbers.
- **Market research.** Map a niche through keyword searches: who publishes, how apps are priced, and how many installs they have.
- **App databases.** Enrich a catalog with icons, screenshots, categories, and content ratings.

### How it works

1. Each entry in `startUrls`, plus the `search` keyword, becomes its own query with its own country and language.
2. Searches and developer pages return app IDs. The Actor then reads every app's public Google Play page for the full record.
3. With reviews on, it pages through each app's public reviews, 150 at a time, in the sort order you chose.
4. Records are saved in the order they were found, and the run stops at `maxItems`, `maxReviewPages`, or your maximum cost.

### FAQ

**Do I need a Google account or an API key?**
No. The Actor reads public Google Play pages that anyone can open without signing in.

**How many apps does a search return?**
Google Play shows about 30 apps per search and doesn't offer more pages. When the keyword matches one app exactly, Google Play also shows rows of related apps, which are included. In our October 2026 tests, "habit tracker" returned 30 apps, "minecraft" 38, and "instagram" 23.

**Why does a numeric developer ID return only about 10 apps?**
Google Play doesn't paginate the numeric developer page (`/store/apps/dev?id=…`). Use the developer's name URL (`/store/apps/developer?id=Google+LLC`) to get the whole portfolio.

**How many reviews can I get?**
As many as Google Play serves for the app and store. Nested under an app, the 9 MB record limit stops at roughly 15,000 reviews. With `onlyIncludeReviews` there's no ceiling. In our test on Apify, 15,000 Instagram reviews as separate records took about 90 seconds.

**Why does the same app show different data in different countries?**
Prices, availability, ratings, and reviews depend on the store country, and texts depend on the language. Use `gl` and `hl` on a URL, or `country` and `lang`, to choose them.

**How long does a run take?**
In our October 2026 tests on Apify, 31 apps took about 6 to 9 seconds, 192 apps from two developer portfolios and a search took about 35 seconds, and one app with about 15,000 nested reviews took about 45 seconds.

**Why was an app not found?**
The app isn't available in the selected country, the ID is wrong, or the app was removed. The log names it, and you aren't charged for it.

**Can I schedule runs or export to Google Sheets?**
Yes. Use [Apify Schedules](https://docs.apify.com/platform/schedules) for recurring runs and [integrations](https://docs.apify.com/platform/integrations) for Google Sheets, Zapier, Make, Slack, and webhooks.

**Something is missing or broken?**
Open an issue on the [Issues tab](https://apify.com/parsebird/google-play-scraper/issues). Feedback and feature requests are welcome there too.

### Is it legal to scrape Google Play?

The Actor collects only public information that Google Play shows to every visitor, like app pages and published reviews. It doesn't sign in or access any account data. Reviews include public usernames and profile images, and developer records can include contact details, which can be personal data, so handle them in line with laws such as the GDPR. You are responsible for how you use the data. Follow [Google Play's Terms of Service](https://play.google.com/about/play-terms/) and copyright rules when you republish descriptions or images. Read more in Apify's blog post [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

### Other scrapers you might like

| Actor | What it does |
|-------|--------------|
| [Apple App Store Scraper](https://apify.com/parsebird/app-store-scraper) | Scrape Apple App Store apps, rankings, reviews, and similar apps |
| [Apple Podcasts Scraper](https://apify.com/parsebird/apple-podcasts-scraper) | Scrape Apple Podcasts episodes, show notes, audio URLs, and transcripts |
| [Product Hunt Scraper](https://apify.com/parsebird/product-hunt-scraper) | Collect Product Hunt launches, upvotes, makers, and reviews |
| [Similarweb Scraper](https://apify.com/parsebird/similarweb-scraper) | Get website traffic, rankings, and audience data |
| [Trustpilot Reviews Scraper](https://apify.com/parsebird/trustpilot-reviews-scraper) | Collect company reviews and ratings from Trustpilot |

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/google-play-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Add app pages (<code>play.google.com/store/apps/details?id=com.instagram.android</code>), search pages (<code>play.google.com/store/search?q=workout\&c=apps</code>), developer pages (<code>play.google.com/store/apps/developer?id=Supercell</code>), bare app IDs (<code>com.instagram.android</code>) or numeric developer IDs. <code>hl</code> and <code>gl</code> in a URL override the language and country for that entry. Category and top-chart pages aren't supported.

## `search` (type: `string`):

Enter a keyword to search Google Play apps, e.g. <code>habit tracker</code>. Runs as its own query next to any URLs. Google Play shows about 30 apps per search.

## `price` (type: `string`):

Only return free or paid apps in search results.

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

Two-letter country code of the Google Play store, e.g. <code>US</code>, <code>GB</code>, <code>DE</code>. Sets prices, availability and reviews. A <code>gl</code> parameter on a URL overrides it for that entry.

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

Language of app texts, e.g. <code>en</code>, <code>de</code>, <code>pt-BR</code>. An <code>hl</code> parameter on a URL overrides it for that entry.

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

Attach reviews to every app in a <code>reviewsList</code> array. Set <b>Max review pages per app</b> too, or every app pages through all of its reviews.

## `onlyIncludeReviews` (type: `boolean`):

Save each review as its own dataset record and skip the app record. Implies <b>Include reviews</b>. Use it for apps with more than about 20,000 reviews.

## `reviewsSort` (type: `string`):

Order of the reviews.

## `maxReviewPages` (type: `integer`):

Review pages to fetch per app, up to 150 reviews each. Leave empty to fetch every page.

## `maxItems` (type: `integer`):

Maximum number of records saved across all queries. Nested reviews belong to their app's record and don't count; with <b>Only output reviews</b>, each review counts. Leave empty for no limit.

## `customMapFunction` (type: `string`):

Optional JavaScript function that reshapes each record before it is saved, e.g. <code>(object) => ({ appId: object.appId, title: object.title, score: object.score })</code>. With <b>Include reviews</b> it receives the app before <code>reviewsList</code> is attached. If it throws, the original record is saved.

## `outputConnector` (type: `string`):

Optional MCP connector to deliver the results to. Authorize it first in Apify Console → Settings → API & Integrations → MCP connectors.

## `deliverTarget` (type: `string`):

URL or ID of where the connector writes. Notion: a page URL (a typed database is created for you) or an existing database URL. Todoist: a project URL or ID. Some services need none.

## `deliverMode` (type: `string`):

perPost writes one record per app or review; summary writes a single roll-up for the run.

## `deliverMaxItems` (type: `integer`):

Optional cap on how many records perPost delivers (ignored in summary mode).

## Actor input object example

```json
{
  "startUrls": [
    "https://play.google.com/store/apps/details?id=com.instagram.android"
  ],
  "search": "habit tracker",
  "price": "all",
  "country": "US",
  "lang": "en",
  "includeReviews": false,
  "onlyIncludeReviews": false,
  "reviewsSort": "NEWEST",
  "maxItems": 1000,
  "deliverMode": "perPost"
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrls": [
        "https://play.google.com/store/apps/details?id=com.instagram.android"
    ],
    "search": "habit tracker",
    "country": "US",
    "lang": "en",
    "maxItems": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/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 = {
    "startUrls": ["https://play.google.com/store/apps/details?id=com.instagram.android"],
    "search": "habit tracker",
    "country": "US",
    "lang": "en",
    "maxItems": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/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 '{
  "startUrls": [
    "https://play.google.com/store/apps/details?id=com.instagram.android"
  ],
  "search": "habit tracker",
  "country": "US",
  "lang": "en",
  "maxItems": 1000
}' |
apify call parsebird/google-play-scraper --silent --output-dataset

```

## MCP server setup

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