Podcast Transcript API

Podcast episode transcripts from RSS feeds: free publisher transcripts when available, otherwise Whisper speech-to-text. JSON, text, SRT, VTT.

Hosted MCP Server

npx add-mcp 'https://mcp.apify.com/?actors=catalyst-labs/podcast-transcript-api'

Installs into Claude Code, Codex, Cursor and more

Documentation

Podcast Transcript API - RSS, Apple Podcasts & Audio to Text (catalyst-labs/podcast-transcript-api) Actor

Get podcast and audio transcripts as text, timestamped segments, SRT/VTT and Markdown. Input: RSS feeds, Apple Podcasts links, episode pages or audio/video URLs. Uses the publisher's own transcript when one exists ($0.01), Whisper speech-to-text otherwise.

Pricing

from $10.00 / 1,000 episode transcript (publisher)s

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 section below.

Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).

README

Podcast Transcript API: RSS, Apple Podcasts & audio to text

Get a transcript for any podcast episode or audio/video file as plain text, timestamped segments, SRT, VTT, LLM-ready text and Markdown, with episode metadata. When the show publishes its own transcript (the Podcasting 2.0 podcast:transcript tag), you get that for a flat $0.01 per episode. Otherwise the audio is transcribed with Whisper large-v3 (turbo as automatic fallback) and billed per audio minute.

For AI agents

  • What it does: podcast RSS feed / Apple Podcasts link / episode page / audio URL in, one transcript record per episode out.
  • Minimal input: {"sources": ["https://podnews.net/rss"], "maxEpisodesPerFeed": 1}
  • Cheap first call: the input above returns the newest Podnews episode from its publisher transcript: $0.01.
  • MCP tool: catalyst-labs--podcast-transcript-api (via https://mcp.apify.com/?tools=catalyst-labs/podcast-transcript-api).
  • Cost controls: maxEpisodesPerFeed (default 3), maxAudioMinutes (default 120 speech-to-text minutes per run), maxMinutesPerEpisode (default 180), transcriptMode: "publisherOnly" (never transcribes), plus the run option maxTotalChargeUsd. The run checks the budget before transcribing each episode, so it never overshoots.
  • Key output fields: transcriptSource (publisher | speechToText), text, llmText, segments[{start,end,text,speaker}], srt, vtt, markdown, speakers, chapters, language, durationSeconds, chargedEvent, chargedMinutes; failures carry errorType, retryable, hint.
  • Known limits: Spotify-exclusive and Apple-subscription shows have no public audio (rejected, not charged; pass the RSS feed). YouTube links: use catalyst-labs/youtube-transcript-api. Speech-to-text has no speaker labels (publisher transcripts keep theirs).

When to choose this tool

  • Choose this tool when you need both paths in one call: publisher transcripts where they exist (cheap, speaker-labelled, exact) and speech-to-text for everything else, with transcriptSource telling you which one you got.
  • Choose it when you start from what people actually share: RSS feeds, Apple Podcasts show or episode links, episode web pages (the feed and audio are found for you) or direct file links.
  • Choose it for long episodes: audio is re-encoded to 16 kHz mono and split into overlapping 10-minute chunks, then stitched on segment midpoints, so 2-3 hour shows work without size errors or duplicated lines at the joins.
  • Choose it for monitoring: onlyNewEpisodes remembers what was delivered, so a scheduled run returns each new episode once.
  • Choose it for agent and RAG pipelines: llmText (fillers and stutters removed), Markdown with linked timestamps, one combined TRANSCRIPTS.md, chapters when published.
  • Never charged: invalid or unsupported links, feeds/files that can't be reached or decoded, audio with no speech, episodes skipped by caps, filters or monitor mode, and any failed episode.
  • QA results: see "Tested" below.

Choose a different tool when you need speaker labels on speech-to-text output (diarization), translation to English, or Spotify-exclusive shows.

Pricing (pay per event, no start fee)

EventFreeBronzeSilverGold+
Episode transcript (publisher)$0.01$0.01$0.01$0.01
Transcribed audio minute$0.009$0.008$0.007$0.006

Minutes are rounded up once per episode (a 30 min 10 s episode = 31 minutes). A 60-minute episode without a publisher transcript costs $0.54 on Free. A feed with publisher transcripts costs $0.01 per episode, at any length.

Input

FieldDefaultWhat it does
sources(required)Feeds, Apple links, episode pages, audio/video URLs
maxEpisodesPerFeed3Newest N per feed (0 = all)
transcriptModeautoauto, publisherOnly, speechToText
maxAudioMinutes120Per-run speech-to-text cap
maxMinutesPerEpisode / truncateLongEpisodes180 / falseSkip or truncate very long episodes
onlyNewEpisodes / monitorIdfalseMonitor mode
publishedAfter, titleFilterEpisode filters
languageautoPublisher-transcript language and STT language hint
vocabularyNames/terms to spell correctly (show and episode titles always used)
outputFormatsalltext, segments, llmText, srt, vtt, markdown
includeChapterstruePodcasting 2.0 chapters

Output example

{ "status": "succeeded", "podcastTitle": "Podnews Daily", "episodeTitle": "WTF returns in visual form", "publishedAt": "2026-10-20T07:00:00.000Z",
  "durationSeconds": 356, "transcriptSource": "publisher", "publisherFormat": "vtt", "language": "en-gb", "wordCount": 880,
  "segments": [{ "start": 0, "end": 4.2, "text": "From our free daily newsletter..." }], "chargedEvent": "publisher-transcript", "charged": true }

The OUTPUT record summarises the run: counts, audioMinutesCharged, errorTypes, stoppedBy.

Tested

Cloud-tested 20 Oct 2026 (build 1.0.8): 16/16 launch cases pass, across 11 podcast hosts and SRT, VTT, JSON and HTML transcripts in English, German and Spanish; Apple show and episode links; episode pages; spending caps; and invalid inputs. Charged events equalled delivered records in every run, and no failed row was charged.

  • Speech-to-text word error rate against the publisher's own transcript: English 2.4% and 3.0%, Spanish 10.2%, German 16.9% (much of the gap is number spelling and errors in the reference).
  • Long episodes: a 100-minute episode transcribes in about 25 seconds, with chunks cut at pauses.
  • Misses: Spotify-only shows are not supported. Speech-to-text output has no speaker labels.

FAQ

Is the speech-to-text accurate? It uses Whisper large-v3 (turbo as automatic fallback). See the measured word error rate under Tested. Names improve when you pass them in vocabulary. Do you store audio? No. Audio is processed in the run's temporary storage and deleted when the episode is done. Copyright: transcripts belong to the shows. Use them for research, search, accessibility and personal use; credit the show when quoting.

Actor input Schema

sources (type: array):

Podcast RSS feed URLs, Apple Podcasts show or episode links, episode web pages, or direct audio/video file URLs (mp3, m4a, mp4, wav...). Feeds return the newest episodes (see maxEpisodesPerFeed). Spotify and YouTube links are not supported. Example: ["https://feeds.buzzsprout.com/1.rss", "https://podcasts.apple.com/us/podcast/id1584274529"]

maxEpisodesPerFeed (type: integer):

Newest N episodes taken from each feed or Apple show link. 0 = all episodes in the feed. Example: 5

transcriptMode (type: string):

auto: use the publisher's Podcasting 2.0 transcript ($0.01 per episode) and transcribe only when none exists (per audio minute). publisherOnly: never run speech-to-text. speechToText: always transcribe.

maxAudioMinutes (type: integer):

Hard cap on speech-to-text minutes billed in this run; episodes that would exceed it are skipped (not charged, retryable). 0 = publisher transcripts only. Combine with the run option maxTotalChargeUsd. Example: 300

maxMinutesPerEpisode (type: integer):

Episodes longer than this are skipped (not charged), or transcribed only up to this length when truncateLongEpisodes is on. Example: 240

truncateLongEpisodes (type: boolean):

When an episode is longer than maxMinutesPerEpisode, transcribe and bill only its first maxMinutesPerEpisode minutes (record flagged truncated: true) instead of skipping it.

onlyNewEpisodes (type: boolean):

Remember delivered episodes and skip them on later runs (never charged twice). Use with a schedule to get each new episode once.

monitorId (type: string):

Optional name for the onlyNewEpisodes memory, so several schedules can track the same feeds separately. Defaults to the list of sources. Example: "weekly-news-shows"

publishedAfter (type: string):

Only episodes published on or after this date (YYYY-MM-DD). Example: "2026-10-01"

titleFilter (type: string):

Only episodes whose title contains this text (case-insensitive). Example: "interview"

language (type: string):

Optional ISO 639-1 code (en, es, de...). Picks the publisher transcript in that language and tells speech-to-text the spoken language. Empty = auto-detect (about 100 languages).

vocabulary (type: array):

Guest names, brands and jargon passed to speech-to-text so they are spelled right. The show and episode titles are always used. Example: ["Adam Curry", "Podcasting 2.0", "Fountain"]

outputFormats (type: array):

Fields to include per episode: text (paragraphs, speaker-labelled when known), segments (start/end seconds, speaker), llmText (fillers removed), srt, vtt, markdown (also combined in TRANSCRIPTS.md). Same price for any combination.

includeChapters (type: boolean):

Add the episode's Podcasting 2.0 chapters (start, title) when the feed publishes them. Free.

Actor input object example

{
  "sources": [
    "https://podnews.net/rss"
  ],
  "maxEpisodesPerFeed": 1,
  "transcriptMode": "auto",
  "maxAudioMinutes": 120,
  "maxMinutesPerEpisode": 180,
  "truncateLongEpisodes": false,
  "onlyNewEpisodes": false,
  "outputFormats": [
    "text",
    "segments",
    "llmText",
    "srt",
    "vtt",
    "markdown"
  ],
  "includeChapters": true
}

Actor output Schema

transcripts (type: string):

Records with text, llmText, segments, SRT/VTT, Markdown, chapters and episode metadata.

summary (type: string):

Counts, error types, audio minutes charged, stoppedBy.

markdown (type: string):

All delivered transcripts in one Markdown file (when outputFormats includes markdown).

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

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 = {
    "sources": [
        "https://podnews.net/rss"
    ],
    "maxEpisodesPerFeed": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("catalyst-labs/podcast-transcript-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

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 = {
    "sources": ["https://podnews.net/rss"],
    "maxEpisodesPerFeed": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("catalyst-labs/podcast-transcript-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

echo '{
  "sources": [
    "https://podnews.net/rss"
  ],
  "maxEpisodesPerFeed": 1
}' |
apify call catalyst-labs/podcast-transcript-api --silent --output-dataset

MCP server setup

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,catalyst-labs/podcast-transcript-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/5jdK5z2K6EbJoWdZd/builds/cZTcV0iM37Fy2lx9g/openapi.json