# App Store & Podcast Data - 175 Apple storefronts (`canonrow/app-store-podcast-scraper`) Actor

Apps, podcasts, music and books from Apple's own public API. One row per item per country, so you can compare price, rating and availability across storefronts in a single run.

- **URL**: https://apify.com/canonrow/app-store-podcast-scraper.md
- **Developed by:** [Canonrow](https://apify.com/canonrow) (community)
- **Categories:** Developer tools, Social media, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

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 & Podcast Data — across 175 Apple storefronts

Apps, podcasts, music, books and films straight from **Apple's own public catalogue API**. No key, no login, no headless browser, no proxies.

The point of difference is in the shape of the output: **one row per item per country**.

### Why per-country matters

Apple runs a separate storefront for every country, and the same app is not the same product in each one. Ask for Spotify in three storefronts and you get three genuinely different rows:

| Country | Name | Currency | Rating |
|---|---|---|---|
| us | Spotify: Music and Podcasts | USD | 4.78 |
| jp | Spotify: 音楽とポッドキャスト | JPY | 4.58 |
| th | Spotify: Music and Podcasts | THB | 4.81 |

Localised names, local pricing, local ratings — and sometimes no row at all, because the item is not sold there. Tools that query a single storefront cannot show you any of this. This one crosses every query with every country you ask for, in one run.

**And when an item is missing from a storefront, that is reported as a finding, not swallowed as an error.** The `SUMMARY` record lists every item/country pair that came back empty, which is exactly what you want when you are checking where a competitor has and has not launched.

### What you can ask for

| Input | Use it when |
|---|---|
| `terms` | You want to see what ranks for a search, e.g. `meditation`, `habit tracker` |
| `ids` | You are tracking specific items, e.g. `324684580`. The right way to follow one app across countries |
| `bundleIds` | You know the app but not its Apple ID, e.g. `com.spotify.client` |

Set `kind` to `app`, `ipadApp`, `macApp`, `podcast`, `song`, `album`, `ebook`, `movie` or `audiobook`.

Set `countries` to any list of two-letter codes, or the single value `all` for the 30 largest storefronts.

### Podcasts get a second hop

Podcast results include the show's RSS `feedUrl`. Turn on `includePodcastEpisodes` and the Actor follows that feed and returns individual episodes as extra rows — title, publish date, duration, direct audio URL, episode and season numbers. Podcast RSS is an open format its publishers intend to be read, so this stays as reliable as the catalogue lookup itself.

### Example input

```json
{
  "ids": ["324684580"],
  "kind": "app",
  "countries": ["us", "gb", "de", "jp", "th", "br"],
  "includeDescription": false
}
```

### Example output

```json
{
  "kind": "app",
  "country": "jp",
  "id": "324684580",
  "bundleId": "com.spotify.client",
  "name": "Spotify: 音楽とポッドキャスト",
  "artist": "Spotify",
  "price": 0,
  "currency": "JPY",
  "isFree": true,
  "rating": 4.58,
  "ratingCount": 1043221,
  "primaryGenre": "Music",
  "currentVersion": "9.0.20",
  "currentVersionReleaseDate": "2026-08-11T09:12:00Z",
  "minimumOsVersion": "16.0",
  "url": "https://apps.apple.com/jp/app/id324684580",
  "fetchedAt": "2026-08-20T04:20:11.512Z"
}
```

### Pricing

Pay per row delivered. A query that returns nothing costs nothing.

### Honest limits

- Apple publishes a rate limit of roughly 20 calls per minute. The Actor paces itself and backs off automatically when the API pushes back, so a very wide job (many terms × many countries) takes minutes rather than seconds. That is the API's constraint, not a choice.
- Search results reflect Apple's own ranking for that storefront on the day you run it. They are not a chart position and Apple does not publish one through this API.
- `ratingCount` is the lifetime count for that storefront. Apple does not expose a review history, so trends have to be built by running on a schedule and keeping the rows.
- Episode data comes from the publisher's RSS feed. If a publisher truncates their feed to recent episodes, that is all anyone can read.

# Actor input Schema

## `terms` (type: `array`):

Words to search Apple's catalogue for, e.g. "meditation" or "budget tracker". Each term is searched separately in every storefront you list below.

## `ids` (type: `array`):

Exact App Store or podcast IDs, e.g. 324684580 (Spotify). More precise than searching, and the right way to track the same item across countries.

## `bundleIds` (type: `array`):

iOS bundle identifiers, e.g. com.spotify.client. Useful when you know the app but not its numeric Apple ID.

## `kind` (type: `string`):

Which part of Apple's catalogue to query.

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

Two-letter country codes, e.g. us, gb, jp, th. Every query runs once per storefront and each result is returned as its own row, so price, rating, localised name and availability can be compared side by side. Use the single value "all" for the 30 largest storefronts.

## `limitPerTerm` (type: `integer`):

How many results each search term returns in each storefront. Ignored for ID and bundle ID lookups, which return one item each.

## `includePodcastEpisodes` (type: `boolean`):

For podcasts, follow the RSS feed Apple points to and return individual episodes as extra rows. Only applies when the results are podcasts.

## `episodesPerShow` (type: `integer`):

How many recent episodes to return per podcast when the option above is on.

## `includeDescription` (type: `boolean`):

Keep the full store description on each row. Turn off for a lighter dataset.

## `concurrency` (type: `integer`):

Apple publishes a rate limit of roughly 20 calls per minute. The Actor paces itself and backs off automatically, so raise this only if you are running small jobs.

## Actor input object example

```json
{
  "terms": [
    "meditation",
    "habit tracker"
  ],
  "kind": "app",
  "countries": [
    "us",
    "gb",
    "jp",
    "th"
  ],
  "limitPerTerm": 25,
  "includePodcastEpisodes": false,
  "episodesPerShow": 20,
  "includeDescription": true,
  "concurrency": 4
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per item per storefront, plus podcast episode rows when requested.

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

Storefronts queried, rows delivered, and every item that is not sold in a given country.

## `browse` (type: `string`):

Open the results table in Apify Console.

# 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 = {
    "terms": [
        "meditation",
        "habit tracker"
    ],
    "countries": [
        "us",
        "gb",
        "jp",
        "th"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("canonrow/app-store-podcast-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 = {
    "terms": [
        "meditation",
        "habit tracker",
    ],
    "countries": [
        "us",
        "gb",
        "jp",
        "th",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("canonrow/app-store-podcast-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 '{
  "terms": [
    "meditation",
    "habit tracker"
  ],
  "countries": [
    "us",
    "gb",
    "jp",
    "th"
  ]
}' |
apify call canonrow/app-store-podcast-scraper --silent --output-dataset

```

## MCP server setup

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