There are two ways to get a podcast transcript in code.
- Retrieve one that already exists. Many episodes are published with a transcript attached. A retrieval API hands it to you as text in one request: seconds per episode, cents each, real speaker names — but only for episodes that have one.
- Generate one from the audio. Find the episode's audio URL in the RSS feed, download it, and run it through a speech-to-text model. Works on anything with audio, including your own recordings — but it takes minutes and dollars per episode, and speakers come back as "Speaker 0", not names.
If the episode is out, retrieve. If the audio is yours or unreleased, generate. The rest of this page is the code for both.
Route 1: retrieve the published transcript
Spoken is a retrieval API. Three endpoints cover the whole job: search for a show or episode, list every episode of the show, fetch each transcript as Markdown. The first two are free; a transcript costs one credit the first time and nothing on a repeat fetch. The pt_demo key below is real and needs no signup — it fetches the demo episode, so you can see the output before buying anything.
One episode, one request
curl -H "x-api-key: pt_demo" \
https://spoken.md/transcripts/1000651996090What comes back:
**Lex Fridman** (0:12)
So let's start with the hard part. What do you think is
genuinely unsolved right now?
**Sam Altman** (0:31)
Reasoning over long horizons. Everything else is
engineering.Find the episode or show
Search takes free text or a pasted episode link from Spotify or YouTube, and returns only episodes that have a transcript.
curl -s -H "x-api-key: pt_demo" \
"https://spoken.md/search?q=acquired%20costco"{ "results": [
{ "id": "1000625088063", "title": "Costco", "podcast": "Acquired",
"podcastId": "1050462261", "date": "2026-03-04T05:46:00Z" },
...
] }Every episode of a show — Python
The usual job is a whole back catalogue. List the show's episodes from its podcastId, then loop. Files already on disk are skipped, so the script is safe to re-run after an interruption or a top-up.
import pathlib, time, requests
API = "https://spoken.md"
HEADERS = {"x-api-key": "pt_demo"} # swap in your own key to fetch any episode
show = requests.get(f"{API}/search", params={"q": "acquired"}, headers=HEADERS).json()["results"][0]
episodes = requests.get(f"{API}/podcasts/{show['podcastId']}/episodes", headers=HEADERS).json()["episodes"]
out = pathlib.Path("transcripts")
out.mkdir(exist_ok=True)
for ep in episodes:
path = out / f"{ep['id']}.md"
if path.exists():
continue
r = requests.get(f"{API}/transcripts/{ep['id']}", headers=HEADERS)
if r.ok:
path.write_text(r.text, encoding="utf-8")
time.sleep(0.34) # ~3 requests/s is a comfortable paceRun as written, this lists all of Acquired for free and then gets a 402 on every episode except the demo one, because pt_demo only fetches that episode. Put your own key in HEADERS and the same script pulls the whole show.
The same loop — Node
import { mkdir, writeFile } from "node:fs/promises";
const API = "https://spoken.md";
const headers = { "x-api-key": process.env.SPOKEN_API_KEY ?? "pt_demo" };
const { results } = await (await fetch(`${API}/search?q=acquired`, { headers })).json();
const { episodes } = await (await fetch(`${API}/podcasts/${results[0].podcastId}/episodes`, { headers })).json();
await mkdir("transcripts", { recursive: true });
for (const ep of episodes) {
const res = await fetch(`${API}/transcripts/${ep.id}`, { headers });
if (res.ok) await writeFile(`transcripts/${ep.id}.md`, await res.text());
}The same loop — Bash
curl -s -H "x-api-key: YOUR_KEY" \
https://spoken.md/podcasts/1050462261/episodes \
| jq -r '.episodes[].id' \
| while read -r id; do
[ -f "$id.md" ] || curl -sf -H "x-api-key: YOUR_KEY" \
-o "$id.md" https://spoken.md/transcripts/$id
sleep 0.34
doneEvery response carries X-Credits-Remaining, and a 402 means the key is empty; its body includes a top-up link. A 404 means that episode has no published transcript, and it is never charged. Full reference: the API page, llms.txt, or the OpenAPI spec. If your client is an AI agent, npx spoken-mcp exposes the same three calls as tools.
What it costs
One credit per episode, regardless of length, from $0.08 to $0.15 each: 100 for $15, 500 for $50, 2,000 for $160. A 300-episode back catalogue fits in the 500 pack with credits to spare for the next show, which is the point of pricing per episode: loading a whole archive is a normal thing to do, not a budget decision. Credits never expire, errors are never charged, and re-fetching an episode you already pulled is free.
"I used Spoken to add every My First Million episode to my knowledge base, with a cron to pull new ones. Now I can enjoy the podcast on a run, then chat with Claude about it later — every episode saved and accessible in my Claude sessions."
That is the loop above plus a scheduled re-run. New episodes show up in the episode list, the existing files are skipped, and only the new ones cost a credit.
Route 2: generate a transcript from the audio
Take this route when the episode has no published transcript, when the audio is your own, or when you need word-level timestamps or caption files. The pipeline has four parts, and the transcription itself is the smallest.
- Find the audio. Every podcast has an RSS feed, and every episode in it has an
<enclosure>tag with the MP3 URL. In Python,feedparserreads it in three lines. - Download it. Typically 50–100 MB per episode, so a 300-episode show is 15–30 GB of audio before you transcribe a word.
- Transcribe it. Whisper locally, or a hosted speech-to-text API such as Deepgram or AssemblyAI. Hosted APIs bill per minute of audio, so a three-hour interview costs nine times what a twenty-minute one does.
- Label the speakers. Diarization (pyannote, or the vendor's option) gives you "Speaker 0" and "Speaker 1". Turning those into names takes a further pass with an LLM, and it is the step most pipelines skip.
import feedparser, whisper
feed = feedparser.parse("https://example.com/feed.xml")
audio_url = feed.entries[0].enclosures[0].href
# download audio_url to episode.mp3, then:
result = whisper.load_model("medium").transcribe("episode.mp3")
print(result["text"]) # one block of text, no speakers, no timestampsThat is a real transcript, and for your own audio it is the right answer. For a published show it re-creates something that already exists, at minutes and dollars per episode instead of seconds and cents. The full arithmetic is on Whisper + diarization vs Spoken, Deepgram and AssemblyAI.
Which route, in one pass
| You have… | Do this |
|---|---|
| A published show and want the text of many episodes | Retrieve — Route 1 |
| One episode link from Spotify or YouTube | Retrieve — paste the link into /search |
| Your own recording, or an episode not yet released | Generate — Route 2 |
| An episode that returns 404 from a retrieval API | Generate — it has no published transcript |
| A need for SRT/VTT captions or word-level timestamps | Generate — retrieval returns paragraph-level timestamps |
| A question like "which episodes mention our brand?" | Neither — you need a transcript search API such as Podchaser or Listen Notes |
Other APIs that return podcast transcripts
Spoken is not the only retrieval option, and the right one depends on what you need most. The honest one-line version of each; the full ranking has prices and trade-offs.
- Spoken — the published transcript as Markdown with real speaker names, per-episode credits that never expire. 404s on episodes without a published transcript.
- TranscriptFetch — resolves a link to the audio and transcribes it, so it covers far more episodes and costs less per transcript. No speaker names, and credits live with a monthly subscription.
- Podchaser — a database with millions of transcripts and an endpoint that searches all of them for a phrase. Built for monitoring and PR, priced accordingly.
- Listen Notes — the long-standing podcast search API; transcript text is on paid tiers only.
- Podscan — a full-text index over a large transcript archive, aimed at monitoring and retrospective search.
- Apify actors — community scrapers that pull transcripts through RSS. Fine for a one-off, with the maintenance risk any scraper carries.
FAQ
How can I extract a transcript from a podcast?
If the episode is published, ask a retrieval API for it: search for the episode, then fetch its transcript by id. If the episode has no published transcript, or the audio is your own, find the MP3 in the RSS feed and run it through a speech-to-text model such as Whisper.
How do I download transcripts for every episode of a podcast?
List the show’s episodes from its podcast id, then loop the ids through the transcript endpoint and write each response to a file. Skip files that already exist so the loop can be re-run. The Python, Node and Bash versions on this page do exactly that.
Does Spotify have a transcript API?
No. Spotify shows a transcript inside its app for some episodes, but it is view-only and there is no public endpoint for it. Paste the Spotify episode link into a retrieval API’s search instead; Spoken resolves it to the episode and returns the transcript as Markdown.
Can AI generate podcast transcripts?
Yes. Speech-to-text models such as Whisper, Deepgram and AssemblyAI transcribe audio with high accuracy. What they do not do on their own is name the speakers: diarization labels turns as Speaker 0 and Speaker 1, and mapping those to real names takes a further step. For a published episode a retrieval API skips all of it, because the transcript already exists.
Is there a free way to get podcast transcripts programmatically?
Running Whisper on your own machine is free apart from compute. Spoken’s pt_demo key works without signup on the demo episode, and search and episode listing are free on any key. Several other APIs offer free tiers; check whether transcript text is included, because on some it is not.
Why does the API return 404 for an episode I can see in the app?
A retrieval API can only return a transcript that was published with the episode. Not every episode has one, and a new episode can take several hours after release before its transcript is available. A 404 is never charged. If you need that episode anyway, generate the transcript from its audio.
How much does it cost to transcribe a whole podcast back catalogue?
On a per-episode retrieval API, a 300-episode show is 300 credits, which fits in a $50 pack. On a per-minute speech-to-text API the same show at 90 minutes an episode is 27,000 minutes of audio, plus the download, diarization and speaker-naming steps around it.
TL;DR: For a published show, search for it, list its episodes, and fetch each transcript — three requests and a loop, at cents per episode with speaker names included. Generate from audio only when there is no published transcript or the audio is yours.
Thousands of transcripts fetched by people building searchable podcast archives