# App Store Scraper — Top Grossing, Charts & App Data (`viralanalyzer/appstore-niche-intelligence`) Actor

Scrape iOS App Store charts including TOP GROSSING — the revenue chart — plus keyword search and full app metadata: rating, rating count, price, category, size, version. Any country. Pure HTTP on Apple's public feeds: no API key, no login, no browser.

- **URL**: https://apify.com/viralanalyzer/appstore-niche-intelligence.md
- **Developed by:** [viralanalyzer](https://apify.com/viralanalyzer) (community)
- **Categories:** Developer tools, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 app discovereds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## App Store Scraper — Top Grossing, Charts & App Data

Scrape iOS App Store **charts including TOP GROSSING** — the revenue chart — plus keyword search
and full app metadata. Any country. Pure HTTP on Apple's public feeds: **no API key, no login,
no headless browser, no residential proxy.**

Most App Store scrapers give you Top Free. Top Free tells you what is popular. **Top Grossing tells
you what makes money** — and that is the chart this Actor reads.

> 🇧🇷 **Versão em português no final deste README.**

***

### Features

- **Top Grossing chart** — the revenue ranking, per storefront, up to 100 apps.
- **Top Free and Top Paid** charts too, same shape.
- **Genre scoping** — pass an Apple genre ID (6017 Education, 6007 Productivity, 6013 Health &
  Fitness, 6015 Finance…) to get the chart inside a niche.
- **Keyword search** — what ranks for a search term, per country.
- **App details by ID** — 20+ fields per app including rating, rating count, price, size, version.
- **Optional enrichment** — chart entries carry no ratings; switch `enrichWithLookup` on and each
  entry is completed with the full metadata record.
- **Explicit nulls** — every field Apple does not provide comes back as `null`, never as a guess or
  an empty string. What is missing is visible.
- **Provenance-checked** — every row is verified before publication: known data source, numeric
  `appId`, parseable timestamp, matching storefront, non-empty name. A malformed record is dropped
  and logged, never published; if more than 5% of a run fails the check the run aborts with the
  rate, because that means the upstream schema moved.
- **Honest failures** — a blocked feed or an empty answer returns a **labeled diagnostic and is not
  charged**. A schema change fails loudly instead of returning silence.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `charts` | `charts` · `search` · `appDetails` |
| `countries` | array | `["us","br"]` | 2-letter storefronts. Charts are per country. |
| `chart` | select | `top-grossing` | `top-grossing` · `top-free` · `top-paid` |
| `genreId` | string | — | Apple genre ID, e.g. `6017`. Empty = overall chart. |
| `limit` | integer | `50` | 1–100. **Apple caps at 100** — asking 200 still returns 100. |
| `searchTerms` | array | — | Keywords (mode = search). |
| `appIds` | array | — | Numeric App Store IDs (mode = appDetails). |
| `enrichWithLookup` | boolean | `false` | Complete chart entries with ratings and full metadata. |
| `proxyConfiguration` | object | datacenter | Optional — feeds are public, residential is not needed. |

### Output

One row per app. `itemType: "app"`.

`country` · `chart` · `genreId` · **`rank`** · `searchTerm` · `appId` · `bundleId` · `name` ·
`developer` · `developerId` · `categoryId` · `categoryName` · `price` · `currency` ·
`formattedPrice` · `isFree` · `releaseDate` · `currentVersionReleaseDate` · `version` ·
**`averageUserRating`** · **`userRatingCount`** · `averageUserRatingCurrentVersion` ·
`userRatingCountCurrentVersion` · `contentAdvisoryRating` · `fileSizeBytes` · `minimumOsVersion` ·
`languageCount` · `genres` · `description` · `sellerName` · `sellerUrl` · `artworkUrl` ·
`appStoreUrl` · `hasInAppPurchases` · `chartUpdatedAt` · `dataSource` · `enriched` · `scrapedAt`

### Use cases

- **Niche discovery** — read Top Grossing inside a genre and see which categories sustain paying users.
- **Competitor tracking** — watch a rival's rank, rating count and version cadence over time.
- **Market entry research** — compare the same niche across storefronts (US vs BR vs DE).
- **ASO research** — what actually ranks for a keyword, per country.
- **Pricing benchmarks** — price and currency per app, per storefront.

### Documented limitations — validated 2026-07-28

Everything here was checked with a live request on that date. Nothing is assumed.

| Limitation | Status |
|---|---|
| **In-app purchases** | ❌ **Not obtainable.** No public Apple endpoint exposes IAP presence — the 44-field lookup record has zero purchase/subscription keys. `hasInAppPurchases` is always `null`. |
| **Download / revenue numbers** | ❌ Not public. Rank is the only public proxy; absolute installs and revenue are Apple-private. |
| **Chart depth** | ⚠️ **Capped at 100** per storefront by Apple. `limit=200` returns 100. |
| **Ratings in charts** | ⚠️ Not in the chart feed. Use `enrichWithLookup` — it costs one extra request per 100 apps. |
| **`top-grossing` on the new API** | ❌ `rss.marketingtools.apple.com` returns **404** for `top-grossing` and gives `genres: []` empty. This Actor uses the **legacy** `itunes.apple.com/rss` feed, which does serve it with a populated category. |
| **Non-browser User-Agent** | ⚠️ Apple returns an empty body to plain server agents. This Actor sends a browser User-Agent. |

### FAQ

**Do I need an Apple developer account or API key?** No. Every feed used is public.

**Is Top Grossing really available?** Yes — verified on `us` and `br`, with and without a genre
filter, on 2026-07-28. It lives in Apple's legacy RSS feed, not in the newer marketing-tools API.

**Why are ratings null in my chart run?** The chart feed does not carry them. Turn on
`enrichWithLookup`.

**Can I get install counts?** No, and no honest scraper can — Apple does not publish them. Anyone
selling you "estimated downloads" is modelling, not measuring.

**What happens if a genre has no chart?** The run ends `SUCCEEDED` with one diagnostic item saying
so, and **nothing is charged**.

### Pricing

Pay-per-event on apps actually delivered. Diagnostic rows are **not** charged. Platform usage is
billed to your account at Apify cost — this Actor is pure HTTP, so it is a fraction of a cent per
run. See the pricing panel on this page for the current rate and tiers.

### Related Actors

- `viralanalyzer/substack-newsletter-intelligence` — paywall and monetization signals for newsletters
- `viralanalyzer/telegram-channel-scraper` — the same pure-HTTP approach for Telegram
- `viralanalyzer/producthunt-launches-tracker` — new product launches

### Changelog

**1.0** — First release. Legacy RSS charts (top-grossing/free/paid) with genre scoping, keyword
search, lookup by ID, optional enrichment, block-gated diagnostics, owner-skip PPE.

***

***

## 🇧🇷 App Store Scraper — Top Grossing, Rankings e Dados de Apps

Extraia rankings da App Store iOS **incluindo TOP GROSSING** — o ranking de faturamento — além de
busca por palavra-chave e metadados completos de apps. Qualquer país. HTTP puro sobre os feeds
públicos da Apple: **sem API key, sem login, sem navegador, sem proxy residencial.**

A maioria dos scrapers entrega Top Free. Top Free mostra o que é popular. **Top Grossing mostra o
que dá dinheiro** — e é esse o ranking que este Actor lê.

### Funcionalidades

- **Ranking Top Grossing** por storefront, até 100 apps
- **Top Free e Top Paid** no mesmo formato
- **Recorte por gênero** — ID da Apple (6017 Educação, 6007 Produtividade, 6013 Saúde, 6015 Finanças)
- **Busca por palavra-chave** — o que ranqueia para um termo, por país
- **Detalhe por ID** — 20+ campos incluindo nota, número de avaliações, preço, tamanho, versão
- **Enriquecimento opcional** — o ranking não traz notas; ligue `enrichWithLookup` e cada entrada é
  completada com o registro cheio
- **Nulls explícitos** — todo campo que a Apple não fornece vem como `null`, nunca como chute
- **Procedência verificada** — cada linha é checada antes de publicar: fonte conhecida, `appId`
  numérico, timestamp parseável, storefront correspondente, nome não vazio. Registro malformado é
  descartado e logado, nunca publicado; acima de 5% de descarte o run aborta informando a taxa
- **Falha honesta** — feed bloqueado ou resposta vazia gera **diagnóstico rotulado, sem cobrança**

### Entrada

Ver a tabela na seção em inglês. Padrões: `mode=charts`, `countries=["us","br"]`,
`chart=top-grossing`, `limit=50` (máximo 100, imposto pela Apple).

### Limitações documentadas — validadas em 28/07/2026

| Limitação | Situação |
|---|---|
| **Compras no app (IAP)** | ❌ **Não obtenível.** Nenhum endpoint público da Apple expõe. O registro de 44 campos não tem nenhuma chave de compra/assinatura. `hasInAppPurchases` é sempre `null`. |
| **Downloads / receita** | ❌ Não são públicos. O ranking é o único proxy; números absolutos são privados da Apple. |
| **Profundidade do ranking** | ⚠️ **Limitado a 100** por storefront pela própria Apple. |
| **Notas no ranking** | ⚠️ Não vêm no feed de ranking. Use `enrichWithLookup`. |
| **`top-grossing` na API nova** | ❌ `rss.marketingtools.apple.com` devolve **404** e `genres: []` vazio. Este Actor usa o feed **legado**, que entrega o ranking com categoria preenchida. |
| **User-Agent não-navegador** | ⚠️ A Apple devolve corpo vazio para agentes de servidor. Este Actor envia UA de navegador. |

### FAQ

**Preciso de conta de desenvolvedor Apple?** Não. Todos os feeds são públicos.

**O Top Grossing existe mesmo?** Sim — verificado em `us` e `br`, com e sem filtro de gênero, em
28/07/2026. Está no feed RSS legado, não na API nova.

**Por que as notas vieram null?** O feed de ranking não as traz. Ligue `enrichWithLookup`.

**Consigo número de downloads?** Não — e nenhum scraper honesto consegue. A Apple não publica. Quem
vende "downloads estimados" está modelando, não medindo.

### Preço

Cobrança por evento, sobre apps efetivamente entregues. Itens de diagnóstico **não** são cobrados.
O custo de plataforma é debitado na sua conta ao custo da Apify.

### Changelog

**1.0** — Primeira versão. Rankings via RSS legada com recorte por gênero, busca, lookup por ID,
enriquecimento opcional, diagnóstico com gate de bloqueio, owner-skip no PPE.

# Actor input Schema

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

charts = ranked chart per country · search = keyword search · appDetails = full metadata for known app IDs.

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

Storefronts to query, e.g. 'us', 'br', 'gb', 'de'. Charts and rankings are per storefront.

## `chart` (type: `string`):

top-grossing is the revenue chart — it exists only in Apple's legacy RSS feed, which this Actor uses.

## `genreId` (type: `string`):

Apple genre ID to scope the chart, e.g. 6017 = Education, 6007 = Productivity, 6013 = Health & Fitness, 6015 = Finance. Leave empty for the overall chart.

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

Apple caps the chart feed at 100 entries per storefront — asking for more still returns 100 (verified 2026-07-28).

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

Keywords to search the App Store with, e.g. 'habit tracker'. One request per term per country.

## `appIds` (type: `array`):

Numeric App Store IDs (trackId), e.g. 6448311069. Up to 200 per request.

## `enrichWithLookup` (type: `boolean`):

For each chart entry, also fetch the 44-field lookup record (rating, rating count, description, size, version, seller). Slower but far richer. Ratings are NOT present in the chart feed itself.

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

Optional. Apple's public feeds work on a direct connection — datacenter proxy only helps spread large runs across IPs. Residential is NOT needed.

## Actor input object example

```json
{
  "mode": "charts",
  "countries": [
    "us",
    "br"
  ],
  "chart": "top-grossing",
  "limit": 10,
  "searchTerms": [
    "habit tracker"
  ],
  "appIds": [
    "6448311069"
  ],
  "enrichWithLookup": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset with one row per app (chart entry, search hit or looked-up app). Each item follows the dataset schema.

# 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": "charts",
    "countries": [
        "us",
        "br"
    ],
    "chart": "top-grossing",
    "limit": 10,
    "searchTerms": [
        "habit tracker"
    ],
    "appIds": [
        "6448311069"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("viralanalyzer/appstore-niche-intelligence").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": "charts",
    "countries": [
        "us",
        "br",
    ],
    "chart": "top-grossing",
    "limit": 10,
    "searchTerms": ["habit tracker"],
    "appIds": ["6448311069"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("viralanalyzer/appstore-niche-intelligence").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "charts",
  "countries": [
    "us",
    "br"
  ],
  "chart": "top-grossing",
  "limit": 10,
  "searchTerms": [
    "habit tracker"
  ],
  "appIds": [
    "6448311069"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call viralanalyzer/appstore-niche-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=viralanalyzer/appstore-niche-intelligence",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/QpNAFF2AKXheXDxeg/builds/qWZwzTgMMZcQB8IJM/openapi.json
