# Podcast Episode Scraper: RSS, Audio URLs & Transcripts (`themineworks/podcast-episode-scraper`) Actor

Scrape podcast episodes from any RSS feed or by show name: title, description, duration, audio URL and publish date, plus the full transcript for shows that publish one. No API key, pay per episode.

- **URL**: https://apify.com/themineworks/podcast-episode-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** News, AI, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## 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 Episode Scraper: RSS, Audio URLs & Transcripts

> ⚡ Pure HTTP. No API key, no login, no proxy, no browser.

> 💸 You are only charged for an episode that actually lands in your dataset. Feeds that fail to load are never billed.

### Overview

Podcast Episode Scraper turns any podcast into structured rows. Give it an RSS feed URL, or just a show name, and it returns every episode with title, show notes, publish date, duration in seconds, episode and season numbers, the direct audio file URL, and **the full transcript for shows that publish one**.

Search by name and the show is resolved through Apple's public podcast directory, so you never have to hunt for the RSS URL yourself.

✅ Any podcast host · ✅ Transcripts where published · ✅ Duration normalised to seconds · ✅ MCP-ready for AI agents

### About transcripts, honestly

**Transcripts are not universally available, and no scraper can invent them.** A transcript exists only when the publisher attaches a `<podcast:transcript>` tag to the feed, which is a genuine minority of podcasts today.

We measured five real feeds on 2026-08-13:

| Show | Transcripts in feed |
| --- | --- |
| Podnews Daily | ✅ every episode |
| Buzzcast (Buzzsprout-hosted) | ✅ every episode |
| The Vergecast | ❌ none |
| The Daily | ❌ none |
| Late Night Linux | ❌ none |

So this actor **always** returns complete episode metadata, and returns transcript text **for the shows that publish it**. Every row carries a `has_transcript` boolean so you know exactly which case you got, and we never return a fabricated or machine-guessed transcript.

If you need a transcript for a show that does not publish one, you need speech-to-text on the audio file, which is a different and far more expensive product. This actor gives you the `audio_url` to feed into one.

Shows hosted on Buzzsprout, Captivate, Transistor, RSS.com and Podnews commonly publish transcripts. Large network shows frequently do not.

### Input

```json
{
  "searchTerms": ["Podnews Daily"],
  "feedUrls": ["https://feeds.buzzsprout.com/1538779.rss"],
  "maxEpisodesPerShow": 50,
  "includeTranscripts": true
}
```

| Field | What it takes |
| --- | --- |
| `searchTerms` | Show names. Each is looked up in Apple's public directory and the top 3 matching feeds are scraped. |
| `feedUrls` | Direct RSS feed URLs, for when you already have the feed or the show is not in Apple's directory. |
| `maxEpisodesPerShow` | Hard cap per show. Your main cost and runtime control. |
| `includeTranscripts` | Fetch and convert transcripts where published. Costs one extra request per episode, so turn it off for a fast metadata-only pass. |

You can mix both inputs in one run. Feeds resolved twice are deduplicated.

### Output

```json
{
  "show_title": "Podnews Weekly Review",
  "show_author": "James Cridland",
  "feed_url": "https://feeds.buzzsprout.com/1538779.rss",
  "episode_title": "Spotify add a \"Skip Ahead\" button",
  "description": "This week we look at Spotify's new player controls...",
  "guid": "buzzsprout-19612589",
  "published_at": "Fri, 08 Aug 2026 05:00:00 -0000",
  "duration_seconds": 5284,
  "episode_number": "212",
  "audio_url": "https://www.buzzsprout.com/1538779/19612589.mp3",
  "has_transcript": true,
  "transcript_url": "https://www.buzzsprout.com/1538779/19612589/transcript.vtt",
  "transcript": "Jordan Blair 0:00 I just upload one file to Buzzsprout and it distributes...",
  "scraped_at": "2026-08-13T12:31:07.004Z"
}
```

| Field | Description |
| --- | --- |
| 🎙️ `show_title` | Podcast name |
| 👤 `show_author` | Publisher or host |
| 📡 `feed_url` | RSS feed the episode came from |
| 📄 `episode_title` | Episode title, HTML entities decoded |
| 📝 `description` | Show notes, HTML stripped |
| 🔑 `guid` | Feed GUID, stable for deduplication across runs |
| 📅 `published_at` | Publish date as the feed states it |
| ⏱️ `duration_seconds` | Duration normalised to seconds, whether the feed used `3431` or `00:57:11` |
| 🔢 `episode_number` / `season` | Where the feed publishes them |
| 🔊 `audio_url` | Direct audio file URL, ready for transcription or download |
| ✅ `has_transcript` | Whether a transcript was found and captured |
| 🔗 `transcript_url` | The transcript file as published |
| 📃 `transcript` | Transcript converted to clean plain text |
| 🕒 `scraped_at` | ISO timestamp of capture |

**Why duration is normalised.** Feeds publish duration as either raw seconds or `HH:MM:SS`, inconsistently, sometimes within the same feed. Sorting or filtering on the raw value gives nonsense, so we always emit seconds.

**Why transcripts are cleaned.** Published transcripts are usually WebVTT or SRT, which are full of cue numbers, timing lines and, in some exports, padding whitespace between every word. We strip the machinery, collapse the padding and return readable prose.

### Common use cases

**RAG and AI knowledge bases.** Transcript text is the highest-value podcast data for retrieval. Pull a back catalogue once and index it.

**Content research and repurposing.** Find which episodes covered a topic, then pull the transcript section you need for clips, show notes or newsletters.

**Competitive and industry monitoring.** Track what shows in your space are publishing, on a schedule, with publish dates and durations.

**Media and PR tracking.** Watch for mentions of a brand, person or product across a set of shows that publish transcripts.

**Audio pipelines.** Use `audio_url` to feed your own speech-to-text for shows that do not publish transcripts.

### Pricing

| Event | Price | You pay when |
| --- | --- | --- |
| Episode delivered | $0.002 | An episode lands in your dataset |

**$2.00 per 1,000 episodes**, whether or not that episode carried a transcript. Feeds that fail to load cost nothing.

### Run it on a schedule

1. Run once with the input you want repeated, then click **Save as a task**.
2. In the Apify Console go to **Schedules → Create new**.
3. Pick a frequency and attach the saved task.
4. Wire the dataset to Sheets, Slack or a webhook from the **Integrations** tab.

Deduplicate on `guid` so a repeated schedule never reprocesses the same episode.

### FAQ

**Do I need an Apple or Spotify account?**
No. Podcast RSS feeds are public by design, and the directory lookup uses Apple's public search endpoint.

**Why does an episode have no transcript?**
Because the publisher did not put one in the feed. See the section above. `has_transcript: false` is a real answer, not a failure.

**Can it scrape Spotify-exclusive shows?**
No. Shows without a public RSS feed are not reachable, by anyone, without breaking into a closed platform.

**How far back does it go?**
As far as the feed publishes. Many feeds carry the full back catalogue, and we saw feeds with over 1,000 episodes.

**Why is my run slower with transcripts on?**
Each transcript is a separate file download. Turn `includeTranscripts` off for a fast metadata-only pass.

### Use from Claude, ChatGPT and any MCP agent

```
https://mcp.apify.com/?tools=themineworks/podcast-episode-scraper
```

Or call it programmatically:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/podcast-episode-scraper').call({
  searchTerms: ['Podnews Daily'],
  maxEpisodesPerShow: 50,
  includeTranscripts: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Questions, or need a field we don't return yet? Reach out through the Apify profile.

# Actor input Schema

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

Podcast names. Each is looked up in Apple's public podcast directory and the top 3 matching feeds are scraped. Use this when you know the show but not its RSS URL.

## `feedUrls` (type: `array`):

Direct podcast RSS feed URLs. Use this when you already have the feed, or for shows not listed in Apple's directory.

## `maxEpisodesPerShow` (type: `integer`):

Hard cap per show. With transcripts on, each episode costs one extra request, so this is your main cost and runtime control.

## `includeTranscripts` (type: `boolean`):

Download and convert the transcript when the feed provides one. Transcripts exist only for shows that publish a podcast:transcript tag, which is a minority of podcasts. Turn off for a faster, cheaper metadata-only run.

## Actor input object example

```json
{
  "searchTerms": [
    "Podnews Daily"
  ],
  "feedUrls": [
    "https://feeds.buzzsprout.com/1538779.rss"
  ],
  "maxEpisodesPerShow": 15,
  "includeTranscripts": true
}
```

# Actor output Schema

## `results` (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": [
        "Podnews Daily"
    ],
    "feedUrls": [
        "https://feeds.buzzsprout.com/1538779.rss"
    ],
    "maxEpisodesPerShow": 15
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/podcast-episode-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": ["Podnews Daily"],
    "feedUrls": ["https://feeds.buzzsprout.com/1538779.rss"],
    "maxEpisodesPerShow": 15,
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/podcast-episode-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 '{
  "searchTerms": [
    "Podnews Daily"
  ],
  "feedUrls": [
    "https://feeds.buzzsprout.com/1538779.rss"
  ],
  "maxEpisodesPerShow": 15
}' |
apify call themineworks/podcast-episode-scraper --silent --output-dataset

```

## MCP server setup

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