# App Store & Google Play Scraper: Apps, Ratings, Charts (`folt/app-store-scraper`) Actor

Public app data from the Apple App Store and Google Play in one clean schema: title, developer company, price, ratings and histogram, installs, version, release notes, Google Play reviews and Apple top charts. For app-market research and competitor tracking.

- **URL**: https://apify.com/folt/app-store-scraper.md
- **Developed by:** [Folt Labs](https://apify.com/folt) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 apps

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## App Store & Google Play Scraper — Apps, Ratings, Reviews & Top Charts

Get **public app data from the Apple App Store and Google Play in one clean schema**: title, developer company, category, price and currency, rating average and count, rating histogram, installs, version, size, release notes, description, icon and screenshots — per country. Add **Google Play reviews** (with developer replies) and **Apple top charts** (top free / top paid) in the same run.

Built for **app-market research, competitor tracking and product/marketing analytics**: compare your app with competitors across countries, watch prices, ratings and release cadence, or track who climbs the charts.

### Why use it

- 🍏🤖 **Both stores, one schema** — the same fields for App Store and Google Play apps, so you can put them side by side in one sheet
- 🌍 **Per country** — prices, currency, ratings, availability and charts for up to 50 storefronts per run
- 📊 **Rich Google Play data** — 1–5★ rating histogram, install range and install count, written-review count, ads / in-app purchase info
- 🏆 **Apple top charts** — top free and top paid, up to 100 ranks per country, optionally with a full app record for every charted app
- 💬 **Google Play reviews without personal data** — rating, text, app version, date, helpful count and the developer's reply. Reviewer names, avatars and ids are **never** returned; emails and phone numbers in text are redacted
- 🤝 **Polite and transparent** — only public, robots.txt-allowed pages and Apple's documented API; Apple's ~20 calls/minute limit is respected; every run records the robots.txt decision in its summary
- ⚡ **Fast and cheap** — no browser; 100 App Store apps are one API call

### How to use

1. Paste **app ids or store URLs** into *Apps* — mix both stores freely:
   - App Store: `6448311069`, `id6448311069` or `https://apps.apple.com/us/app/chatgpt/id6448311069`
   - Google Play: `com.spotify.music` or `https://play.google.com/store/apps/details?id=com.spotify.music`
2. Pick **countries** (2-letter codes, default `us`) and, for Google Play texts, a **language** (`en`, `de`, `pt-BR`…).
3. Optionally add **Apple top charts** and tick **Include reviews** for Google Play reviews.
4. Run. Use *Max results* or Apify's *maximum cost per run* to cap spending — the Actor stops cleanly.

#### Input example

```json
{
  "apps": ["6448311069", "479516143", "com.spotify.music", "com.duolingo"],
  "countries": ["us", "de"],
  "language": "en",
  "appleCharts": ["top-free"],
  "chartSize": 25,
  "includeReviews": true,
  "maxReviewsPerApp": 20
}
```

### Output

Four record types share one dataset: `app`, `review`, `chart-entry` and `error` (an input that failed, never charged). Real records from a test run on 2026-10-06 (long texts shortened here):

**App Store app**

```json
{
  "type": "app",
  "store": "apple",
  "appId": "479516143",
  "bundleId": "com.mojang.minecraftpe",
  "country": "us",
  "title": "Minecraft: Play with Friends!",
  "developer": "Mojang",
  "developerLegalName": "Mojang AB",
  "developerId": "479516146",
  "developerUrl": "https://apps.apple.com/us/developer/mojang/id479516146",
  "genre": "Games",
  "genres": ["Games", "Simulation", "Adventure"],
  "price": 6.99,
  "currency": "USD",
  "priceText": "$6.99",
  "free": false,
  "ratingAverage": 4.5071,
  "ratingCount": 841917,
  "ratingHistogram": null,
  "version": "26.52",
  "sizeBytes": 1327799296,
  "minOsVersion": "13.0",
  "contentRating": "9+",
  "releaseDate": "2011-11-17T08:00:00.000Z",
  "lastUpdated": "2026-09-28T16:23:50.000Z",
  "releaseNotes": "Various bug fixes!",
  "description": "Dive into an open world of building, crafting and survival. Gather resources, survive the night, and build whatever you can imagine one bloc…",
  "supportedLanguages": ["DA", "NL", "EN", "FI", "…"],
  "iconUrl": "https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/3b/b7/24/3bb724be-0244-933a-af48-ad2195689877/AppIcon-0-0-1x_U007emarketing-0-10-0-85-220.png/512x512bb.jpg",
  "screenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/07/47/6f/07476fcd-1ecf-18ca-e7f7-364d6c6cd5e1/pr_source.png/406x228bb.png", "…"],
  "storeUrl": "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143",
  "scrapedAt": "2026-10-06T15:08:39.202Z"
}
```

**Google Play app**

```json
{
  "type": "app",
  "store": "google",
  "appId": "com.duolingo",
  "country": "us",
  "language": "en",
  "title": "Duolingo: Learn Languages",
  "summary": "Make language learning fun with Spanish, French, English, chess, math & music.",
  "developer": "Duolingo",
  "developerId": "6957685454452609502",
  "developerUrl": "https://play.google.com/store/apps/dev?id=6957685454452609502",
  "developerWebsite": "https://www.duolingo.com/help/support-request",
  "genre": "Education",
  "genreId": "EDUCATION",
  "price": 0,
  "currency": "USD",
  "free": true,
  "inAppPriceRange": "$0.99 - $239.99 per item",
  "containsAds": true,
  "ratingAverage": 4.7321,
  "ratingCount": 49510755,
  "ratingHistogram": { "1": 1025581, "2": 370222, "3": 1130252, "4": 5788262, "5": 41196389 },
  "reviewCount": 958793,
  "installs": "500,000,000+",
  "minInstalls": 500000000,
  "installCount": 979094893,
  "version": null,
  "contentRating": "Everyone",
  "releaseDate": "2013-05-29T12:18:00.000Z",
  "lastUpdated": "2026-09-30T16:46:06.000Z",
  "releaseNotes": "Our mascot owl, Duo, is trading in his usual diet of mice for bugs this week. Yup, we’re squashing those pesky bugs to make the experience b…",
  "storeUrl": "https://play.google.com/store/apps/details?id=com.duolingo",
  "scrapedAt": "2026-10-06T15:06:53.473Z"
}
```

**Google Play review** — no reviewer identity; the reviewer's name is removed from the developer's reply too

```json
{
  "type": "review",
  "store": "google",
  "appId": "com.ubercab",
  "country": "us",
  "reviewId": "feb5aa1b-c2fa-4f20-8b37-dffab90c9d1a",
  "rating": 3,
  "title": null,
  "text": "The app itself has usually worked fine for getting a ride but often means finding your driver. It determines weird pickup spots sometimes, e…",
  "appVersion": "4.646.10004",
  "date": "2026-09-08T03:28:38.000Z",
  "thumbsUpCount": 7,
  "developerReplyText": "Hi [name]! We would like to know more about this. It would be great if you could send out a description of this with details at t.uber.com/c…",
  "developerReplyDate": "2020-01-17T06:20:15.000Z",
  "storeUrl": "https://play.google.com/store/apps/details?id=com.ubercab"
}
```

**Apple chart entry**

```json
{
  "type": "chart-entry",
  "store": "apple",
  "chart": "top-free",
  "country": "de",
  "rank": 1,
  "appId": "6473753684",
  "title": "Claude by Anthropic",
  "developer": "Anthropic PBC",
  "releaseDate": "2024-05-13",
  "storeUrl": "https://apps.apple.com/de/app/claude-by-anthropic/id6473753684",
  "chartUpdatedAt": "2026-10-06T15:07:22.000Z"
}
```

#### Fields

| Field | App Store | Google Play |
| --- | --- | --- |
| `appId` | numeric id | package name |
| `developer` / `developerLegalName` | developer name / legal seller name | developer name / — |
| `developerId`, `developerUrl`, `developerWebsite` | ✓ | ✓ |
| `genre`, `genreId`, `genres` | ✓ (all genres) | ✓ (primary) |
| `price`, `currency`, `priceText`, `free` | ✓ | ✓ |
| `inAppPriceRange`, `containsAds` | — | ✓ |
| `ratingAverage`, `ratingCount` | ✓ (this country) | ✓ |
| `ratingHistogram` (1–5★ counts) | — | ✓ |
| `reviewCount` (written reviews) | — | ✓ |
| `installs`, `minInstalls`, `installCount` | — | ✓ (`installCount` is the figure Google embeds in the page; the page itself only shows the range) |
| `version`, `minOsVersion` | ✓ | when not "varies with device" |
| `sizeBytes` | ✓ | — (Google no longer publishes it) |
| `contentRating`, `releaseDate`, `lastUpdated`, `releaseNotes`, `description` | ✓ | ✓ |
| `summary` (short description) | — | ✓ |
| `supportedLanguages` | ✓ | — |
| `iconUrl`, `screenshotUrls` (max 10), `storeUrl` | ✓ | ✓ |

Descriptions are clipped at 5,000 characters, release notes and review texts at 3,000. Missing values are `null`, never guessed.

### Pricing

Pay per result: **$0.50 per 1,000 apps**, **$0.10 per 1,000 reviews** and **$0.30 per 1,000 chart entries**, plus **$0.002 per run**. Platform usage is included — you pay nothing else. Example: 50 competitor apps in 3 countries with 20 reviews each = 150 apps + 3,000 reviews ≈ $0.38. Error rows are free. Cap any run with *Max results* or Apify's *maximum cost per run* — the Actor stops cleanly.

### Use cases

- **Competitor tracking:** schedule a daily run for your app and your competitors; chart ratings, rating counts, prices and release cadence over time
- **Market research:** compare prices, categories and ratings of an app across 50 countries and both stores
- **Chart monitoring:** who entered the top 100 in Germany this week, and which company is behind it
- **Product feedback:** what users praise or complain about in Google Play reviews, and how competitors reply

### FAQ

**Which countries work?** Any App Store / Google Play storefront, as a 2-letter code (`us`, `gb`, `de`, `bg`, `jp`…). An app that isn't sold in a country returns an `error` row for that country.

**Why are there no App Store reviews?** Apple's customer-review feed (`itunes.apple.com/{country}/rss/customerreviews/…`) is disallowed by Apple's robots.txt (`Disallow: /*/rss/*`), and Apple's website terms forbid page scraping, so we don't collect them. App Store records still include the rating average and count.

**How many Google Play reviews do I get?** Up to **20 per app, country and language** — the reviews Google shows on the public app page (its "most relevant" selection, not the newest). Loading more would require Google Play's internal endpoint, which its robots.txt disallows (`Disallow: /_`), so we don't use it. Running several countries or languages gives you different reviews.

**Why is a review's date newer than the developer's reply?** The date is when the review was last edited; reviewers often update old reviews after a reply.

**Can I search by keyword?** No. Both stores disallow their search pages in robots.txt (`itunes.apple.com: Disallow: /search*`, `play.google.com: Disallow: /store/search`). Use app ids / URLs, or start from the Apple top charts.

**Is this personal data?** Reviewer names, usernames, avatars and user ids are never output, the reviewer's name is removed from developer replies, and emails / phone numbers in texts are replaced with `[email]` / `[phone]`. Note that some developers publish under their own personal name — that is how the store lists them.

### Limitations

- **App Store:** no reviews and no rating histogram (see FAQ). Ratings are per storefront. App texts come in the storefront's own language (the *Language* setting applies to Google Play only).
- **Google Play:** at most 20 reviews per app, country and language; reviews have no title; app size is not published; `version` / `minOsVersion` are `null` when Google shows "Varies with device". Google Play data is read from the public app page, so a change to Google's page layout can break it until we update the Actor.
- **Charts:** Apple top free and top paid (iPhone apps), up to 100 ranks — the limit of Apple's public feed. Apple's feed server is sometimes slow; the Actor retries, and a chart that still fails returns an `error` row.
- **No keyword search** (see FAQ).
- Throughput: App Store lookups are throttled to Apple's documented ~20 calls/minute (100 apps per call); Google Play pages are fetched about one per second.

# Changelog

This Actor's version history is a separate document: https://apify.com/folt/app-store-scraper/changelog.md

# Actor input Schema

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

App Store ids or URLs (6448311069, https://apps.apple.com/us/app/chatgpt/id6448311069) and Google Play package names or URLs (com.spotify.music, https://play.google.com/store/apps/details?id=com.spotify.music). Up to 1,000 per run.

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

Storefronts as 2-letter ISO codes (us, gb, de, bg…). Prices, currency, ratings, availability and charts are per country. Up to 50.

## `language` (type: `string`):

Language of Google Play texts, e.g. en, de, pt-BR. App Store texts come in the storefront's own language.

## `appleCharts` (type: `array`):

App Store top charts to include for every country (iPhone apps, from Apple's public marketing feeds).

## `chartSize` (type: `integer`):

How many ranks per chart (1–100).

## `chartAppDetails` (type: `boolean`):

Also returns an app record (price, rating, version, developer…) for every app in the charts. Each one is charged as an app.

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

Adds the reviews Google shows on each app's public page (up to 20 per app and country, Google's "most relevant" selection). Reviewer names and avatars are never included. App Store reviews are not available — see the README.

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

Per app and country (1–20).

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

Stops after this many charged results (apps + reviews + chart entries). Leave empty for no limit.

## Actor input object example

```json
{
  "apps": [
    "6448311069",
    "com.spotify.music"
  ],
  "countries": [
    "us"
  ],
  "language": "en",
  "appleCharts": [
    "top-free"
  ],
  "chartSize": 10,
  "chartAppDetails": false,
  "includeReviews": true,
  "maxReviewsPerApp": 3
}
```

# Actor output Schema

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

App records from both stores, Google Play reviews and Apple top-chart entries.

## `allFields` (type: `string`):

The same records with every field, as JSON.

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

Per-input status, counts and anything that could not be processed.

# 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": [
        "6448311069",
        "com.spotify.music"
    ],
    "countries": [
        "us"
    ],
    "appleCharts": [
        "top-free"
    ],
    "chartSize": 10,
    "includeReviews": true,
    "maxReviewsPerApp": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("folt/app-store-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": [
        "6448311069",
        "com.spotify.music",
    ],
    "countries": ["us"],
    "appleCharts": ["top-free"],
    "chartSize": 10,
    "includeReviews": True,
    "maxReviewsPerApp": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("folt/app-store-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": [
    "6448311069",
    "com.spotify.music"
  ],
  "countries": [
    "us"
  ],
  "appleCharts": [
    "top-free"
  ],
  "chartSize": 10,
  "includeReviews": true,
  "maxReviewsPerApp": 3
}' |
apify call folt/app-store-scraper --silent --output-dataset

```

## MCP server setup

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