# Podcast Search, Episodes & Charts API (`insight.solutions/podcast-api`) Actor

Scrape podcasts as data. One row per episode: title, show notes, audio URL, duration, episode number, publish date, GUID. Plus one row per show — feed URL, categories, artwork, owner email — Apple's Top Shows charts by country, and keyword search. No API key, no login.

- **URL**: https://apify.com/insight.solutions/podcast-api.md
- **Developed by:** [Insight Solutions](https://apify.com/insight.solutions) (community)
- **Categories:** News, Marketing, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.24 / 1,000 episode returneds

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

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

## Podcast Search, Episodes & Charts API

**Every episode of any podcast, as a flat table.** Give this Actor an Apple Podcasts link, a bare Apple ID, an RSS feed URL or just a show's name — mixed together, in any order — and get one row per episode: the title, the full show notes, the audio file URL, the duration in seconds, the episode number, the publish date and the GUID. Each show also gets a row of its own: feed URL, categories, language, artwork, episode count, first and latest episode dates, and the publisher's public contact address. Add a country code and you get Apple's **Top Shows** chart; add a keyword and you get every show Apple can find for it.

No API key. No login. No podcast-host account. **$0.40 per 1,000 episodes, proxy included**, shows that could not be read are free, and a run that returns nothing costs nothing at all.

### Try it in 30 seconds

```json
{
  "podcasts": [
    "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110"
  ],
  "maxEpisodesPerPodcast": 50,
  "episodeSource": "rss",
  "country": "us"
}
```

One Apple Podcasts link, the fifty most recent episodes. A bare ID (`1545953110`), a feed URL (`https://feeds.megaphone.fm/hubermanlab`) and the plain name `Huberman Lab` all reach the same show.

Want the market rather than one show? `{"charts": ["us", "gb"], "chartSize": 50}`. Want a list? `{"searchQueries": ["true crime"], "maxResultsPerQuery": 200}`.

### What comes back

One `episode` row per episode:

```jsonc
{
  "ok": true,
  "rowType": "episode",              // "episode" | "podcast" | "chart" | "diagnostic"

  "appleId": "1545953110",           // the join key across every row of this show
  "podcastTitle": "Huberman Lab",
  "title": "How Mitochondria Control Your Metabolism | Dr. Jared Rutter",

  "episodeId": "ee502b96-aa66-11f1-ad04-5ff2fd270a25",   // the feed's GUID — dedupe on this
  "publishedAt": "2026-09-07T08:00:00.000Z",
  "durationSec": 7426,               // 2 h 3 m, from itunes:duration in any of its 3 formats
  "audioUrl": "https://traffic.megaphone.fm/SCIM5888935664.mp3",
  "audioType": "audio/mpeg",
  "audioSizeBytes": null,            // this host sends length="0", which is "not stated"
  "episodeNumber": 297,
  "seasonNumber": null,
  "episodeType": "full",             // "full" | "trailer" | "bonus"
  "explicit": false,

  "description": "Dr. Jared Rutter, PhD, Professor of Biochemistry at the University of Utah and Howard Hughes Medical Institute Investigator, is a leading expert on mitochondria…",
  "descriptionHtml": null,           // the same notes with their links, when you ask for them
  "link": "https://www.hubermanlab.com/episode/how-mitochondria-control-your-metabolism-jared-rutter",
  "transcriptUrl": null,             // when the feed declares one (podcast:transcript)

  "feedUrl": "https://feeds.megaphone.fm/hubermanlab",
  "url": "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110?uo=4",
  "position": 2,                     // 1-based, newest first
  "country": "us",

  "error": null,
  "errorType": null,
  "scrapedAt": "2026-09-10T15:04:05.487Z",
  "source": "rss",                   // "rss" | "apple" | "both"
  "sourceUrl": "https://feeds.megaphone.fm/hubermanlab"
}
```

And one `podcast` row per show, written before its episodes:

```jsonc
{
  "ok": true,
  "rowType": "podcast",
  "appleId": "1545953110",
  "podcastTitle": "Huberman Lab",
  "title": "Huberman Lab",
  "author": "Scicomm Media",
  "ownerEmail": "podcast-verification@scicommedia.com",   // from the feed; no Apple endpoint has it
  "feedUrl": "https://feeds.megaphone.fm/hubermanlab",
  "url": "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110?uo=4",
  "websiteUrl": "https://www.hubermanlab.com",
  "language": "en",
  "categories": ["Health & Fitness", "Science", "Life Sciences"],   // the feed's own tree
  "genres": ["Health & Fitness", "Podcasts", "Science", "Life Sciences"],  // Apple's
  "explicit": false,
  "podcastType": "episodic",
  "episodeCount": 440,
  "latestEpisodeAt": "2026-09-10T08:00:00.000Z",
  "firstEpisodeAt": "2020-12-21T05:22:00.000Z",
  "copyright": "Copyright © 2021-2025 Scicomm Media LLC",
  "artworkUrl": "https://megaphone.imgix.net/podcasts/042e6144-725e-11ec-a75d-c38f702aecad/image/…jpg",
  "rating": null,                    // 4.8 when includeRating is on — one extra request per show
  "ratingCount": null,
  "resolvedFrom": "apple-id",        // "apple-id" | "feed-url" | "search" | "chart"
  "source": "both"
}
```

A `chart` row is one position in a country's Top Shows chart — `rank`, `podcastTitle`, `author`, `genres`, `appleId`, `url`, `artworkUrl` — and with `includeChartDetails` it also carries the show's `feedUrl`, `episodeCount` and `latestEpisodeAt`.

Every row carries the same columns, so podcasts, episodes, charts and diagnostics export as one rectangular table.

### Use cases

- **Feed monitoring at scale.** A scheduled run over a few hundred shows, keyed on `episodeId`, gives you every new episode within the hour — with the audio URL already resolved, ready to hand to a transcription pipeline.
- **Building a podcast database.** `searchQueries` with a `genreId` returns 200 shows a query, each with its feed URL, categories, artwork and episode count. That is a directory, not a page of search results.
- **Chart tracking.** `charts: ["us","gb","de","au"]` on a daily schedule is a time series of who is climbing, in four markets, for a fraction of a cent a day.
- **Competitive and publishing analysis.** `firstEpisodeAt`, `latestEpisodeAt` and `episodeCount` on one row tell you cadence and whether a show has quietly stopped. Compare `durationSec` distributions across a genre and you can see a format changing.
- **Ad and sponsorship research.** Show notes are where the sponsor links live. Turn on `includeDescriptionHtml` and the anchors come through with them.
- **Content and LLM pipelines.** Titles plus show notes plus duration plus publish date, as a flat array — a labelled corpus without the labelling. `transcriptUrl` points at a transcript when the publisher declares one.
- **Podcast guest and outreach research.** `ownerEmail` is the address the publisher put in their own feed for exactly this purpose, and `websiteUrl` is where the rest of their contact details are.

### How it works, and why it keeps working

There is no single podcast API, because a podcast is not one thing: the *catalogue* is Apple's, and the *episodes* are the publisher's, served from their own feed. This Actor reads all three public surfaces and merges them.

| Source | What it reads | Shape |
|---|---|---|
| **iTunes search** | `itunes.apple.com/search?media=podcast&entity=podcast` | JSON. Shows by keyword or name, with feed URL, genres and artwork |
| **iTunes lookup** | `itunes.apple.com/lookup?id=…&entity=podcastEpisode` | JSON. One show, plus up to 200 episodes |
| **Apple charts** | `rss.marketingtools.apple.com/api/v2/<cc>/podcasts/top/<n>/podcasts.json` | JSON. Top Shows for a country, 25/50/100 deep |
| **The show's RSS feed** | Whatever address Apple (or you) gives — Megaphone, Simplecast, WordPress, anything | XML. The full catalogue: show notes, audio URLs, GUIDs, durations, episode numbers |
| **Apple Podcasts page** *(opt-in)* | The show's public web page | HTML with a schema.org block. The only place Apple publishes a star rating |

Three things catch naive scrapers here, and all three are handled:

**Apple answers with `content-type: text/javascript`.** The body is JSON. A client that trusts the header sees a script and gives up.

**Podcast feeds are large and irregular.** A show with a long back catalogue is a multi-megabyte XML document — the largest one this was built against is 4.4 MB — and no two hosting platforms agree on how to write it. Durations arrive as `2138`, `43:57` and `5:21:57`. "Explicit" arrives as `no`, `false` and `notExplicit`. Show notes hide in `<description>`, `<content:encoded>` or `<itunes:summary>`, wrapped in CDATA, with entities encoded twice. One host writes `length="0"` for every enclosure. The parser here is a scanner built for exactly this shape — no XML library, no DOM — and it reads a 4.4 MB feed in about 20 ms.

**Apple's copy of a feed address goes stale.** When the feed does not answer, or answers with a web page instead of XML, the run **falls back to Apple's episode list** for that show and files a free `feed-unavailable` row saying why the notes are shorter than usual. You get the episodes either way.

Underneath: **Apify proxy** for Apple's endpoints, one pinned session per parallel worker. **RSS feeds are fetched directly first** — a feed is published for machines and lives on a CDN, and a multi-megabyte feed that takes a fraction of a second direct can take a minute or more through a shared exit — with the proxy as the fallback for the odd host that refuses Apify's own address. When an endpoint refuses an exit IP — HTTP 429, HTTP 403, an empty body, HTML where XML belongs — that session is retired and **the same request goes out once more from a different address**. Retrying on an address that was just refused only deepens the block, so it is never done. If the second address is refused too, the job stops, **keeps every row it already delivered**, and files one free `blocked` row saying where it stopped. Requests within one job are spaced 250–600 ms apart.

### How it compares

- **Episodes come from the feed, not from Apple.** Apple's lookup stops at 200 episodes and hands you a flattened description with no episode number, no season, no per-episode artwork and no explicit flag. The feed has all of it and no ceiling. This Actor reads the feed by default and uses Apple as the *fallback*, which is the opposite of most tools that touch this data.
- **Four sources, one schema.** A search hit, a charting show, a feed you pasted and an Apple link all produce the same columns, so mixing them is a filter rather than a reconciliation project.
- **Failures are free and legible.** A dead feed, a show Apple has never heard of, an empty search or a block produce a diagnostic row with an `errorType` you can branch on — and no charge. A run that returns nothing at all finishes **FAILED** with the reason in its status message, never a green run containing an apology.
- **A partial run is kept, not thrown away.** Hit `maxRunSecs` or your charge ceiling halfway through a chart and you keep the ranks already written.
- **Honest about what is not here.** No transcripts, no download or listener numbers, no Spotify — see *Limits* below, in detail, rather than as a footnote.
- **No login, ever.** No Apple ID, no host account, no cookie jar, no session token. Public endpoints only, which is also why it runs under Apify's **limited permissions**.

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `podcasts` | array of strings | prefilled with one | Apple Podcasts links, bare Apple IDs, RSS feed URLs, or show names. Prefix with `feed:`, `id:` or `name:` to be explicit. Duplicates are read, and billed, once |
| `maxEpisodesPerPodcast` | integer | `50` | Episodes per show, newest first. `0` = every episode in the feed. The feed is one request whatever you ask for |
| `episodeSource` | `rss` | `apple` | `rss` | The show's own feed (everything, no cap) or Apple's lookup (fewer fields, capped at 200, works without a feed). RSS falls back to Apple automatically |
| `includeDescriptionHtml` | boolean | `false` | Add `descriptionHtml` — the show notes with their links and markup intact |
| `includeRating` | boolean | `false` | Add `rating` and `ratingCount`. One extra ~600 KB page request per show, which is why it is off |
| `searchQueries` | array of strings | `[]` | Keyword search. One `podcast` row per hit, no episodes unless you ask |
| `maxResultsPerQuery` | integer | `25` | Hits per query. Apple's ceiling is **200** |
| `genreId` | string | — | Restrict searches to one Apple genre — `1462` History, `1488` True Crime, `1489` News, `1533` Science, `1318` Technology |
| `includeEpisodesForSearchHits` | boolean | `false` | Also read every search hit's feed. One request per hit plus a feed download each |
| `charts` | array of strings | `[]` | Two-letter country codes → Apple's Top Shows chart as ranked rows |
| `chartSize` | `25` | `50` | `100` | `50` | How deep the chart goes. Apple serves exactly these three |
| `includeChartDetails` | boolean | `false` | Look each charting show up for its feed URL and episode count. **One extra request per show** |
| `country` | string | `us` | Apple storefront. Catalogue, search ranking and charts are all per-country; RSS feeds are global |
| `maxConcurrency` | integer | `3` | Shows, queries or charts in parallel. Each worker keeps its own proxy session |
| `maxRunSecs` | integer | `240` | Whole-run wall-clock budget. When it runs out the Actor keeps what it has and files a free diagnostic row for each entry it never reached |
| `proxyConfiguration` | object | Apify datacenter | Apple and the big podcast hosts answer datacenter addresses happily, so the cheap proxy is the default |

### Output reference

| Column | On which rows | What it is |
|---|---|---|
| `ok`, `rowType` | all | `true` plus `podcast` / `episode` / `chart`, or `false` plus `diagnostic` |
| `input` | all | The entry this row came from, as you supplied it |
| `appleId` | all | Apple's collection ID — the join key between a show and its episodes |
| `podcastTitle` | all | The show's name, so a mixed sheet reads without a join |
| `title` | all | The show's name, or the episode's title |
| `feedUrl`, `url`, `websiteUrl` | podcast, episode | The RSS feed, the Apple page, the publisher's own site |
| `author`, `ownerEmail` | podcast, chart | Publisher name; the contact address from the feed's `itunes:owner` |
| `description`, `descriptionHtml` | podcast, episode | Show notes as text (clipped to 5,000 chars), and with markup when asked |
| `language`, `categories`, `genres`, `keywords`, `explicit`, `copyright`, `podcastType` | podcast | The feed's declarations, plus Apple's genre list |
| `episodeCount`, `latestEpisodeAt`, `firstEpisodeAt` | podcast | Catalogue size and date range — the whole feed, not just the rows returned |
| `rating`, `ratingCount` | podcast | Stars and how many, when `includeRating` is on |
| `artworkUrl` | all | Show art, or the episode's own where a feed sets one |
| `episodeId`, `appleEpisodeId` | episode | The feed's GUID (dedupe on this) and Apple's numeric track ID |
| `publishedAt`, `durationSec`, `episodeNumber`, `seasonNumber`, `episodeType` | episode | When, how long, and where it sits in the run of the show |
| `audioUrl`, `audioType`, `audioSizeBytes` | episode | The enclosure: the audio file itself, its MIME type and declared size |
| `link`, `transcriptUrl` | episode | The episode's web page; a declared transcript's address |
| `rank` | chart | Position in the country's Top Shows chart, 1 being the top |
| `position` | episode | 1-based order within the show, newest first |
| `resolvedFrom`, `source`, `sourceUrl` | all | How the show was identified, which surface the row came from, and the exact address |
| `error`, `errorType` | diagnostic | What went wrong, and a type to branch on |
| `country`, `scrapedAt` | all | Storefront, and when the row was written |

`errorType` is one of `not-found`, `no-results`, `feed-unavailable`, `invalid-input`, `blocked`, `timeout`.

### Pricing

**$0.40 per 1,000 episodes.** Pay-per-event, with proxy already inside that number — there is no separate proxy line on your bill for this Actor.

| Event | What triggers it | FREE | Starter | Scale | Business |
|---|---|---|---|---|---|
| **Episode returned** *(primary)* | One episode row written to your dataset | $0.0004 | $0.0004 | $0.00032 | $0.00024 |
| Podcast record returned | One `podcast` row — the show, merged from Apple and its feed | $0.0015 | $0.0015 | $0.0015 | $0.0015 |
| Chart entry returned | One position in a country's Top Shows chart | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
| Run started | Once per run, after the first paid row | $0.001 | $0.001 | $0.001 | $0.001 |

**Worked example.** 20 shows, 50 newest episodes each, one show's feed dead (its episodes come from Apple instead), one name misspelled beyond rescue:

- 19 shows × 50 episodes + 50 from Apple's fallback = 1,000 episodes × $0.0004 = **$0.40**
- 20 podcast rows × $0.0015 = **$0.03**
- 1 run start = **$0.001**
- 1 unresolvable name, 1 dead feed = **$0.00** (free diagnostic rows)
- **Total: $0.431**

**Chart tracking example.** Four countries, Top 50, no enrichment: 200 chart rows × $0.0005 + $0.001 = **$0.101 per run**, about **$3.03 a month** daily.

**Back-catalogue example.** One show with 440 episodes, `maxEpisodesPerPodcast: 0`: 440 × $0.0004 + $0.0015 + $0.001 = **$0.1785**, from two requests.

What you are never charged for: a show that does not exist, a feed that will not answer, an entry that was not a podcast, a search that matched nothing, a show the run never reached before `maxRunSecs`, or a request the endpoint blocked. If a whole run comes back empty it finishes FAILED and bills **nothing at all**, start fee included.

Set `ACTOR_MAX_TOTAL_CHARGE_USD` on a run and the Actor stops fetching once the ceiling is in sight, rather than handing you rows it cannot bill or billing you for rows it cannot hand over. It finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.

### Limits, and the ones that might bite

**No transcripts.** This Actor returns `transcriptUrl` when a publisher declares one in their feed, and nothing more — it does not download or generate transcripts. Most feeds declare none. If the show is also published on YouTube, our [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) will give you the spoken words from there.

**Apple's lookup caps at 200 episodes**, so `episodeSource: "apple"` cannot return more than that however large the show. The RSS feed has no such cap and is the default for exactly this reason. What a feed contains is the publisher's choice: most carry the whole catalogue, some trim to the last hundred or so, and nothing outside a feed can be recovered from it.

**Apple ratings are per-show and opt-in.** `rating` and `ratingCount` come from the show's Apple Podcasts *page*, not from any API, and cost one extra request each — so they are null unless you set `includeRating: true`. There are no individual podcast *reviews* here at all: Apple does not publish them in a machine-readable form.

**No listener or download numbers.** Nobody publishes them. Download counts live in the publisher's own hosting dashboard, and any tool that claims to have them for arbitrary shows is estimating.

**Apple only — no Spotify, YouTube or Amazon catalogue.** The episodes are from the publisher's feed, which is the same feed every app reads, so the episode data is platform-neutral. The catalogue, the charts and the search ranking are Apple's.

**Feeds disagree with each other, and the nulls are honest.** Of the four real feeds this was built against: one sends `length="0"` for every enclosure, so `audioSizeBytes` is null there; one carries no per-episode artwork; one declares no `itunes:type`; none of them numbers its seasons; and only some episodes of most shows carry an `itunes:episode` number — trailers and bonus material usually do not. A null means the publisher did not say.

**Episode order is feed order.** Every real podcast feed serves newest first — that is what podcast apps expect — and `position` reflects the order the feed was in. A publisher who reorders their feed will reorder your rows.

**Charts are Top Shows only**, at 25, 50 or 100, per country. Apple's chart feed has no per-genre chart and no historical data: each run captures the chart as it stands.

**`resolvedFrom: "search"` means a guess was made.** A show name is resolved to Apple's first hit. For a distinctive name that is right; for "The Daily" there are several, and pasting the Apple link removes the ambiguity. The column is there so you can spot it.

**The upstream format may change.** Apple's endpoints and the podcast hosting platforms change their output without notice — that is true of every tool that reads this data, including the ones that do not say so. When a shape changes, rows stop arriving and you get free `blocked` or `feed-unavailable` diagnostic rows rather than quietly wrong data, and a run that returns nothing bills nothing.

**Rate and reliability.** Requests go out through proxy sessions pinned per worker, one rotation per block, and a 250–600 ms pause between requests of the same job. Three jobs in parallel is the default because feeds are large; raising `maxConcurrency` speeds a long list up and raises memory use with it.

### Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with **limited permissions**, uses **pay-per-event** pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The **Integrations** tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

```bash
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~podcast-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"podcasts":["https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110"],"maxEpisodesPerPodcast":50}'
```

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/podcast-api").call(run_input={
    "podcasts": ["Huberman Lab", "https://feeds.simplecast.com/Sl5CSM3S"],
    "maxEpisodesPerPodcast": 50,
    "episodeSource": "rss",
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["rowType"] == "episode":
        print(row["publishedAt"], row["durationSec"], row["title"])
```

### FAQ

**Do I need an account with Apple or with a podcast host?**
No. Every source here is public: Apple's search, lookup and chart endpoints, and the RSS feed that any podcast app reads.

**How do I deduplicate between runs?**
On `episodeId`, which is the feed's own GUID and the same identifier podcast apps use. An incremental pipeline is an upsert keyed on `(appleId, episodeId)`. Apple's episode records carry the same GUID, so rows from the two sources join cleanly.

**Can I get every episode of a show?**
Yes — `maxEpisodesPerPodcast: 0` returns every item in the feed, which for most shows is the whole catalogue. It is still one request.

**Why is `audioSizeBytes` null?**
Because that feed sends `length="0"` in its enclosure tag, which several large hosts do. Zero is not a file size; null is the honest reading.

**Why did I get fewer episodes than I asked for?**
The feed had fewer, or you used `episodeSource: "apple"`, which Apple caps at 200. The `episodeCount` column tells you how many the show actually has.

**What does `source: "both"` mean?**
That the podcast row was merged: Apple supplied the ID, the store URL and the genre list, and the feed supplied the title, description, categories, artwork, owner email and date range. Where both had a value, the feed wins for anything the publisher controls.

**Can I search inside episode titles or show notes?**
Not at the source — Apple's search matches shows, not episodes. Fetch the show's episodes and filter locally; one feed request gives you every episode to search through.

**Does `country` change the episodes?**
No. RSS feeds are global; the episodes are identical wherever you read them from. `country` changes Apple's catalogue, search ranking and charts.

**What happens if one show fails?**
The others still run. The failed one produces a free diagnostic row and the run finishes `SUCCEEDED`. If *every* entry fails, the run finishes `FAILED` and you are billed nothing at all.

**Is the data fresh?**
Live. Every run reads Apple and the feeds at that moment; nothing is cached.

### Legal and data-protection notes

- **Public feeds and public endpoints only.** An RSS feed is published precisely so that software will read it; Apple's search, lookup and chart endpoints are the ones its own web player uses. The Actor never logs in, never accepts cookies or session tokens, and never takes an API key belonging to anyone else.
- **`ownerEmail` is a published business contact.** It is the address the publisher put in their own feed so that directories can verify ownership. In most jurisdictions a business contact address is still personal data when it identifies a person: have a lawful basis before you use it for outreach, honour opt-outs, and check the marketing rules where you and the recipient are.
- **Episode content belongs to its publisher.** Titles, show notes and audio are copyrighted works, and `copyright` on the podcast row is often where the publisher states their terms. Indexing, analysis and linking are the ordinary uses and are what this is built for; republishing is your call and your responsibility.
- **Audio URLs are not a licence.** `audioUrl` is the address a podcast app would fetch. Downloading it at scale is a cost to the publisher's host and may breach their terms; this Actor never downloads audio.
- **Not affiliated with Apple Inc. or with any podcast, publisher or hosting platform whose content you retrieve.** All names and trademarks belong to their owners and are used only to describe which public endpoints this Actor reads.

### Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

**Video, audio & social**

- [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- [YouTube Comments API](https://apify.com/insight.solutions/youtube-comments-api) — comments and replies with likes, pinned and hearted flags, newest or top sort.
- [YouTube Channel API](https://apify.com/insight.solutions/youtube-channel-api) — a channel's videos, Shorts and live streams, plus YouTube search.
- [Bluesky Scraper](https://apify.com/insight.solutions/bluesky-scraper) — profiles, posts, followers and follows from the public AT Protocol API.
- [Telegram Channel Scraper](https://apify.com/insight.solutions/telegram-channel-scraper) — posts, views and channel stats from public Telegram channels.
- [Substack Scraper](https://apify.com/insight.solutions/substack-scraper) — posts with full free text, comments and publication profiles.

**News, documents & the web**

- [Google News Search, Topics & Real Article URLs](https://apify.com/insight.solutions/google-news-api) — news search and topic feeds with the publisher's real URL decoded.
- [Website to Markdown — Content Extractor for LLMs & RAG](https://apify.com/insight.solutions/website-content-extractor) — any site as clean Markdown, text and heading-aware chunks.
- [Internet Archive API](https://apify.com/insight.solutions/internet-archive-api) — archive.org search, item metadata, files and reviews.
- [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) — archived URL inventories, snapshots and text diffs between dates.
- [Website Technology Detector](https://apify.com/insight.solutions/website-tech-detector) — the tech stack behind any site, with the evidence for each detection.
- [Domain Intelligence API](https://apify.com/insight.solutions/domain-intelligence-api) — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- [SEO Page Audit](https://apify.com/insight.solutions/seo-page-audit) — sitemap crawl with on-page checks, structured data and broken-link reports.
- [Keyword Suggestions API](https://apify.com/insight.solutions/keyword-suggestions-api) — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- [Website Contact Extractor](https://apify.com/insight.solutions/website-contact-extractor) — emails, phone numbers and social profiles from any list of websites.

**Business, finance & jobs**

- [Congress & Insider Trades API](https://apify.com/insight.solutions/congress-insider-trades-api) — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- [SEC EDGAR API](https://apify.com/insight.solutions/sec-edgar-api) — filings, XBRL financials and full-text search by ticker or CIK.
- [Y Combinator Companies, Batches & Founders](https://apify.com/insight.solutions/yc-companies-directory) — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- [Career Site Jobs API](https://apify.com/insight.solutions/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- [New Job Postings Monitor](https://apify.com/insight.solutions/job-postings-monitor) — new, closed and changed postings on the career sites you watch.
- [Shopify Products API](https://apify.com/insight.solutions/shopify-products-api) — any Shopify store's catalogue, variants, prices and stock signals.

**Apps & games**

- [App Store & Google Play Reviews API](https://apify.com/insight.solutions/app-reviews-api) — reviews from both stores with ratings, versions and developer replies.
- [App Store Top Charts & App Search API](https://apify.com/insight.solutions/app-charts-api) — Apple top charts by country and genre, plus app search and details.
- [Steam Reviews API](https://apify.com/insight.solutions/steam-reviews-api) — Steam reviews with playtime, helpfulness and game details.
- [Steam Game Data API](https://apify.com/insight.solutions/steam-store-stats-api) — prices, tags, review scores, live player counts and top charts.

# Actor input Schema

## `podcasts` (type: `array`):

One entry per show. Four shapes work: an **Apple Podcasts link** (`https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110` — an episode link works too, it resolves to the show), a **bare Apple ID** (`1545953110`), an **RSS feed URL** (`https://feeds.megaphone.fm/hubermanlab`, `https://lexfridman.com/feed/podcast/` — it does not have to end in .xml), or a **show name** (`Huberman Lab`), which is resolved through Apple's search and flagged as `resolvedFrom: search` on the row. A number shorter than five digits is read as a name, because `1619` is a podcast. To be explicit, prefix an entry: `feed:`, `id:` or `name:`. Duplicates are read, and billed, once.

## `maxEpisodesPerPodcast` (type: `integer`):

How many episodes to return for each show, newest first. Set **0 for every episode in the feed** — that is the whole back catalogue, which for a daily news show is a few thousand rows. The feed is one request whatever you ask for, so a high number costs no extra requests, only rows. With `episodeSource: apple` the ceiling is 200: Apple's lookup will not serve more than that, however many the show has.

## `episodeSource` (type: `string`):

**RSS** is the show's own feed: full show notes, the real audio URL, the publisher's GUID, duration, episode and season numbers, per-episode artwork — and no 200-episode ceiling. **Apple** is the iTunes lookup: fewer fields, descriptions already flattened to plain text, no episode numbers, capped at 200 — but it works for a show whose feed is unreachable, and it is one request instead of a multi-megabyte download. RSS is the default and the fallback happens automatically: if the feed will not answer, Apple's episode list is used instead and a free diagnostic row says so.

## `includeDescriptionHtml` (type: `boolean`):

Add a `descriptionHtml` column holding the show notes as the publisher wrote them, links and all. The plain-text `description` column is always there; this is for when you want the anchor tags — sponsor links, chapter links, guest bios. It makes rows several times larger and it is off by default.

## `includeRating` (type: `boolean`):

Add `rating` and `ratingCount` to each podcast row. Apple publishes a podcast's star rating **only on the show's web page**, so this costs one extra request per show — and that page is around 600 KB of HTML for two numbers. Off by default; the two columns are null unless you turn it on. It never fails a run: a page that will not load costs the rating, not the episodes.

## `searchQueries` (type: `array`):

Find shows by keyword. Each query returns up to `maxResultsPerQuery` **podcast** rows — title, author, feed URL, genres, artwork, Apple's episode count — and no episodes unless you turn on `includeEpisodesForSearchHits`. This is the input for building a list: "every true-crime podcast Apple knows about", "shows whose name mentions Bitcoin".

## `maxResultsPerQuery` (type: `integer`):

How many shows each search query returns. Apple's own ceiling is 200 and asking for more does not get more.

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

Restrict every search query to one Apple podcast genre, by numeric ID — `1462` History, `1488` True Crime, `1489` News, `1533` Science, `1512` Health & Fitness, `1318` Technology. Leave empty to search all genres. It has no effect on the `podcasts` or `charts` inputs.

## `includeEpisodesForSearchHits` (type: `boolean`):

Read every search hit's RSS feed as well, returning `maxEpisodesPerPodcast` episodes for each. This turns one query into one request per hit plus a feed download each, so a 25-result query becomes 26 requests and a lot of rows. Off by default. Shows that Apple lists with no public feed — Apple-exclusive ones, mostly — get a free diagnostic row instead.

## `charts` (type: `array`):

Two-letter country codes. Each one returns Apple's current **Top Shows** chart for that country as ranked `chart` rows: rank, show, artist, genres, artwork and the Apple link. This is the cheapest data here — one request buys up to 100 rows — and it is how you watch a market rather than a show.

## `chartSize` (type: `integer`):

How deep each chart goes. Apple serves exactly three sizes — 25, 50 and 100 — and anything else is rounded to the nearest of them, because any other number is a 404.

## `includeChartDetails` (type: `boolean`):

Look each charting show up, adding its feed URL, episode count, latest episode date and explicit flag to the chart row. It is **one extra request per show**, so an enriched Top 100 is 101 requests and takes a couple of minutes. Off by default: the chart itself already carries the rank, the name, the artist, the genres and the artwork.

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

Two-letter ISO country code, lower case. Apple's catalogue is per-country: a show published only in Germany is not in the `us` storefront at all, search rankings differ, and so do the charts. RSS feeds are global — the feed is the same wherever you read it from — so this changes what Apple tells you, not what the publisher does.

## `maxConcurrency` (type: `integer`):

How many shows, queries or charts are read at once. Each parallel worker keeps its own proxy session, so one blocked feed burns only its own exit IP. Feeds are large — a long-running show is several megabytes — so raising this raises memory as well as speed.

## `maxRunSecs` (type: `integer`):

Wall-clock budget for the whole run. When it is reached the Actor stops fetching, keeps and bills for every row it already wrote, and files a free diagnostic row for each entry it never reached. A show stopped part-way keeps its rows. Nothing is charged for work that did not happen.

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

Apple's endpoints and the big podcast hosts answer datacenter addresses happily, so the default is Apify's datacenter proxy — much cheaper than residential, and the proxy cost is already inside the per-row price. Switch to residential only if you are reading a feed from a host that rate-limits shared addresses. Sessions rotate automatically when an exit IP is refused.

## Actor input object example

```json
{
  "podcasts": [
    "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110",
    "1545953110",
    "https://feeds.simplecast.com/Sl5CSM3S",
    "99% Invisible"
  ],
  "maxEpisodesPerPodcast": 50,
  "episodeSource": "rss",
  "includeDescriptionHtml": false,
  "includeRating": false,
  "searchQueries": [
    "true crime",
    "startup founders"
  ],
  "maxResultsPerQuery": 25,
  "genreId": "1462",
  "includeEpisodesForSearchHits": false,
  "charts": [
    "us",
    "gb",
    "de"
  ],
  "chartSize": 50,
  "includeChartDetails": false,
  "country": "us",
  "maxConcurrency": 3,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per episode — title, show notes, audio URL, duration, publish date, GUID — plus one row per show and one per chart position. Entries that could not be read get a free diagnostic row saying why. Delivered as JSON items in the default dataset.

# 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 = {
    "podcasts": [
        "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110"
    ],
    "maxEpisodesPerPodcast": 50,
    "episodeSource": "rss",
    "includeDescriptionHtml": false,
    "includeRating": false,
    "searchQueries": [],
    "maxResultsPerQuery": 25,
    "includeEpisodesForSearchHits": false,
    "charts": [],
    "chartSize": 50,
    "includeChartDetails": false,
    "country": "us",
    "maxConcurrency": 3,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insight.solutions/podcast-api").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 = {
    "podcasts": ["https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110"],
    "maxEpisodesPerPodcast": 50,
    "episodeSource": "rss",
    "includeDescriptionHtml": False,
    "includeRating": False,
    "searchQueries": [],
    "maxResultsPerQuery": 25,
    "includeEpisodesForSearchHits": False,
    "charts": [],
    "chartSize": 50,
    "includeChartDetails": False,
    "country": "us",
    "maxConcurrency": 3,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("insight.solutions/podcast-api").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 '{
  "podcasts": [
    "https://podcasts.apple.com/us/podcast/huberman-lab/id1545953110"
  ],
  "maxEpisodesPerPodcast": 50,
  "episodeSource": "rss",
  "includeDescriptionHtml": false,
  "includeRating": false,
  "searchQueries": [],
  "maxResultsPerQuery": 25,
  "includeEpisodesForSearchHits": false,
  "charts": [],
  "chartSize": 50,
  "includeChartDetails": false,
  "country": "us",
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call insight.solutions/podcast-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,insight.solutions/podcast-api"
        }
    }
}

```

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/LcF3fhqclHM1gLqPx/builds/ocAugahUMJ7AWdGji/openapi.json
