# Apple Podcasts Scraper - Podcasts, Episodes & Reviews (`solidscrape/apple-podcasts-scraper`) Actor

Scrape Apple Podcasts without an API key: podcast details, episodes, and reviews by keyword or podcast ID, in any country. Export JSON/CSV/Excel.

- **URL**: https://apify.com/solidscrape/apple-podcasts-scraper.md
- **Developed by:** [Shahryar](https://apify.com/solidscrape) (community)
- **Categories:** News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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 Scraper – Podcasts, Episodes & Reviews API (No API Key)

Extract structured data from **Apple Podcasts** without an API key: full **podcast (show) details**, **episodes**, and **reviews** — by keyword or numeric podcast ID, in any country storefront. Export to **JSON, CSV, or Excel**.

This **Apple Podcasts scraper** is built for **podcast publishers, media researchers, marketers, and data teams** who want clean, reliable Apple Podcasts data without fighting HTML, browser automation, or rate limits. Use it as a key-free **Apple Podcasts API** to power discovery research, episode catalogs, and review analysis.

> Pairs with the **Apple App Store Scraper** and **Google Play Scraper** for full app + podcast intelligence across the Apple and Google ecosystems.

### What it does

- 🔎 **Search podcasts** by keyword and get every matching show.
- 🎙️ **Podcast details** – complete metadata by numeric podcast ID (lookup batches up to 100 IDs per call).
- 🎧 **Episodes** – title, release date, duration, audio URL, description, artwork, and more (optional).
- ⭐ **Reviews** – reviewer, star rating, title, text, helpful votes, and date from the public review feed (optional).
- 🌍 **Any country & language** – choose the storefront via `country`.
- 🧱 **Deeper back catalog (optional)** – when the iTunes episode cap (~200) isn't enough, the show's RSS feed is parsed for older episodes too (still bounded by `maxEpisodes`).
- 📤 **Export anywhere** – download as JSON, CSV, or Excel, or pull via the Apify API / dataset.

### Why this scraper

Uses Apple's **official iTunes endpoints** (search, lookup, the episode lookup, and the customer-reviews feed) — so it's **fast, reliable, and key-free**, with none of the blocking that plagues HTML scrapers. There is **no login and no API key** to manage. Episodes beyond Apple's cached cap are pulled straight from the show's own RSS feed, so you can reach deeper into the **podcast dataset** and pull older episodes (up to your `maxEpisodes` limit).

### How discovery works

Apple's Search API is **keyword-based** for podcasts. Provide `searchTerms` (each term is URL-encoded and sent to the search endpoint) and/or `podcastIds` (numeric collection IDs, batched up to 100 per lookup). There is no reliable genre-browse endpoint, so genre IDs are returned only as a passthrough output field — they are not used as an input filter.

### Example input

```json
{
  "searchTerms": ["true crime"],
  "podcastIds": ["1200361736"],
  "country": "us",
  "maxPodcastsPerSearch": 50,
  "maxItems": 200,
  "scrapeEpisodes": true,
  "maxEpisodes": 100,
  "scrapeFullEpisodeFeed": false,
  "scrapeReviews": true,
  "maxReviewsPerPodcast": 100,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### Example podcast output

```json
{
  "type": "podcast",
  "id": 1200361736,
  "name": "The Daily",
  "artist": "The New York Times",
  "artistId": 121664449,
  "url": "https://podcasts.apple.com/us/podcast/the-daily/id1200361736",
  "feedUrl": "https://feeds.simplecast.com/54nAGcIl",
  "genre": "Daily News",
  "genres": ["News", "Podcasts"],
  "genreIds": ["1489", "26"],
  "episodeCount": 2637,
  "rating": null,
  "ratingCount": null,
  "contentAdvisoryRating": "Clean",
  "explicit": "cleaned",
  "country": "USA",
  "releaseDate": "2026-06-20T09:00:00Z",
  "artwork": "https://.../600x600bb.jpg",
  "artworkUrl30": "https://.../30x30bb.jpg",
  "scrapedAt": "2026-06-20T12:00:00.000Z"
}
```

> Note: `rating` and `ratingCount` are frequently `null` for podcasts — Apple does not expose aggregate star ratings in the search/lookup responses. Per-review star ratings are available via `scrapeReviews`.

### Example episode output

```json
{
  "type": "episode",
  "podcastId": 1200361736,
  "podcastName": "The Daily",
  "id": 1000659912345,
  "title": "Friday's Episode",
  "episodeGuid": "gid://art19-episode-locator/V0/...",
  "releaseDate": "2026-06-20T09:00:00Z",
  "durationMs": 1620000,
  "description": "Today on the show...",
  "shortDescription": "Today on the show...",
  "audioUrl": "https://.../episode.mp3",
  "previewUrl": "https://.../episode.mp3",
  "fileExtension": "mp3",
  "contentType": "audio",
  "contentAdvisoryRating": "clean",
  "closedCaptioning": "none",
  "feedUrl": "https://feeds.simplecast.com/54nAGcIl",
  "artwork": "https://.../600x600bb.jpg",
  "trackViewUrl": "https://podcasts.apple.com/us/podcast/.../id1000659912345",
  "episodeNumber": null,
  "seasonNumber": null,
  "scrapedAt": "2026-06-20T12:00:00.000Z"
}
```

> `episodeNumber` and `seasonNumber` are `null` for episodes from the iTunes lookup; they are only populated for episodes pulled from the RSS feed (when `scrapeFullEpisodeFeed` is on). RSS-sourced episodes also carry an extra `"source": "rss"` field and have `id: null`, `shortDescription: null`, and `trackViewUrl: null` (no iTunes track data).

### Example review output

```json
{
  "type": "review",
  "podcastId": 1200361736,
  "reviewId": "1234567890",
  "userName": "podfan_99",
  "userUrl": "https://itunes.apple.com/us/reviews/id...",
  "title": "Essential listening",
  "text": "I start every morning with this show.",
  "score": 5,
  "voteSum": 3,
  "voteCount": 4,
  "updated": "2026-06-19T08:12:00-07:00",
  "scrapedAt": "2026-06-20T12:00:00.000Z"
}
```

### Output fields

Each item carries a `type` discriminator: `podcast`, `episode`, or `review`. Use it to split the mixed dataset into three clean tables (see the dataset views: **Podcasts**, **Episodes**, **Reviews**).

#### Podcast (`type: "podcast"`)

| Field | Type | Description |
|---|---|---|
| `type` | string | Always `"podcast"`. |
| `id` | number | iTunes collection ID (falls back to track ID). |
| `name` | string | Podcast (show) name. |
| `artist` | string | Publisher / author name. |
| `artistId` | number | Publisher iTunes artist ID. |
| `url` | string | Apple Podcasts page URL. |
| `feedUrl` | string | The show's real RSS feed URL. |
| `genre` | string | Primary genre name. |
| `genres` | array | All genre names. |
| `genreIds` | array | All genre IDs (passthrough only; not an input filter). |
| `episodeCount` | number | Track count reported by Apple. |
| `rating` | number | Aggregate star rating (often `null` for podcasts). |
| `ratingCount` | number | Number of ratings (often `null` for podcasts). |
| `contentAdvisoryRating` | string | Content advisory, e.g. `"Clean"` / `"Explicit"`. |
| `explicit` | string | Explicitness flag, e.g. `"cleaned"` / `"explicit"` / `"notExplicit"`. |
| `country` | string | Storefront country of the result (e.g. `"USA"`). |
| `releaseDate` | string | Latest episode date reported by Apple (ISO 8601). |
| `artwork` | string | Highest-resolution artwork available (600 → 100 → 60 px). |
| `artworkUrl30` | string | 30px thumbnail artwork. |
| `scrapedAt` | string | ISO 8601 timestamp of the scrape. |

#### Episode (`type: "episode"`)

| Field | Type | Description |
|---|---|---|
| `type` | string | Always `"episode"`. |
| `podcastId` | number | Parent podcast collection ID. |
| `podcastName` | string | Parent podcast name. |
| `id` | number | Episode track ID (`null` for RSS-sourced episodes). |
| `title` | string | Episode title. |
| `episodeGuid` | string | Episode GUID. |
| `releaseDate` | string | Publish date. |
| `durationMs` | number | Duration in milliseconds. |
| `description` | string | Episode notes / show notes. |
| `shortDescription` | string | Short description (`null` for RSS-sourced episodes). |
| `audioUrl` | string | Direct media URL. |
| `previewUrl` | string | Preview/media URL (usually identical to `audioUrl`). |
| `fileExtension` | string | Media file extension, e.g. `mp3` / `m4a` / `mp4`. |
| `contentType` | string | Media content type, e.g. `audio` / `video`. |
| `contentAdvisoryRating` | string | Episode advisory flag (e.g. `clean` / `explicit`). |
| `closedCaptioning` | string | Closed-captioning flag from the iTunes lookup. |
| `feedUrl` | string | The show's RSS feed URL. |
| `artwork` | string | Highest-resolution episode/show artwork (600 → 160 → 60 px). |
| `trackViewUrl` | string | Apple Podcasts episode URL (`null` for RSS-sourced episodes). |
| `episodeNumber` | number | Episode number — only populated from the RSS feed fallback. |
| `seasonNumber` | number | Season number — only populated from the RSS feed fallback. |
| `source` | string | Present and equal to `"rss"` only for episodes pulled from the RSS feed; absent for iTunes-lookup episodes. |
| `scrapedAt` | string | ISO 8601 timestamp of the scrape. |

#### Review (`type: "review"`)

| Field | Type | Description |
|---|---|---|
| `type` | string | Always `"review"`. |
| `podcastId` | number | Podcast the review belongs to. |
| `reviewId` | string | Review ID. |
| `userName` | string | Reviewer display name. |
| `userUrl` | string | Reviewer profile URL. |
| `title` | string | Review title. |
| `text` | string | Review body. |
| `score` | number | Star rating (1–5). |
| `voteSum` | number | Sum of helpful votes. |
| `voteCount` | number | Number of helpful votes cast. |
| `updated` | string | Review date (ISO 8601 with offset). |
| `scrapedAt` | string | ISO 8601 timestamp of the scrape. |

### Common use cases

- **Discovery & competitive research** – see which shows rank for your target keywords in any storefront.
- **Episode catalogs** – build a dataset of episodes with audio URLs, durations, and artwork.
- **Review analysis & sentiment** – export reviews and star ratings to JSON/CSV for sentiment and topic analysis.
- **Catalog monitoring** – track publish cadence, episode counts, and metadata over time.
- **Podcast data feeds** – power dashboards, BI tools, or your own database with a clean podcast dataset.
- **Lead & PR research** – find shows and publishers in a niche for outreach and advertising.

### Input reference

| Field | Type | Default | Description |
|---|---|---|---|
| `searchTerms` | array | – | Keywords to search Apple Podcasts (each must be non-empty). |
| `podcastIds` | array | – | Numeric iTunes collection IDs to scrape directly (batched 100 per lookup). |
| `country` | string | `us` | Two-letter storefront country code. |
| `maxPodcastsPerSearch` | integer | `50` | Max podcasts per search term (1–200). |
| `maxItems` | integer | `200` | Max podcasts in total (`0` = no limit). |
| `scrapeEpisodes` | boolean | `false` | Also fetch episodes for every podcast found. |
| `maxEpisodes` | integer | `100` | Cap on episodes per podcast (only when `scrapeEpisodes` is on). |
| `scrapeFullEpisodeFeed` | boolean | `false` | Parse the show's RSS feed for older episodes when the lookup cap (~200) isn't enough. Total per podcast is still bounded by `maxEpisodes`, so raise `maxEpisodes` to actually pull more. |
| `scrapeReviews` | boolean | `false` | Also scrape reviews for every podcast found. |
| `maxReviewsPerPodcast` | integer | `100` | Cap on reviews per podcast (only when `scrapeReviews` is on). |
| `proxyConfiguration` | object | Apify proxy | Proxy settings (the default Apify proxy is plenty). |

### FAQ

**Do I need an Apple/iTunes API key?** No. This Apple Podcasts scraper uses Apple's public iTunes endpoints — there is no API key and no login required.

**How do I find a podcast ID?** It's the number in the Apple Podcasts URL, e.g. `podcasts.apple.com/us/podcast/the-daily/id1200361736` → `1200361736`.

**Why are `rating` and `ratingCount` empty?** Apple does not expose aggregate star ratings for podcasts in the search/lookup responses. Enable `scrapeReviews` to get per-review star ratings (`score`) instead.

**How many episodes can I get?** The iTunes lookup returns up to ~200 most-recent episodes — and for some shows fewer, because it reflects Apple's cached copy of the feed. To reach older episodes, enable `scrapeFullEpisodeFeed` (which parses the show's own RSS feed) **and** raise `maxEpisodes` above the lookup count — the total per podcast is always capped by `maxEpisodes`, so leave it at the default 100 and the RSS fallback won't add anything.

**How many reviews can I get?** Apple's public review feed exposes up to ~500 most-recent reviews per podcast (about 10 pages × ~50), per storefront.

**Can I scrape other countries?** Yes — set `country` to `gb`, `de`, `jp`, `ca`, `au`, etc. The storefront also affects the review feed and availability.

**How does pagination work?** Search results are capped per term by `maxPodcastsPerSearch` (Apple's max is 200). Reviews are auto-paginated through the customer-reviews feed up to 10 pages (the ~500-review ceiling) and your `maxReviewsPerPodcast` cap; episodes come from the iTunes lookup and, optionally, the show's RSS feed for older episodes — always bounded by `maxEpisodes`. You never manage page tokens manually.

**Do I need a proxy?** Apple's iTunes endpoints are open and rarely block, so the default Apify proxy is sufficient. You can supply your own `proxyConfiguration` if you prefer.

**What export formats are supported?** Results are stored in an Apify dataset and can be exported to **JSON, CSV, or Excel**, or pulled programmatically via the Apify API.

**Are new episodes always present?** Episodes published on Apple Podcasts can lag in the iTunes API due to a known sync delay, so "most recent" is best-effort. The RSS fallback (`scrapeFullEpisodeFeed`) reflects the publisher's feed directly.

***

Looking for app data too? Pair this with the **Apple App Store Scraper** and **Google Play Scraper** for end-to-end app + podcast intelligence.

# Actor input Schema

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

Keywords to search Apple Podcasts, e.g. "true crime", "daily news". Each term must be non-empty (Apple requires a search term). Leave empty if you only use Podcast IDs.

## `podcastIds` (type: `array`):

Numeric iTunes collection IDs to scrape directly, e.g. "1200361736" (the id in podcasts.apple.com/podcast/id1200361736). Batched 100 per lookup call. Leave empty if you only use search terms.

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

Two-letter storefront country code (e.g. us, gb, de, jp, ca, au). Affects availability, language, and the review feed path.

## `maxPodcastsPerSearch` (type: `integer`):

Maximum podcasts to return per search term (Apple allows up to 200).

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

Maximum number of podcasts to return in total across all search terms and IDs. Set 0 for no limit.

## `scrapeEpisodes` (type: `boolean`):

If enabled, also fetch episodes for every podcast found (title, date, audio URL, duration, description, artwork).

## `maxEpisodes` (type: `integer`):

Only used when 'Scrape episodes' is on. The iTunes lookup returns at most ~200 most-recent episodes. This value caps the total episodes per podcast (including any from the RSS fallback); raise it and enable 'Scrape full episode feed (RSS)' to reach older episodes.

## `scrapeFullEpisodeFeed` (type: `boolean`):

When on and 'Max episodes per podcast' exceeds what the iTunes lookup returns (~200), the podcast's RSS feed (feedUrl) is parsed for older episodes too, up to your 'Max episodes per podcast' limit. RSS-sourced episodes add episodeNumber/seasonNumber and source="rss" but have no iTunes trackId.

## `scrapeReviews` (type: `boolean`):

If enabled, also scrape reviews for every podcast found (reviewer, star rating, title, text, helpful votes, date).

## `maxReviewsPerPodcast` (type: `integer`):

Only used when 'Scrape reviews' is on. Apple's public review feed exposes up to ~500 most-recent reviews per podcast (about 10 pages).

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

Apple's iTunes endpoints are open and rarely block; the default Apify proxy is plenty.

## Actor input object example

```json
{
  "searchTerms": [
    "true crime",
    "daily news"
  ],
  "podcastIds": [
    "1200361736"
  ],
  "country": "us",
  "maxPodcastsPerSearch": 50,
  "maxItems": 200,
  "scrapeEpisodes": true,
  "maxEpisodes": 100,
  "scrapeFullEpisodeFeed": false,
  "scrapeReviews": true,
  "maxReviewsPerPodcast": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `podcasts` (type: `string`):

No description

## `episodes` (type: `string`):

No description

## `reviews` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "true crime"
    ],
    "podcastIds": [],
    "country": "us",
    "maxPodcastsPerSearch": 50,
    "maxItems": 200,
    "scrapeEpisodes": true,
    "maxEpisodes": 100,
    "scrapeFullEpisodeFeed": false,
    "scrapeReviews": true,
    "maxReviewsPerPodcast": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidscrape/apple-podcasts-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 = {
    "searchTerms": ["true crime"],
    "podcastIds": [],
    "country": "us",
    "maxPodcastsPerSearch": 50,
    "maxItems": 200,
    "scrapeEpisodes": True,
    "maxEpisodes": 100,
    "scrapeFullEpisodeFeed": False,
    "scrapeReviews": True,
    "maxReviewsPerPodcast": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("solidscrape/apple-podcasts-scraper").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 '{
  "searchTerms": [
    "true crime"
  ],
  "podcastIds": [],
  "country": "us",
  "maxPodcastsPerSearch": 50,
  "maxItems": 200,
  "scrapeEpisodes": true,
  "maxEpisodes": 100,
  "scrapeFullEpisodeFeed": false,
  "scrapeReviews": true,
  "maxReviewsPerPodcast": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call solidscrape/apple-podcasts-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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