# App Store & Google Play API: iOS, Android, ASO (`ocius-data/app-store-data-reliable`) Actor

App Store and Google Play API: iOS and Android app details, keyword search ranks and top charts in any country. Ratings, installs, versions. Pay per app.

- **URL**: https://apify.com/ocius-data/app-store-data-reliable.md
- **Developed by:** [Christian Barbosa](https://apify.com/ocius-data) (community)
- **Categories:** Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 unique 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 API: iOS, Android, ASO

Get app data from the **Apple App Store** and **Google Play** in one normalized format: **app details**, **keyword search results** with positions, and **top charts** (free, paid, grossing) for any country. You pay **only per app found**. IDs that do not exist, empty searches and failed requests are free.

User reviews are not included by design, so the output contains no personal data.

### Why this app store scraper

- **Two stores, one schema.** The same fields for Apple and Google Play: rating, ratings count, price, currency, version, release and update dates (ISO 8601, UTC), developer, category, screenshots, icon and more. Paste App Store URLs, Google Play URLs, Apple IDs or package names in the same list: the store is detected automatically.
- **Official sources first.** Apple data comes from the official iTunes Search and Lookup API and Apple's RSS charts. Google Play data comes from the JSON embedded in each app page, not from fragile HTML selectors.
- **Keyword and chart positions.** Every search and chart row keeps its position (`searchPosition`, `chartPosition`), so you can track app store optimization (ASO) rankings over time.
- **Fair pricing.** One flat price per unique app per country. You are never charged for apps that are not found, empty results or errors.
- **Clear status.** Every input ends as `OK`, `NO_RESULTS`, `NOT_FOUND`, `INVALID_INPUT`, `BLOCKED` or `ERROR`. The run message shows the counts and the `RUN_SUMMARY` record lists each input with the reason. If more than 20% of inputs fail, the run is marked as failed so you notice.
- **Reliable by design.** No browser. Failed requests are retried with exponential backoff and a fresh session, within a retry budget. If a store keeps blocking, the Actor switches automatically from datacenter to residential proxies.
- **Safe on long runs.** Progress is saved, so a platform restart never duplicates rows or charges twice.

### What data you get

| Mode | Description |
|---|---|
| `details` | Full details for each app ID or store URL, in each selected country. |
| `search` | Apps returned for each search term, in store order, with `searchPosition`. |
| `topCharts` | Top free, top paid or top grossing apps, overall or by category, with `chartPosition`. |

The output tab has three views: overview, search and chart positions, and all fields. Download as JSON, CSV or Excel, or connect through the API.

### How to use it

1. Choose a **mode**: app details, search by keyword or top charts. The mode is optional: when it is empty, apps in the list mean details, only search terms mean search, and neither means top charts.
2. For details, paste **app IDs or URLs**: `https://apps.apple.com/us/app/whatsapp-messenger/id310633997`, `310633997`, `com.whatsapp` or `https://play.google.com/store/apps/details?id=com.whatsapp`. Use `apple:com.burbn.instagram` for an Apple bundle ID.
3. For search, enter one or more **search terms**. For top charts, choose the **chart type** and **category**.
4. Choose the **stores** (search and charts) and one or more **countries** (`us`, `gb`, `co`, `de`, `br`...).
5. Optional: set the **language**, **max results per search or chart** and **max items per run**.
6. Run the Actor.

### Example output

```json
{
  "store": "googlePlay",
  "appId": "com.raha.app.mymoney.free",
  "title": "MyMoney—Track Expense & Budget",
  "developer": "Ananta Raha",
  "category": "Finance",
  "price": 0,
  "currency": "USD",
  "free": true,
  "rating": 4.784,
  "ratingsCount": 68109,
  "installs": 1000000,
  "installsText": "1,000,000+",
  "version": "6.6-free",
  "updatedAt": "2026-07-31T19:15:16.000Z",
  "releasedAt": "2019-11-17T07:59:34.000Z",
  "contentRating": "Everyone",
  "url": "https://play.google.com/store/apps/details?id=com.raha.app.mymoney.free",
  "country": "us",
  "searchTerm": "budget tracker",
  "searchPosition": 1,
  "detailsComplete": true,
  "input": "budget tracker",
  "sourceUrl": "https://play.google.com/store/apps/details?id=com.raha.app.mymoney.free&hl=en&gl=us",
  "scrapedAt": "2026-11-01T19:49:15.617Z"
}
```

### Pricing

You pay a flat price of USD 0.002 per unique app (store + country + app ID) saved in the run. The same app found by several search terms in the same country is charged once. Apps not found, empty searches and failed requests are not charged. Your maximum cost per run is respected: the Actor stops as soon as it is reached.

| Run | Unique apps | Approximate cost |
|---|---|---|
| Daily check of 20 competitor apps in 1 country | 20 | USD 0.04 |
| Top 100 free apps in both stores, 1 country | 200 | USD 0.40 |
| 10 keywords, top 30 results, both stores, 3 countries | up to 1,800 | up to USD 3.60 |

Platform compute is billed separately by Apify and is small: in local tests, 1,500 Google Play and Apple apps with full details took about 70 seconds. The default memory is 256 MB.

### Output fields

| Field | Meaning | When it is null |
|---|---|---|
| `store` | `appStore` or `googlePlay`. | Never |
| `appId` | Apple numeric ID or Google Play package name. | Never |
| `bundleId` | Apple bundle ID. | Always on Google Play |
| `title`, `summary` | App name and short description. | `summary`: on Apple, which has no short description |
| `developer`, `developerId` | Developer name and store ID. | When the store does not show it |
| `developerWebsite` | Website the developer publishes on the store page. | When not published |
| `developerEmail` | Support email published on the Google Play page (a public business contact). Present only when `includeDeveloperEmail` is on. | On Apple, or when not published |
| `category`, `categoryId` | Primary category name (in the store language) and code. | Rarely |
| `price`, `currency`, `free` | Price in the country currency (for example 3500 COP or 6.49 EUR), and whether the app is free. | When the store does not report a price |
| `rating`, `ratingsCount` | Average rating (0 to 5) and number of ratings in that country. | When the app has no ratings yet |
| `reviewsCount` | Number of written reviews (Google Play counts them separately from star ratings). | Always on Apple |
| `ratingsHistogram` | Number of ratings per star, for example `{"1": 3717957, ..., "5": 27375607}`. | Always on Apple, which does not publish it |
| `ratingCurrentVersion`, `ratingsCountCurrentVersion` | Average rating and number of ratings of the current version only. | Always on Google Play |
| `installs`, `installsText` | Google Play minimum install count (number) and the label shown in the store. | Always on Apple, which does not publish installs |
| `version`, `minOsVersion` | Current version and minimum iOS or Android version. | On Google Play when the version "varies with device" |
| `updatedAt`, `releasedAt` | Last update and first release, ISO 8601 in UTC. | When the store does not report it |
| `size` | Download size in bytes. | Always on Google Play, which no longer shows it |
| `contentRating` | Age rating as shown in the store (for example `12+`, `Everyone`, `USK ab 0 Jahren`). | Rarely |
| `description` | Full description as plain text. | When the store does not report it |
| `releaseNotes` | "What's new" text of the current version, as plain text. | When the developer did not publish it |
| `genres` | All categories of the app, in the store language. | Rarely |
| `languages` | Languages the app supports (ISO 639-1 codes). | Always on Google Play |
| `containsAds`, `offersInAppPurchases`, `inAppPurchaseRange` | Whether the app shows ads or sells in-app purchases, and the price range shown by the store. | Always on Apple, which does not publish them |
| `privacyPolicyUrl` | Link to the privacy policy published on the store page. | On Apple, or when not published |
| `developerUrl` | Developer page on the store, with all the developer's apps. | Rarely |
| `screenshots`, `ipadScreenshots`, `headerImage`, `icon` | Image URLs (`ipadScreenshots` on Apple, `headerImage` on Google Play). | Empty list or `null` when there are none |
| `url` | Public store page of the app. | Never |
| `country`, `language`, `mode` | The filters used. | Never |
| `searchTerm`, `searchPosition` | Search term and position (1 = first). | Outside search mode |
| `chartType`, `chartCategory`, `chartPosition` | Chart and position (1 = first). | Outside top charts mode |
| `detailsComplete` | `false` when only the basic list fields were available (see Known limits). | Never |
| `input` | The app ID, URL, search term or chart that produced the row. | Never |
| `sourceUrl` | The source request, to check the data yourself. | Never |
| `scrapedAt` | When the data was collected (UTC). | Never |

### Statuses and errors

| Status | Meaning | What to do |
|---|---|---|
| `OK` | Data returned and charged. | Nothing |
| `NO_RESULTS` | The store confirmed an empty search or chart. Not charged. | Try another term, category or country. |
| `NOT_FOUND` | The app ID does not exist or the app is not available in that country. Not charged. | Check the ID or try another country. |
| `INVALID_INPUT` | The entry is not a recognized app ID or store URL. Not charged. | Use an Apple numeric ID, a Google Play package name or a store URL. |
| `BLOCKED` | The store kept rate-limiting after all retries and proxy escalation. Not charged. | Run again later or select residential proxies. |
| `ERROR` | The store returned an unexpected response, for example after a site change. Not charged. | Run again; if it persists, open an issue. |
| `SKIPPED` | Not processed because the maximum cost or maximum items was reached. Not charged. | Raise the limit. |

### Known limits

- **Store result caps:** Apple search returns up to 200 apps, Apple charts up to 100, Google Play search about 30 and Google Play charts up to 200. When fewer apps are returned than requested, the reason is written in `RUN_SUMMARY`.
- **Apple charts** are iPhone charts. The current Apple RSS feed has no grossing chart, so free, paid and grossing charts use Apple's long-standing RSS feed, with the current feed as a backup for free and paid.
- **Google Play paid charts** in some categories and countries are short or empty; the Actor reports exactly what the store returns.
- **Google Play `size`** is always empty because Google no longer publishes it. Apple does not publish installs.
- **Basic rows:** with **Full details for Google Play results** turned off, or if an app page fails after all retries, Google Play search and chart rows contain only the list fields (title, developer, price, rating, icon) and have `detailsComplete: false`.
- **Language:** Apple applies the language only where the country store offers it; otherwise the store default language is used.
- **No reviews:** user reviews are excluded on purpose because they contain personal data.

### Integrations: API, schedules, webhooks, Google Sheets and AI agents

**API.** Run the Actor and receive the rows in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/ocius-data~app-store-data-reliable/run-sync-get-dataset-items?token=YOUR_API_TOKEN&format=json"   -H "Content-Type: application/json"   -d '{"mode": "details", "apps": ["com.spotify.music", "324684580"], "countries": ["us"]}'
```

Python, with the official `apify-client` package:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("ocius-data/app-store-data-reliable").call(run_input={"mode": "topCharts", "countries": ["us", "gb"], "maxResults": 100})
for app in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(app["store"], app["chartPosition"], app["title"], app["rating"])
```

Node.js, with the official `apify-client` package:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('ocius-data/app-store-data-reliable').call({ mode: 'search', searchTerms: ['budget app'], countries: ['us'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**Schedules.** Save your input as a task and open **Schedules** in Apify Console to track charts, ratings and versions daily. Keep the same countries and terms in every run so positions are comparable.

**Webhooks, Google Sheets, Zapier, Make and n8n.** In the task, open **Integrations** and add a webhook for `ACTOR.RUN.SUCCEEDED`, the Google Sheets integration, or the official Apify app in Zapier, Make or n8n (trigger "Actor run finished", action "Get dataset items").

**MCP and AI agents.** The Actor is available through the Apify MCP server (`https://mcp.apify.com`). Add `ocius-data/app-store-data-reliable` to the server's Actor list and an AI agent such as Claude can call it with plain inputs such as `{"mode": "details", "apps": ["com.whatsapp"]}`.

### FAQ

**Is it legal?** The Actor collects publicly available store listing data. Apple data comes from Apple's official public API and feeds. No user reviews or other personal data are collected.

**Can I mix both stores in one list?** Yes. In details mode each ID or URL is routed to its store automatically.

**How do I track keyword rankings?** Use search mode with your keywords and schedule the Actor daily. Compare `searchPosition` by `appId`, `searchTerm` and `country` over time.

**Why are prices and ratings different by country?** Each store reports price, currency, ratings and availability per country. Add every country you need to `countries`.

### Related Actors from ocius-data

Built to the same standard: a status for every input in `RUN_SUMMARY`, actionable error messages and list-based inputs, so they chain well in one workflow:

- **[Google Autocomplete API: Keyword Ideas & Questions](https://apify.com/ocius-data/google-autocomplete-keyword-ideas)**: hundreds of long-tail keyword ideas and questions from Google, YouTube and Shopping autocomplete.
- **[Bulk Keyword Search Volume & CPC - Keyword Planner](https://apify.com/ocius-data/keyword-metrics)**: absolute monthly search volume, cost per click (CPC) and competition from Google Ads data, no Ads account needed.
- **[Google Trends API: Interest, Related & Trending Now](https://apify.com/ocius-data/google-trends-reliable)**: relative interest over time and by region, related queries and Trending Now.

### Changelog

- **November 2026** The **mode** field is optional and follows the input when it is empty, so AI agents and API calls that send only search terms or only apps work without it.
- **November 2026** New fields: written reviews count, ratings per star, rating of the current version, release notes, all categories, supported languages, ads and in-app purchases, privacy policy, developer page, iPad screenshots and header image. New "Ratings and monetization" view.
- **0.1** First version: details, search and top charts for Apple App Store and Google Play, normalized output, per-input statuses, run summary, field completeness and pay per unique app.

### Use cases

- App store optimization (ASO): keyword ranking and chart tracking
- Competitor monitoring: versions, update frequency, ratings and prices
- Market research by category and country
- Lead lists of app publishers (company names and websites)
- Datasets for AI agents and analytics

### Tips

- For daily rank tracking, keep the same countries, language and terms in every run, so positions are comparable.
- Turn off **Full details for Google Play results** for fast, low-cost ranking checks; turn it on when you need installs, versions and dates.
- Use **Max items per run** and the maximum cost per run to control spending on large keyword lists.
- `RUN_SUMMARY` also includes field completeness per store (`fieldCompletenessPercent`), which helps you spot fields a store stopped publishing.

### Support

Open an issue on the Actor page. Issues are reviewed every day and fixes are released quickly.

# Actor input Schema

## `mode` (type: `string`):

What to extract. Details uses the apps list; Search uses the search terms; Top charts uses chart type and category. Optional: when it is left empty, the mode follows the input (apps: Details; only search terms: Search; neither: Top charts).

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

For Details mode. The store is detected automatically: Apple numeric ID (284882215 or id284882215), App Store URL, Google Play package (com.whatsapp) or Google Play URL. Prefix an Apple bundle ID with apple: (for example apple:com.burbn.instagram). You are charged once per app found; IDs not found are free.

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

For Search mode. Each term is searched in every selected store and country. Results keep their position (searchPosition) for keyword tracking.

## `stores` (type: `array`):

Stores to use in Search and Top charts modes. In Details mode the store comes from each ID.

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

Two-letter country codes (us, gb, co, de, br...). Each app, term or chart is processed for every country. Prices, currency, ratings and availability depend on the country.

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

Language for titles and descriptions, for example en, es, de or pt-BR. Apple applies it only where the country store offers that language.

## `chartType` (type: `string`):

Which top chart to extract in Top charts mode.

## `category` (type: `string`):

Chart category, mapped to the equivalent category in each store.

## `maxResults` (type: `integer`):

Maximum apps per search term or chart, per store and country. Store limits: Apple search 200, Apple charts 100, Google Play search about 30, Google Play charts 200.

## `fetchFullDetails` (type: `boolean`):

Open each Google Play app page in Search and Top charts modes to get every field (installs, version, dates, description, screenshots). Turn off for faster runs with basic fields only. Apple results always include full details.

## `includeDeveloperEmail` (type: `boolean`):

Adds the support email that the developer publishes on the Google Play page (a public business contact). Off by default. Apple does not publish it.

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

Stops the run after this many dataset items. 0 means no limit.

## `maxRetries` (type: `integer`):

How many times a blocked or failed request is attempted, with a new session each time.

## `maxConcurrency` (type: `integer`):

Parallel requests to Google Play. Apple requests are spaced automatically to respect its rate limit.

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

By default the Actor uses Apify datacenter proxies and switches automatically to residential proxies if a store blocks requests.

## Actor input object example

```json
{
  "mode": "details",
  "apps": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.whatsapp"
  ],
  "searchTerms": [
    "budget tracker"
  ],
  "stores": [
    "appStore",
    "googlePlay"
  ],
  "countries": [
    "us"
  ],
  "language": "en",
  "chartType": "free",
  "category": "ALL",
  "maxResults": 50,
  "fetchFullDetails": true,
  "includeDeveloperEmail": false,
  "maxItems": 0,
  "maxRetries": 6,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per app (and per search term or chart in those modes), normalized across both stores.

## `runSummary` (type: `string`):

Status per entry (OK, NO_RESULTS, NOT_FOUND, INVALID_INPUT, BLOCKED, ERROR), field completeness and charges.

# 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 = {
    "mode": "details",
    "apps": [
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
        "com.whatsapp"
    ],
    "searchTerms": [
        "budget tracker"
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ocius-data/app-store-data-reliable").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 = {
    "mode": "details",
    "apps": [
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
        "com.whatsapp",
    ],
    "searchTerms": ["budget tracker"],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("ocius-data/app-store-data-reliable").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 '{
  "mode": "details",
  "apps": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "com.whatsapp"
  ],
  "searchTerms": [
    "budget tracker"
  ],
  "countries": [
    "us"
  ]
}' |
apify call ocius-data/app-store-data-reliable --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ocius-data/app-store-data-reliable"
        }
    }
}
```

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/Li3VjHulmgc5Qk9vA/builds/nwGcWq9b1tMTrgiyy/openapi.json
