# App Store Search & Top Charts - iOS App Data (`dropin-apis/app-store-search-charts`) Actor

Search iOS apps, look up IDs or bundle IDs, and get country top-free, top-paid, or top-grossing charts from Apple's public catalog and RSS endpoints. No login, browser scraping, proxy, or personal-data collection.

- **URL**: https://apify.com/dropin-apis/app-store-search-charts.md
- **Developed by:** [drop-in apis](https://apify.com/dropin-apis) (community)
- **Categories:** Developer tools, Marketing, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.08 / 1,000 app results

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 Search & Top Charts API

Search iOS apps, resolve app IDs or bundle IDs, and get country top-free, top-paid, or top-grossing charts from **Apple's public catalog and RSS endpoints**. Results are structured app rows that can feed `dropin-apis/app-store-reviews` directly—no login, App Store Connect key, browser scraping, proxy, or CAPTCHA handling.

**Price:** `$0.00008` per delivered app row (**$0.08 per 1,000**), with no custom setup or query fee. Apify also adds its standard `$0.00005` Actor Start event per 256 MiB run. A real zero-result answer succeeds, writes a free run summary, and pushes no paid result row; the platform start event can still apply. Live health runs delivered 24 search results in **2.955–4.225 seconds**; measured Actor cost averaged about `$0.0003` per run. Full evidence is in [VERIFY.md](./VERIFY.md).

### What you get

- `search`: keyword → up to 200 iOS apps for one storefront.
- `lookup`: numeric IDs, `id123...`, App Store URLs, or bundle IDs → matching apps.
- `topCharts`: top free, paid, or grossing apps by country, optionally filtered by Apple genre ID, up to 50 rows.
- One stable shape across all modes: `appId`, `bundleId`, `country`, name, public publisher display name, price, ratings, version, genres, OS requirement, Store URL, source, chart rank, and `checkedAt`.
- A free `RUN-SUMMARY` with found/pushed counts, invalid inputs, endpoint families, and the empty-result explanation.

The output intentionally omits App Store icons, screenshots, previews, and copied app-description bodies. Apple's Search API treats promotional media as restricted promotional content; this Actor stays focused on factual catalog fields and includes the product URL.

### Quick start

#### Search by keyword

```json
{
  "mode": "search",
  "term": "markdown editor",
  "country": "us",
  "limit": 25
}
```

#### Look up IDs, URLs, or bundle IDs

```json
{
  "mode": "lookup",
  "apps": [
    "570060128",
    "https://apps.apple.com/us/app/gmail-email-by-google/id422689480",
    "com.google.Gmail"
  ],
  "country": "us"
}
```

#### Get a country chart

```json
{
  "mode": "topCharts",
  "country": "gb",
  "chartType": "grossing",
  "limit": 25
}
```

Optional `genreId` accepts a numeric Apple App Store genre ID, for example `6014` for Games.

### Output

Each paid dataset row is one app:

```json
{
  "type": "app",
  "sourceMode": "search",
  "sourceEndpoint": "itunes-search",
  "query": "markdown editor",
  "rank": null,
  "chartType": null,
  "appId": "100000001",
  "bundleId": "com.example.notes",
  "country": "us",
  "name": "Example Notes",
  "developer": "Example Software LLC",
  "price": 0,
  "currency": "USD",
  "averageRating": 4.7,
  "ratingCount": 1200,
  "version": "3.2.1",
  "releaseDate": "2024-02-01T00:00:00Z",
  "currentVersionReleaseDate": "2026-09-20T00:00:00Z",
  "genres": ["Productivity", "Utilities"],
  "genreIds": ["6007", "6002"],
  "contentRating": "4+",
  "size": "12345678",
  "minimumOsVersion": "16.0",
  "url": "https://apps.apple.com/us/app/example-notes/id100000001",
  "checkedAt": "2026-10-10T00:00:00.000Z"
}
```

Apple owns the live values; the example shape uses synthetic fixture values. `checkedAt` is when this Actor requested the data, not a promise about when Apple refreshed its catalog cache.

### Chain search → reviews

1. Run this Actor in `search`, `lookup`, or `topCharts` mode.
2. Take the `appId` values from the dataset.
3. Run [App Store Reviews Scraper](https://apify.com/dropin-apis/app-store-reviews):

```json
{
  "apps": ["570060128", "422689480"],
  "countries": ["us"],
  "maxReviewsPerApp": 100,
  "includeAppDetails": false
}
```

The common `appId`, `country`, and `name` fields make that handoff explicit. The two Actors remain separate so catalog buyers do not pay to fetch reviews they did not request.

### Reliability and limits

- Apple's Search API documentation says approximately **20 calls per minute**, subject to change. Calls are paced at least 3.1 seconds apart, `Retry-After` is honored, and 429/5xx/network failures get bounded retries.
- Search supports 1–200 rows. Charts support 1–50; the Actor requests Apple's next available 10/25/50 feed size and returns only the requested count.
- Numeric app IDs are documented by Apple's Search API. Public `bundleId` lookup worked in the 2026-10-10 verification but is not listed in Apple's official lookup examples, so treat it as a useful compatibility path rather than a permanent guarantee.
- Current Apple Marketing Tools JSON feeds are used for unfiltered free and paid charts. Apple's public legacy iTunes RSS feed is used for grossing or genre-filtered charts because the current grossing path returned 404 during verification.
- If current chart metadata enrichment fails after retries, the Actor can still return the chart's own factual fields and rank.
- Apple can cache catalog data and can change public endpoints. There is no historical chart archive in v1.
- The Actor accepts only fixed Apple hosts, HTTPS, bounded redirects, a 2 MB response cap, a 20-second request timeout, and at most 50 lookup inputs.

### Billing and empty results

The product event is `apify-default-dataset-item` at `$0.00008`. One pushed row means one charged result. There is no custom setup, query, chart, invalid-input, or empty-result event. Apify injects its standard `apify-actor-start` event—currently `$0.00005` for this 256 MiB Actor—so an empty run has no result charge but is not necessarily a zero-dollar platform run.

Examples that succeed with zero paid rows:

- a keyword has no results in the chosen storefront;
- an app ID is not sold in that country;
- a bundle ID returns no public match;
- a valid country/chart combination returns an empty feed.

Network exhaustion, malformed upstream JSON, and invalid required input fail the run rather than returning invented data.

### Privacy and scope

The Actor returns public app/catalog metadata. It does not collect customer accounts, review-author data, emails, phone numbers, profiles, device IDs, or private App Store Connect data. `developer` is only the public publisher/developer display name returned for the app listing.

### FAQ

#### Is this affiliated with Apple?

No. It is an independent Apify Actor using public Apple endpoints. Apple, App Store, and iTunes are trademarks of Apple Inc.

#### Is this an App Store HTML scraper?

No. It calls Apple's public Search/Lookup API and RSS chart endpoints. It does not load product-page HTML or bypass access controls.

#### Why not include icons, screenshots, or descriptions?

Apple's Search API terms constrain promotional media use. V1 avoids reselling promotional assets and copied description bodies; it returns factual app metadata and the App Store product URL.

#### Does a zero-result search fail or cost money?

It does not fail and it has no result charge: the run saves `found: 0` in `RUN-SUMMARY` and pushes no dataset item. Apify's standard Actor Start event can still apply.

#### Can I get reviews in the same run?

Not in this Actor. Pass its `appId` values to `dropin-apis/app-store-reviews`; separating the jobs keeps pricing and failures understandable.

#### Is bundle-ID lookup guaranteed?

No. It is a current public behavior observed live, but Apple's official lookup examples document numeric IDs rather than bundle IDs. Numeric IDs and App Store URLs are the most stable inputs.

### Sources

- [Apple iTunes Search API documentation](https://performance-partners.apple.com/search-api)
- [Apple RSS Builder](https://rss.marketingtools.apple.com/)
- [Demand and price gate](../../research/round12/APP-STORE-SEARCH-GATE.md)
- [Verification record](./VERIFY.md)

# Actor input Schema

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

search finds iOS apps by keyword; lookup resolves app IDs, bundle IDs, or App Store URLs; topCharts returns a country ranking.

## `term` (type: `string`):

Required in search mode. A plain keyword or phrase such as markdown editor, budgeting, or language learning.

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

Used in lookup mode. One numeric app ID, id-prefixed ID, App Store URL, or bundle ID per line. Invalid rows are skipped and reported in RUN-SUMMARY.

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

Two-letter App Store storefront code such as us, gb, de, or iq. Case does not matter.

## `limit` (type: `integer`):

Maximum rows to return. Search supports 1-200. Top charts supports 1-50 and fetches the smallest official feed size that covers the requested limit.

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

Used in topCharts mode: top free, top paid, or top grossing apps for the selected storefront.

## `genreId` (type: `integer`):

Optional numeric Apple App Store genre ID for topCharts mode, for example 6014 for Games. When omitted, the chart covers all app genres.

## Actor input object example

```json
{
  "mode": "search",
  "term": "markdown",
  "apps": [
    "570060128",
    "com.google.Gmail"
  ],
  "country": "us",
  "limit": 25,
  "chartType": "free"
}
```

# Actor output Schema

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

One compatible app row per delivered search, lookup, or chart result.

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

Mode, requested count, found count, invalid inputs, endpoints used, and empty-result status. This key-value record is free.

# 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": "search",
    "term": "markdown",
    "apps": [
        "570060128",
        "com.google.Gmail"
    ],
    "country": "us",
    "limit": 25,
    "chartType": "free"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dropin-apis/app-store-search-charts").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": "search",
    "term": "markdown",
    "apps": [
        "570060128",
        "com.google.Gmail",
    ],
    "country": "us",
    "limit": 25,
    "chartType": "free",
}

# Run the Actor and wait for it to finish
run = client.actor("dropin-apis/app-store-search-charts").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": "search",
  "term": "markdown",
  "apps": [
    "570060128",
    "com.google.Gmail"
  ],
  "country": "us",
  "limit": 25,
  "chartType": "free"
}' |
apify call dropin-apis/app-store-search-charts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dropin-apis/app-store-search-charts"
        }
    }
}
```

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/n4n1xfaRFLPoE0sAd/builds/H0htHQpqMapcpG995/openapi.json
