# Podcast RSS Feed Scraper + Podcast Index (Podcasting 2.0) (`hydrocore/podcast-rss-scraper`) Actor

Turn any podcast RSS feed, website or show name into clean show and episode records: audio URL, duration, dates, seasons, chapters and transcript links, funding, value-for-value, persons. Optional free Podcast Index key adds search, trending and recent feeds. Pay per row, hard spend caps.

- **URL**: https://apify.com/hydrocore/podcast-rss-scraper.md
- **Developed by:** [Hydrocore Data](https://apify.com/hydrocore) (community)
- **Categories:** Social media, News
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 show records

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Podcast RSS Feed Scraper + Podcast Index (Podcasting 2.0)

Turn any podcast **RSS feed, show website or show name** into clean, ready-to-use data: one **show record** per podcast and one **episode record** per episode, with audio URL, duration, dates, season and episode numbers, show notes, **chapters and transcript links**, **funding**, **value-for-value (Lightning) splits**, hosts and guests (`podcast:person`), location, podroll, live items and publishing statistics.

Works **without any API key**. Add a **free Podcast Index key** (optional) to also search 4+ million podcasts, read the **trending** and **recently updated** lists, look up shows by Podcast Index ID or GUID, and fall back to Podcast Index's stored copy when a feed is down.

- No login, no cookies, no proxies. Public RSS feeds only.
- Pay only for rows saved. Not-found inputs, blocked feeds, duplicates and episodes outside your date filter are **never charged**.
- Hard spend caps: the run stops before going over your limit.
- Huge feeds (3,000+ episodes, 20 MB+) are parsed as they stream in and fit in 256 MB of memory.

### What you can do with it

- **Podcast research & lead lists**: build lists of shows in a niche with language, categories, host platform, publishing frequency, last episode date and whether the show is still active.
- **Episode monitoring**: schedule a daily run with "Only episodes from the last 1 day" to get every new episode of the shows you follow.
- **AI & transcription pipelines**: get the audio URL plus transcript (`podcast:transcript`) and chapter (`podcast:chapters`) links for every episode.
- **Podcasting 2.0 audits**: see which shows use funding, value-for-value, transcripts, chapters, persons, podroll, live items or podping.
- **Archive exports**: export a full back catalogue to JSON, CSV or Excel.

### Quick start (no key needed)

1. Paste one or more podcasts into **Podcasts**, one per line:
   - an RSS feed URL: `https://feeds.npr.org/510289/podcast.xml`
   - a show website: `https://www.buzzsprout.com/1` (the feed the page advertises is used)
   - a show name: `Hardcore History`
2. Set **Max episodes per feed** (newest first; 0 = show records only).
3. Click **Start**. Results appear in the **Shows** and **Episodes** tables; download them as JSON, CSV or Excel.

Example input:

```json
{
  "feeds": ["https://feeds.npr.org/510289/podcast.xml", "Hardcore History"],
  "maxEpisodesPerFeed": 10
}
```

### Optional: free Podcast Index API key (2 minutes)

[Podcast Index](https://podcastindex.org) is a free, open podcast directory with 4+ million shows. Its API is free, but every user needs their own key.

1. Go to **https://api.podcastindex.org/signup** and enter your e-mail address.
2. Open the activation link in the e-mail you receive and click **Accept** on the terms page.
3. A second e-mail arrives within a minute with your **API Key** and **API Secret** (keep it: it is the only copy of the secret).
4. In this Actor's input, open the section **Podcast Index key (optional, free)** and paste the key into **Podcast Index API key** and the secret into **Podcast Index API secret**.
5. Both fields are stored encrypted by Apify (secret inputs) and are never written to the dataset or the log.

**What the key adds**

| Feature | Without key | With free key |
|---|---|---|
| RSS feed URLs, show websites | Yes | Yes |
| Show names | Yes (fyyd.de / gpodder.net directories) | Yes (Podcast Index first, then fyyd.de) |
| Keyword search | Yes (fyyd.de, up to 50 shows per search) | Yes (Podcast Index, up to 1,000) |
| Podcast Index feed IDs and podcast GUIDs as input | No (skipped, not charged, with a note) | Yes |
| Trending and recently updated lists | No (skipped with a note) | Yes, filter by language, category, hours |
| Podcast Index fields on show records (ID, Apple ID, crawl status, dead flag) | No | Yes |
| Use Podcast Index's stored episodes when a feed is blocked or offline | No | Yes |

**What happens without a key:** everything RSS-based works fully. Inputs that need the key are skipped (and not charged) and the run log and `RUN_SUMMARY` tell you exactly which and how to get the key. A wrong key or secret is detected with one test request at the start: the run continues in RSS-only mode and tells you to re-check the two fields.

### Output

Every row has `recordType`: `show` or `episode`. Rows of the same type always have the same columns in the same order (the examples below are shortened to the filled columns; all other columns are present as `null`, including the Podcast Index columns when you run without a key). Dates are ISO 8601 in UTC. Real output from a run on 2026-11-03 (feed `https://feeds.buzzsprout.com/1.rss`, description shortened):

Show record:

```json
{
  "recordType": "show",
  "title": "How to Start a Podcast",
  "author": "Buzzsprout",
  "feedUrl": "https://rss.buzzsprout.com/1.rss",
  "inputFeedUrl": "https://feeds.buzzsprout.com/1.rss",
  "websiteUrl": "https://www.buzzsprout.com/1",
  "language": "en-us",
  "categories": ["Education", "How To", "Courses"],
  "keywords": ["podcasting", "how to podcast", "podcast strategies", "podcast tutorial"],
  "explicit": false,
  "showType": "serial",
  "podcastGuid": "7d1a25c1-c5d2-540b-95eb-ba83ec2521de",
  "locked": true,
  "locationName": "Jacksonville, FL, USA",
  "locationGeo": "geo:30.3321838,-81.65565099999999",
  "locationOsm": null,
  "generator": "Buzzsprout (https://www.buzzsprout.com)",
  "hostingProvider": "Buzzsprout",
  "episodesInFeed": 11,
  "firstEpisodeAt": "2024-01-01T05:00:00.000Z",
  "lastEpisodeAt": "2026-10-02T20:00:00.000Z",
  "avgDaysBetweenEpisodes": 100.6,
  "publishingFrequency": "less than monthly",
  "isActive": true,
  "avgEpisodeMinutes": 24.4,
  "episodesWithTranscripts": 11,
  "episodesWithChapters": 10,
  "episodesWithValue": 0,
  "seasons": 1,
  "dataSource": "rss",
  "feedStatus": "ok",
  "foundBy": "input"
}
```

Episode record:

```json
{
  "recordType": "episode",
  "showTitle": "How to Start a Podcast",
  "title": "The Key to Making Your Podcast Stand Out // Eric Nuzum",
  "publishedAt": "2026-10-02T20:00:00.000Z",
  "durationSeconds": 2144,
  "audioUrl": "https://dts.podtrac.com/redirect.mp3/www.buzzsprout.com/1/episodes/2562823-the-key-to-making-your-podcast-stand-out-eric-nuzum.mp3",
  "audioType": "audio/mpeg",
  "audioBytes": 25757065,
  "episodeType": "bonus",
  "seasonNumber": 1,
  "explicit": false,
  "description": "In this special bonus episode, Travis sits down with one of the godfathers of podcasting - Eric Nuzum. ...",
  "link": "https://www.buzzsprout.com/1/2562823",
  "transcripts": [
    { "url": "https://www.buzzsprout.com/1/2562823/transcript", "type": "text/html", "language": null, "rel": null },
    { "url": "https://www.buzzsprout.com/1/2562823/transcript.vtt", "type": "text/vtt", "language": null, "rel": null }
  ],
  "transcriptUrl": "https://www.buzzsprout.com/1/2562823/transcript",
  "guid": "Buzzsprout-2562823",
  "podcastGuid": "7d1a25c1-c5d2-540b-95eb-ba83ec2521de",
  "feedUrl": "https://rss.buzzsprout.com/1.rss",
  "dataSource": "rss"
}
```

Feeds that use more Podcasting 2.0 tags (for example `https://feeds.podcastindex.org/pc20.xml`, tested 2026-11-03) also fill `funding`, `value` (recipients with name, type, address and split), `persons`, `podroll`, `liveItems`, `blockedOn`, `chaptersUrl` and `soundbites`.

**Views.** The Output tab opens in **Overview (shows)**. There are also **Episodes**, **Podcasting 2.0 tags** and **Detailed** (every field) views.

> Changed in v1.1: the nested `location` object is now `locationName`, `locationGeo`, `locationOsm`; every row type has a fixed column order, with `null` for anything the feed doesn't set.

All fields are described in the dataset schema (Output tab). A run summary is saved as `RUN_SUMMARY` in the key-value store: per input what was saved, what was skipped and why, total charged and why the run stopped.

**Privacy:** owner e-mail addresses (`itunes:owner`, `managingEditor`, `webMaster`, the e-mail in `podcast:locked`) are never saved, and `podcast:person` entries that are e-mail addresses are dropped. Value-for-value recipient addresses are kept because they are public payment addresses published for listeners.

### Pricing

Pay per event, no subscription. Prices per 1,000 rows by Apify plan:

| Event | Free | Bronze | Silver | Gold / Platinum / Diamond |
|---|---|---|---|---|
| Show record | $2.10 | $1.90 | $1.70 | $1.50 |
| Episode | $2.10 | $1.90 | $1.70 | $1.50 |
| Actor start (once per run) | $0.0003 | $0.0003 | $0.0003 | $0.0003 |

Examples on the Free plan: one show with its 10 newest episodes = $0.0234; 100 shows from a search without episodes = $0.2103; a full 3,000-episode archive = $6.30. Set **Max spend for this run** or Apify's **Maximum cost per run** and the Actor stops before going over it.

### Why this Actor (comparison, checked 2026-11-03 on Apify Store)

| Actor | Price per 1,000 rows (Free plan) | Start fee | Inputs |
|---|---|---|---|
| **This Actor** | **$2.10** (down to $1.50) | $0.0003 | RSS URL, website, show name, Podcast Index ID/GUID, keyword search, trending, recent |
| logiover/apple-podcasts-episode-scraper | $2.50 (down to $1.75) | $0.00005 | Apple Podcasts via iTunes API + RSS |
| parseforge/podcastindex-episodes-scraper | $8.50 | none | Podcast Index search query |
| nexgendata/podcast-episodes-scraper | $20.00 | $0.00005 | RSS feed or show name via Apple Podcasts |
| xtech/feed-extractor | $2.00 | $0.00005 | Generic RSS / Atom / JSON Feed |
| automation-lab/rss-feed-reader | $1.15 | $0.035 | Generic RSS / Atom |

**Competitive pricing** for podcast-specific rows (show records + episodes + Podcasting 2.0 tags). The table above is a factual snapshot of Store prices as of the check date — other Actors can change their prices anytime. Generic feed readers (xtech, automation-lab) may cost less per row but return generic feed items, not podcast show records.

What you get in one run here: show records with publishing stats next to the episodes; Podcasting 2.0 tags (funding, value-for-value splits, persons, podroll, live items, soundbites, alternate enclosures, transcripts, chapters); website auto-discovery of the feed; bot walls reported with a clear reason instead of silently empty results; an optional Podcast Index fallback for dead feeds; owner e-mails left out on purpose. Prices of other Actors can change at any time; check their pages.

### FAQ

**Do I need a Podcast Index key?** No. RSS feeds, websites, show names and keyword search all work without one. The key (free at https://api.podcastindex.org/signup) only adds Podcast Index IDs/GUIDs, the trending and recent lists, richer search and the dead-feed fallback.

**Where do I paste the key?** Input tab, section "Podcast Index key (optional, free)": key into "Podcast Index API key", secret into "Podcast Index API secret". Both are needed.

**I pasted the key but it says it was not accepted.** Check you did not swap key and secret and that there are no spaces. The run then continues in RSS-only mode; you are not charged for skipped inputs.

**Can I use Apple Podcasts or Spotify links?** Not in this Actor. Paste the show's RSS feed or its name instead. For Apple ratings, reviews and charts use hydrocore/apple-podcasts-scraper.

**A feed says "blocked".** The host answered with a bot-protection page (Cloudflare, PerimeterX, DataDome, Akamai ...) or needs a login. This Actor does not bypass bot protection or log in. Nothing is charged. Ask the publisher for a public feed URL, or, with a Podcast Index key, the Actor uses Podcast Index's stored copy.

**Are private or premium feeds supported?** No. Feeds that need a login, token or payment are reported as blocked and skipped.

**How do I get only new episodes every day?** Set "Only episodes from the last" to 1 day (or use "Only episodes published on or after"), turn off "Save show records" if you only want episodes, and schedule the Actor. Older episodes are skipped for free.

**How are duplicates handled?** The same feed listed twice (or two URLs that redirect to it, or two feeds with the same `podcast:guid`) is collected once. Duplicate episodes inside a feed are skipped. Duplicates are never charged.

**How big can a feed be?** Up to 80 MB. Feeds with thousands of episodes are parsed while they download, so the default 256 MB memory is enough.

**Why is a show's `episodesInFeed` smaller than on Apple?** Many hosts publish only the newest 100-300 episodes in the RSS feed. With a Podcast Index key, `indexEpisodeCount` shows what Podcast Index has seen.

**Is this legal?** The Actor reads public RSS feeds, which publishers make available so that apps can read them, plus public directory APIs. It does not log in, bypass protection or collect owner e-mail addresses. You are responsible for how you use the data (for example, respect copyright on audio and show notes).

**What happens with slow or unreachable sites?** Each feed gets 12 seconds to start answering (big feeds can then stream for up to 3 minutes as long as data keeps flowing). Timeouts are not retried, and once a run has spent about a minute on failing sites, failing inputs get no more retries. The failed input is listed in the run summary with the reason, and no row is charged for it.

### Support

Found a feed that is parsed wrongly? Open an issue on the Issues tab with the feed URL and what you expected.

# Actor input Schema

## `feeds` (type: `array`):

One podcast per line. Paste an RSS feed URL (https://feeds.npr.org/510289/podcast.xml), the show's website (the feed it advertises is used), a show name (Hardcore History), a Podcast Index feed ID (920666) or a podcast GUID. Names are looked up in Podcast Index when you add a key, otherwise in the free fyyd.de / gpodder.net directories; the run log shows which show was picked. Podcast Index IDs and GUIDs need the free key (see below). The same feed listed twice is collected once.

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

Find podcasts by topic (woodworking, true crime, bitcoin ...). With a Podcast Index key the 4+ million shows of Podcast Index are searched; without a key the free fyyd.de directory is used (smaller, max 50 results per search). Each podcast found is one show record.

## `maxSearchResults` (type: `integer`):

How many podcasts to keep from each search (and each Podcast Index list below).

## `indexTrending` (type: `boolean`):

Save the podcasts trending on Podcast Index right now, ranked (trendRank). Needs the free Podcast Index key and secret below; without them this is skipped with a note and nothing is charged.

## `indexRecentFeeds` (type: `boolean`):

Save podcasts that published new episodes most recently, according to Podcast Index. Needs the free key.

## `indexListSize` (type: `integer`):

How many podcasts to keep from the trending / recently updated lists.

## `indexLanguage` (type: `string`):

Optional language filter for the Podcast Index lists, for example en or de or en,es.

## `indexCategories` (type: `string`):

Optional category filter for the Podcast Index lists, names or IDs separated by commas, for example News,Technology.

## `indexSinceHours` (type: `integer`):

Optional: only list podcasts updated within this many hours (0 = no limit).

## `foundShowsDetail` (type: `string`):

"Read each RSS feed" opens the feed of every podcast found and saves the full show record (Podcasting 2.0 tags, publishing stats). "Directory data only" saves what Podcast Index / fyyd.de already returned, without opening the feeds. The price per show record is the same.

## `episodesForFoundShows` (type: `boolean`):

Off: podcasts found by search or lists give one show record each. On: their episodes are saved too (up to "Max episodes per feed").

## `saveShowRecords` (type: `boolean`):

One show record per podcast. Turn off if you only want episodes of the podcasts you listed.

## `maxEpisodesPerFeed` (type: `integer`):

Newest episodes first. 0 = show records only. Large feeds can have 3,000+ episodes; you pay per episode saved, so set what you need.

## `since` (type: `string`):

Optional date (YYYY-MM-DD). Older episodes are skipped and not charged.

## `lastDays` (type: `integer`):

Optional: only episodes published within this many days (0 = no limit). Handy for daily or weekly monitoring.

## `includeEpisodeHtml` (type: `boolean`):

Also save the original show notes as HTML (descriptionHtml). The plain-text description is always included.

## `indexFallback` (type: `boolean`):

With a key: if a feed is blocked, offline or broken, use the episodes Podcast Index stored for it (dataSource = podcast-index). Without a key this does nothing.

## `podcastIndexApiKey` (type: `string`):

Free from https://api.podcastindex.org/signup (you get an API key and an API secret by e-mail). Paste the API key here. Stored encrypted; never written to the output or log.

## `podcastIndexApiSecret` (type: `string`):

The API secret from the same e-mail. Both key and secret are needed.

## `maxRowsTotal` (type: `integer`):

Stop after this many rows (shows + episodes). 0 = no limit.

## `maxSpendUsd` (type: `string`):

Optional hard cap in US dollars, for example 0.50. The run stops before going over it. The "Maximum cost per run" you set in Apify is respected too; the lower one wins.

## Actor input object example

```json
{
  "feeds": [
    "https://feeds.npr.org/510289/podcast.xml",
    "Hardcore History"
  ],
  "searchTerms": [],
  "maxSearchResults": 10,
  "indexTrending": false,
  "indexRecentFeeds": false,
  "indexListSize": 25,
  "indexSinceHours": 0,
  "foundShowsDetail": "feed",
  "episodesForFoundShows": false,
  "saveShowRecords": true,
  "maxEpisodesPerFeed": 10,
  "lastDays": 0,
  "includeEpisodeHtml": false,
  "indexFallback": true,
  "maxRowsTotal": 0
}
```

# Actor output Schema

## `shows` (type: `string`):

Show records: feed metadata, Podcasting 2.0 tags, publishing stats and Podcast Index data.

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

Episodes with dates, duration, audio URL, chapters and transcript links.

## `podcasting20` (type: `string`):

Funding, value-for-value, people, location and other podcast: namespace tags per show.

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

Every saved row; recordType is show or episode.

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

Per feed and search: what was saved, what was skipped for free and why; total charged and why the run stopped.

# 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 = {
    "feeds": [
        "https://feeds.npr.org/510289/podcast.xml",
        "Hardcore History"
    ],
    "searchTerms": [],
    "maxEpisodesPerFeed": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("hydrocore/podcast-rss-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 = {
    "feeds": [
        "https://feeds.npr.org/510289/podcast.xml",
        "Hardcore History",
    ],
    "searchTerms": [],
    "maxEpisodesPerFeed": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("hydrocore/podcast-rss-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 '{
  "feeds": [
    "https://feeds.npr.org/510289/podcast.xml",
    "Hardcore History"
  ],
  "searchTerms": [],
  "maxEpisodesPerFeed": 10
}' |
apify call hydrocore/podcast-rss-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hydrocore/podcast-rss-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/seREoPI06M87ws1ek/builds/geEMXbkhheT3S34vJ/openapi.json
