# Apple Podcasts Chart Scraper (`taroyamada/apple-podcast-chart-tracker`) Actor

Track public Apple Podcasts chart positions and emit one source-linked movement report when a saved monitor detects new, changed, or dropped positions.

- **URL**: https://apify.com/taroyamada/apple-podcast-chart-tracker.md
- **Developed by:** [naoki anzai](https://apify.com/taroyamada) (community)
- **Categories:** SEO tools, Marketing
- **Stats:** 7 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 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/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

## Apple Podcasts Chart Scraper

Podcast growth teams, agencies, networks, and research teams provide public Apple Podcasts storefront codes and an optional genre/depth filter. The actor returns source-linked `chart_rank` rows, or one change report when a saved monitor detects new, changed, or dropped positions. Raw chart delivery remains the default for existing schedules.

### Run the next report

- [Build a media buyer shortlist](https://apify.com/taroyamada/podcast-media-buyer-shortlist-scraper) from a focused chart result.
- [Generate a podcast category benchmark](https://apify.com/taroyamada/podcast-category-network-benchmark-report) when rank context should be compared across categories or networks.

### Store Quickstart

The default path is a low-cost raw chart snapshot. Use one country and a small limit first. For recurring rank movement, set a stable `monitorKey` and `generateMovementReport` to `true`; the first `baseline_only` run stores state without dataset rows or charges.

#### 1. Raw chart snapshot

```json
{
  "countries": ["us"],
  "limit": 25,
  "delivery": "dataset",
  "dryRun": false
}
```

#### 2. Free baseline for a recurring monitor

```json
{
  "countries": ["us", "gb"],
  "genreId": "1321",
  "limit": 50,
  "monitorKey": "weekly-news-us-gb",
  "generateMovementReport": true,
  "initialRunMode": "baseline_only",
  "maxChargeUsd": 3,
  "dryRun": false
}
```

#### 3. Movement report or webhook delivery

```json
{
  "countries": ["us"],
  "limit": 25,
  "monitorKey": "weekly-news-us-gb",
  "generateMovementReport": true,
  "initialRunMode": "emit_backfill",
  "delivery": "webhook",
  "webhookUrl": "https://example.com/podcast-chart-hook",
  "maxChargeUsd": 3,
  "dryRun": false
}
```

`countries` accepts at most 20 unique two-letter codes. Each country is fetched with a timeout and bounded retry. `limit` is capped at 200.

### Output

The actor output contains `chartEntries`, `movementReports`, and `deliveryRows`. Raw rows keep legacy aliases (`name`, `artist`, and `collectionId`) and add the stable fields used by integrations.

#### Raw chart output

```json
{
  "actorName": "apple-podcast-chart-tracker",
  "rowType": "chart_rank",
  "billingEventName": "apify-default-dataset-item",
  "country": "us",
  "rank": 12,
  "showId": "123456",
  "showName": "Example Podcast",
  "artistName": "Example Network",
  "sourceUrl": "https://podcasts.apple.com/us/podcast/id123456",
  "fetchedAt": "2026-08-01T00:00:00.000Z",
  "collectionId": "123456",
  "name": "Example Podcast",
  "artist": "Example Network"
}
```

#### Movement report output

```json
{
  "actorName": "apple-podcast-chart-tracker",
  "rowType": "podcast_chart_movement_report",
  "billingEventName": "podcast-chart-movement-report",
  "monitorKey": "weekly-news-us-gb",
  "initialRun": false,
  "fetchedAt": "2026-08-01T00:00:00.000Z",
  "changedCount": 1,
  "newCount": 1,
  "droppedCount": 0,
  "changes": [
    {
      "changeType": "changed",
      "country": "us",
      "showId": "123456",
      "showName": "Example Podcast",
      "previousRank": 18,
      "currentRank": 12,
      "rankDelta": 6,
      "sourceUrl": "https://podcasts.apple.com/us/podcast/id123456"
    }
  ]
}
```

A baseline run emits zero `deliveryRows`. A later unchanged poll emits zero rows and zero charges. A later poll emits at most one movement report row for all observed changes. A failed source is not treated as a mass drop.

### Output fields

- Raw: `actorName`, `rowType`, `billingEventName`, `country`, `rank`, `showId`, `showName`, `artistName`, `sourceUrl`, `fetchedAt`, plus legacy aliases.
- Movement report: `monitorKey`, `changedCount`, `newCount`, `droppedCount`, `changes`, and source limitations.
- Envelope: `chartEntries`, `movementReports`, `deliveryRows`, `meta`, and delivery/state status in the final output file.

### Pricing and delivery

The existing raw path is unchanged: the default dataset event is used for each raw chart row. The movement event is named `podcast-chart-movement-report` and is sent through `Actor.pushData(row, eventName)` when the Apify SDK is available. The local test path never charges.

`maxChargeUsd` defaults to `$3`. The local safety estimate is `$0.003` per raw row and `$2.50` per movement report row; delivery stops before any row is sent when the estimate exceeds the cap.

`delivery=dataset` writes billable rows to the Apify default dataset. `delivery=webhook` sends the same output payload to the supplied HTTP(S) webhook first, then writes the billable rows to the default dataset. A non-2xx webhook response or dataset/PPE failure fails the run and prevents state commit. Webhook delivery does not replace dataset delivery.

### State and no-change behavior

State is isolated by `monitorKey`. State is saved only after webhook and dataset/PPE delivery succeeds. A state load or save failure fails closed; it never silently treats a missing state as a new baseline after a remote storage error.

- `baseline_only`: save the first successful snapshot with 0 rows and 0 charges.
- `emit_backfill`: emit one initial movement report for the current positions.
- Subsequent runs: emit only new, changed, or dropped positions; unchanged polls emit 0 rows and 0 charges.
- Set `emitRawRows=true` only when a monitor also needs the legacy raw rows; the charge cap still applies.

### Compliance guardrails

- Uses public Apple Podcasts/iTunes chart JSON only.
- No Apple logo, endorsement, private dashboard, or authenticated data is claimed.
- Rank movement is descriptive evidence, not a forecast, audience estimate, advertising guarantee, or provider approval.
- Unsupported storefronts produce a warning and are never interpreted as a mass drop from the saved baseline.

### See also

- [Apple Podcasts Scraper](https://apify.com/taroyamada/apple-podcast-scraper) for broad public show discovery.
- [Podcast Media Buyer Shortlist Scraper](https://apify.com/taroyamada/podcast-media-buyer-shortlist-scraper) for the next report-oriented workflow.

# Actor input Schema

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

ISO-3166-1 alpha-2 country codes, for example us, gb, jp, or de. At most 20 unique countries are fetched per run.

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

Optional Apple-internal genre ID, such as 1321 for News. Leave empty for the overall chart.

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

Number of chart entries per country, capped at 200.

## `monitorKey` (type: `string`):

Optional stable state namespace. Movement reports are enabled only when this is set and generateMovementReport is true.

## `generateMovementReport` (type: `boolean`):

When enabled with monitorKey, emit one report row only for new, changed, or dropped chart positions. Default false preserves the legacy raw-row path.

## `initialRunMode` (type: `string`):

baseline\_only saves the first snapshot with zero rows and zero charges. emit\_backfill reports the initial current positions once.

## `emitRawRows` (type: `boolean`):

Optional compatibility switch. In movement mode, also deliver the legacy chart rows. Leave false for zero-charge unchanged polls.

## `maxChargeUsd` (type: `number`):

Fail closed before delivery when the estimated raw and movement-event charge exceeds this cap. The movement report is estimated at $2.50 and raw rows at $0.003 each.

## `delivery` (type: `string`):

dataset writes billable rows to the Apify default dataset. webhook sends the same payload first and then also writes billable rows to the default dataset; a webhook failure stops the run before dataset delivery.

## `webhookUrl` (type: `string`):

Required for delivery=webhook. Only http and https URLs are accepted.

## `dryRun` (type: `boolean`):

Fetch and format the result without dataset, webhook, charge, or state delivery.

## Actor input object example

```json
{
  "countries": [
    "us"
  ],
  "genreId": "",
  "limit": 50,
  "monitorKey": "",
  "generateMovementReport": false,
  "initialRunMode": "baseline_only",
  "emitRawRows": false,
  "maxChargeUsd": 3,
  "delivery": "dataset",
  "dryRun": false
}
```

# 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 = {
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("taroyamada/apple-podcast-chart-tracker").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 = { "countries": ["us"] }

# Run the Actor and wait for it to finish
run = client.actor("taroyamada/apple-podcast-chart-tracker").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 '{
  "countries": [
    "us"
  ]
}' |
apify call taroyamada/apple-podcast-chart-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=taroyamada/apple-podcast-chart-tracker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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