Most transcript tools stop at a single video. Paste a URL, get one transcript, repeat. That falls apart the moment you want to analyze a creator's full catalog, build a searchable archive, or feed a channel into a language model. This guide shows a reliable, repeatable way to pull transcripts from every video on a YouTube channel.
The approach has two steps: list the channel's videos, then fetch transcripts for those video IDs in bulk (see free tools vs API for bulk downloads). We will use the TranscriptFetch API, but the pattern works with any backend that can list a channel and return captions.
The two-step pattern
- List the channel's videos. A channel handle, channel ID, or full URL goes in, a list of video IDs comes out.
- Batch fetch transcripts. Send those IDs to a batch endpoint and get every transcript back in one round trip.
Doing it this way means you never paste URLs by hand, and you can re-run the job to pick up new uploads.
Step 1: list the channel's videos
The channel listing endpoint accepts a handle like @veritasium, a channel ID like UCHnyfMqiRRG1u-2MsSQLbXA, or a normal channel URL.
curl https://transcriptfetch.com/api/transcripts \
-H "Authorization: Bearer $TRANSCRIPTFETCH_KEY" \
-H "Content-Type: application/json" \
-d '{ "endpoint": "channel_videos", "value": "@veritasium", "limit": 50 }'The response includes a videos array. Each entry carries the video ID, title, and URL:
{
"ok": true,
"videos": [
{ "videoId": "abc123", "title": "How this works", "url": "https://youtu.be/abc123" },
{ "videoId": "def456", "title": "Another upload", "url": "https://youtu.be/def456" }
]
}You can request up to 50 videos per call. For a large back catalog, page through the channel by making repeated calls and collecting IDs until you have the full set.
Step 2: batch fetch the transcripts
Once you have the IDs, send them to the batch endpoint. It accepts up to 50 IDs per request and fetches them concurrently, so a full page of a channel comes back in seconds.
curl https://transcriptfetch.com/api/transcripts/batch \
-H "Authorization: Bearer $TRANSCRIPTFETCH_KEY" \
-H "Content-Type: application/json" \
-d '{ "videoIds": ["abc123", "def456", "ghi789"] }'Each result contains the transcript text, timestamped segments, and an outcome flag:
{
"results": [
{
"videoId": "abc123",
"title": "How this works",
"text": "Full transcript text here...",
"segments": [{ "start": 0.0, "duration": 3.2, "text": "Welcome back" }],
"outcome": "ok",
"cached": false
}
],
"creditsSpent": 3,
"balance": 997
}Putting it together
Here is a small script that turns a channel handle into a folder of transcript files. It lists the channel, chunks the IDs into batches of 50, and writes each transcript to disk.
import os, json, requests
KEY = os.environ["TRANSCRIPTFETCH_KEY"]
BASE = "https://transcriptfetch.com/api"
HEAD = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
def list_channel(handle, limit=50):
r = requests.post(f"{BASE}/transcripts", headers=HEAD,
json={"endpoint": "channel_videos", "value": handle, "limit": limit})
r.raise_for_status()
return [v["videoId"] for v in r.json().get("videos", [])]
def fetch_batch(ids):
r = requests.post(f"{BASE}/transcripts/batch", headers=HEAD,
json={"videoIds": ids})
r.raise_for_status()
return r.json()["results"]
def chunk(items, n):
for i in range(0, len(items), n):
yield items[i:i + n]
ids = list_channel("@veritasium")
os.makedirs("transcripts", exist_ok=True)
for group in chunk(ids, 50):
for res in fetch_batch(group):
if res["outcome"] == "ok" and res["text"]:
with open(f"transcripts/{res['videoId']}.txt", "w") as f:
f.write(res["text"])
else:
print("skipped", res["videoId"], res["outcome"])Handling videos without captions
Not every video has captions. Live streams, music videos, and some older uploads return an outcome of no_transcript. The API does not charge for those, so you only pay for transcripts you actually receive. Your code should check the outcome field rather than assuming text is always present.
Costs and rate limits
Each successful transcript costs one credit. Failed or empty fetches are free. Requests are rate limited per API key, with a generous default, and the batch endpoint counts as one request regardless of how many videos it contains. For a 200 video channel that is roughly 200 credits and four batch calls.
The faster path: ask your AI assistant
If you would rather not write a script, connect the MCP server to Claude, Cursor, or ChatGPT and ask in plain language:
Pull the latest 30 videos from @veritasium and summarize the recurring themes.
The assistant lists the channel and fetches the transcripts for you using the same endpoints described above. Same data, no glue code.
Wrapping up
Getting transcripts for an entire channel is not one big magic call. It is a list step followed by a batch step, wrapped in a loop. Once you have that pattern, archiving a creator's full catalog or keeping an index fresh becomes a scheduled job rather than an afternoon of copy and paste.
