---
title: "Google Play scraper"
description: "Scrape Google Play apps as JSON: title, developer, rating, installs, update date, data safety and reviews. One API request from Python, Node.js, CLI or MCP."
canonical: https://www.zenrows.com/scrape/google-play
updated: 2026-10-20
---

# Google Play scraper

The Zenrows Google Play scraper turns any Play Store app URL into structured JSON: app ID, title, developer, rating, review count, installs, category, last update, data safety, reviews and similar apps. You send the URL, Fetch in Adaptive Stealth Mode opens the page, and Extract returns the fields. Run it from an API call, the CLI or an AI agent.

- Site: play.google.com
- Returns: App details, ratings, installs, reviews and similar apps

## Run it: one Google Play app in, JSON out

```json Input
{
  "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "app": {
    "app_id": "com.spotify.music",
    "title": "Spotify: Music and Podcasts",
    "developer": "Spotify AB",
    "developer_url": "https://play.google.com/store/apps/developer?id=Spotify%20AB",
    "category": "Music & Audio",
    "content_rating": "Teen",
    "contains_ads": true,
    "in_app_purchases": true,
    "editors_choice": true,
    "chart_rank": "#1 top free music & audio",
    "updated_on": "Oct 14, 2026",
    "icon_url": "https://play-lh.googleusercontent.com/IzQgYCcnCFCD08GR-3bdtcT8xzOvrNkC84avGT5CwTX2VIqmTmKKJcP_Cd4JoBOdmCMlTndlOzV6hrthg2fOWA=w240-h480-rw"
  },
  "ratings": {
    "average_rating": 4.3,
    "review_count": "36.5M",
    "installs": "1B+"
  },
  "reviews": [
    {
      "author": "M. M.",
      "date": "September 18, 2026",
      "helpful_votes": 347,
      "body": "I don't know what you guys did in the last update, but now when I listen to any podcast, it plays the list opposite…",
      "developer_reply": {
        "author": "Spotify AB",
        "date": "September 18, 2026",
        "body": "Hi! For more information, visit support.spotify.com and search for \"Follow artists, podcasts, and shows.\"…"
      }
    }
  ],
  "similar_apps": [
    { "title": "YouTube Music", "developer": "Google LLC", "app_id": "com.google.android.apps.youtube.music", "rating": 4.5 }
  ]
}
```

Sample output for a Google Play app page, built from a live request on Oct 20, 2026, trimmed for length. A field is returned when the page shows it.

## What data can you scrape from Google Play?

An app's Play Store page holds the listing, the numbers that rank it, the developer's privacy declarations and a first page of reviews. The scraper returns them as separate groups under one record.

| Field | What it holds | Example |
|---|---|---|
| `app.app_id` | The package name, Google Play's unique ID for the app | `com.spotify.music` |
| `app.title` | The app name on the listing | `Spotify: Music and Podcasts` |
| `app.developer` | The publisher's account name | `Spotify AB` |
| `app.category` | The store category | `Music & Audio` |
| `app.content_rating` | The age rating shown on the listing | `Teen` |
| `app.contains_ads`, `app.in_app_purchases` | The monetization labels under the title | `true` |
| `app.editors_choice` | Whether the app carries the Editors' Choice badge | `true` |
| `app.chart_rank` | The chart position the listing shows | `#1 top free music & audio` |
| `app.updated_on` | Date of the last update | `Oct 14, 2026` |
| `app.description` | The full "About this app" text | `With the Spotify music and podcast app, you can play millions of songs…` |
| `ratings.average_rating` | Star rating out of 5 | `4.3` |
| `ratings.review_count` | Number of reviews, as Google Play rounds it | `36.5M` |
| `ratings.installs` | The install bracket | `1B+` |
| `data_safety` | What the developer declares it shares and collects, encryption in transit, deletion requests | `{ "shares": "Location, Personal info, and Device or other IDs", … }` |
| `reviews[]` | The reviews on the page: author, date, text, helpful votes and the developer's reply | `{ "helpful_votes": 261, … }` |
| `more_by_developer[]` | Other apps from the same developer, with ID and rating | `{ "title": "Spotify for Artists", "rating": 3.5 }` |
| `similar_apps[]` | Google's "Similar apps" list, with developer, ID and rating | `{ "title": "Duolingo: Learn Languages", "rating": 4.7 }` |

## How to scrape Google Play with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Build the app URL from the package name.** Every listing lives at `https://play.google.com/store/apps/details?id=` plus the app ID, such as `com.spotify.music`. Find the ID in the address bar of any Play Store page.
3. **Fix the language with `hl`** (`hl=en`, `hl=de`) and, for prices and availability by market, `gl` (`gl=US`) plus the matching request country.
4. **Send it with the default configuration**: Adaptive Stealth Mode to open the page and Extract to return the fields. Read `parsed` from the response.
5. **Run your app list in Batch**, one URL per app ID, with the ID as `external_id` so results join back to your own records.

```python Python
# pip install requests
import json
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en",
    "mode": "auto",      # Adaptive Stealth Mode
    "extract": "auto",   # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

data = response.json()["parsed"]
print(data["app"]["title"], data["ratings"]["average_rating"], data["ratings"]["installs"])
print(json.dumps(data["reviews"][:2], indent=2))
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
console.log(parsed.app.title, parsed.ratings.review_count, parsed.app.updated_on);
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.spotify.music%26hl%3Den&mode=auto&extract=auto"

# Only the listing numbers
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.spotify.music%26hl%3Den&mode=auto&extract=auto&extract_fields=app.title%2Cratings.average_rating%2Cratings.installs%2Capp.updated_on"
```

```python Python SDK
# pip install zenrows
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
for app_id in ["com.spotify.music", "com.duolingo"]:
    response = client.get(
        f"https://play.google.com/store/apps/details?id={app_id}&hl=en",
        params={"mode": "auto", "extract": "auto"},
    )
    parsed = response.json()["parsed"]
    print(app_id, parsed["ratings"]["average_rating"], parsed["app"]["updated_on"])
```

## Input

The scraper takes one Google Play URL per request. The app, language and market are in the URL; the options below control how Zenrows opens it. In a Batch job they apply to every task.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A Google Play app page: `https://play.google.com/store/apps/details?id=<package>`, with `hl` for language and `gl` for market |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when the page needs them |
| `extract` | string | `auto` | Returns the listing as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `app.title,ratings.average_rating,ratings.installs` |
| `proxy_country` | string | any | Two-letter country code. Use it with `gl` when prices, availability or chart ranks differ by market |
| `wait_for` | string | none | A CSS selector to wait for before the page is read |
| `session_id` | integer | none | Keep the same session across several requests, up to 10 minutes |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en", "external_id": "com.spotify.music" },
    { "url": "https://play.google.com/store/apps/details?id=com.duolingo&hl=en", "external_id": "com.duolingo" },
    { "url": "https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music&hl=en", "external_id": "com.google.android.apps.youtube.music" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the Play Store page as Google served it, and `parsed`, the structured record. The sample below is the full shape for one app, trimmed to one or two items per list.

```json App page
{
  "app": {
    "app_id": "com.spotify.music",
    "title": "Spotify: Music and Podcasts",
    "developer": "Spotify AB",
    "developer_url": "https://play.google.com/store/apps/developer?id=Spotify%20AB",
    "category": "Music & Audio",
    "content_rating": "Teen",
    "contains_ads": true,
    "in_app_purchases": true,
    "editors_choice": true,
    "chart_rank": "#1 top free music & audio",
    "updated_on": "Oct 14, 2026",
    "description": "With the Spotify music and podcast app, you can play millions of songs, albums and original podcasts for free. We have even added audiobooks…",
    "icon_url": "https://play-lh.googleusercontent.com/IzQgYCcnCFCD08GR-3bdtcT8xzOvrNkC84avGT5CwTX2VIqmTmKKJcP_Cd4JoBOdmCMlTndlOzV6hrthg2fOWA=w240-h480-rw",
    "screenshots": [
      "https://play-lh.googleusercontent.com/c1jnjL-9CIFlwlTMX3xNyeo8aEH39sNuC5zpTHhfW8keGxQE3TBMRX9Rm3VqM3E03Cyl9AqtnxuKvxJpcW0WCA=w526-h296-rw"
    ]
  },
  "ratings": {
    "average_rating": 4.3,
    "review_count": "36.5M",
    "installs": "1B+"
  },
  "data_safety": {
    "shares": "Location, Personal info, and Device or other IDs",
    "collects": "Location, Personal info and 7 others",
    "encrypted_in_transit": true,
    "deletion_request": true
  },
  "reviews": [
    {
      "author": "M. D.",
      "date": "September 15, 2026",
      "helpful_votes": 261,
      "body": "Spotify has a new, horrendous feature where the ending to the song that you are listening to gets cut off by the middle of the next song…"
    },
    {
      "author": "M. M.",
      "date": "September 18, 2026",
      "helpful_votes": 347,
      "body": "I don't know what you guys did in the last update, but now when I listen to any podcast, it plays the list opposite…",
      "developer_reply": {
        "author": "Spotify AB",
        "date": "September 18, 2026",
        "body": "Hi! For more information, visit support.spotify.com and search for \"Follow artists, podcasts, and shows.\"…"
      }
    }
  ],
  "more_by_developer": [
    { "title": "Spotify for Artists", "developer": "Spotify AB", "app_id": "com.spotify.s4a", "rating": 3.5 },
    { "title": "Spotify Kids", "developer": "Spotify AB", "app_id": "com.spotify.kids", "rating": 2.7 }
  ],
  "similar_apps": [
    { "title": "YouTube Music", "developer": "Google LLC", "app_id": "com.google.android.apps.youtube.music", "rating": 4.5 },
    { "title": "Duolingo: Learn Languages", "developer": "Duolingo", "app_id": "com.duolingo", "rating": 4.7 }
  ]
}
```

Counts such as `review_count` and `installs` come back as Google Play prints them (`36.5M`, `1B+`), because the store rounds them on the page. Convert them to numbers in your pipeline if you chart them. Need a spreadsheet? Load `parsed` into pandas with `pd.json_normalize(...)` and write CSV. Need the page for an LLM? Ask for Markdown instead of JSON.

## Scrape Google Play from your coding agent

Claude Code, Cursor, Codex and any MCP client can look up Play Store apps and compare them from a prompt.

The agent sends the same Fetch and Extract request a developer would, so it reads the rating, installs, update date and reviews as JSON. Connect the Zenrows MCP server once, or install the CLI and let the agent call it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en"
```

```text Then ask your agent
Use Zenrows to get the Google Play listings for com.spotify.music and
com.google.android.apps.youtube.music. Compare rating, review count,
installs and last update date in a table, then summarize the complaints
in the reviews on each page.
```

## Scrape Google Play at scale with Batch and Crawl

**Batch** runs your list of app IDs as one job, with each package name as its `external_id`. App market teams run it weekly across their own apps and every competitor's to track rating, review count, installs and update cadence side by side.

**Crawl** finds app IDs you do not have yet. Start it on a developer page or on any app page and keep links that contain `/store/apps/details?id=`: it follows the "More by" and "Similar apps" lists and returns every listing it reaches. Send those URLs to Batch with Extract.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en", "external_id": "com.spotify.music" },
      { "url": "https://play.google.com/store/apps/details?id=com.duolingo&hl=en", "external_id": "com.duolingo" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# apps.jsonl: one {"url": "https://play.google.com/store/apps/details?id=...", "external_id": "...", "extract": "auto"} per line
zenrows batch create apps.jsonl --wait
zenrows batch results <job-id> --out google-play-apps.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://play.google.com/store/apps/developer?id=Spotify%20AB",
    "depth": 2,
    "max_pages": 200,
    "include_patterns": ["/store/apps/details?id="]
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://play.google.com/store/apps/details?id=com.spotify.music&hl=en",
          "external_id": "google-play"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with Google Play data

| Use case | Data they pull | Who runs it |
|---|---|---|
| App store optimization | Title, description, category, rating and chart rank for your app and its rivals | ASO and growth teams |
| Competitor tracking | Install bracket, review count, update date and Editors' Choice badge across a category | Product managers and mobile strategy teams |
| Review analysis | Review text, helpful votes and developer replies, fed to a sentiment or topic model | Product, CX and support teams |
| Market research | Developers, categories, monetization labels and ratings across many listings | Analysts, investors and app studios |
| Privacy and compliance audits | Data safety declarations: what an app shares, collects and lets users delete | Privacy, security and compliance teams |
| App catalogs for agents and RAG | The full listing as JSON or the page as Markdown | AI and data teams |

## Tips for scraping Google Play

- **Key everything on the package name.** The `id` in the URL never changes for an app, even when the title does. Use it as `external_id` and as your database key.
- **Pin the language.** Without `hl`, Google Play picks a language from the request, and the description, category name and dates change with it. `hl=en` keeps every run comparable.
- **Use `gl` and the request country for market data.** Paid app prices, availability and chart ranks depend on the store country. Set both to the market you report on.
- **Expect rounded counts.** Review counts read like `36.5M` and installs like `1B+`. Store the string as shown and a parsed number next to it.
- **Grow your list from the page itself.** `more_by_developer` and `similar_apps` carry app IDs, so each run can add new competitors to the next one.
- **Watch `updated_on` for release cadence.** Comparing the date run over run tells you how often each competitor ships.

## Frequently asked questions

### Is it legal to scrape Google Play?

Collecting public listing data from Google Play, such as app names, ratings, install brackets and descriptions shown to every visitor, is common practice for app market research. Reviews carry reviewers' names, and personal data falls under laws such as the GDPR and the CCPA, so keep only what you have a legitimate reason to use. Check Google Play's terms for your use case and ask your lawyer if you are unsure.

### Is there an official Google Play API?

The Google Play Developer API covers apps you publish: your own listings, in-app products and the reviews on your own apps. It does not return other developers' listings, ratings or installs, so teams that track competitors or a whole category scrape the public store pages.

### What Google Play pages can I scrape?

App detail pages ( /store/apps/details?id=… ) are the core: listing, ratings, installs, data safety, reviews and related apps. Developer pages ( /store/apps/developer?id=… ) list every app from one publisher and are a good start for a Crawl.

### Can I scrape Google Play reviews?

Yes. The app page returns its reviews with author, date, text, helpful votes and the developer's reply when there is one, plus the overall rating and review count. Run the app URLs in Batch to collect reviews across many apps, and repeat the run to catch new ones.

### How do I scrape Google Play with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the app URL, Adaptive Stealth Mode and Extract, as in the Python example above. parsed["app"] , parsed["ratings"] and parsed["reviews"] hold the record as Python objects. The zenrows package on PyPI wraps the same request.

### How many apps can I scrape?

Send one app URL per request, or put the whole list in a Batch job that runs them in parallel with the package name on each result. One Batch job accepts more than 10,000 URLs, sent inline or as a CSV file.

### Can AI agents scrape Google Play with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Name the apps you want compared and the agent calls Fetch and Extract, then works from the listings.

### Can I scrape Google Play on a schedule?

Yes. Create a scheduled Batch job with your Google Play URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the Google Play scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. A weekly workflow can refresh competitor ratings in Google Sheets or a database. See the integrations page for the full list.

### What format does the data come in?

JSON by default, with the structured listing in parsed and the original page in html . You can also ask for the page as Markdown or plain text, which keeps the description and reviews readable for an LLM.

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
