Back to blog
Guide·Jun 10, 2026·4 min read

How to get transcripts from an entire YouTube channel

Most transcript tools stop at one video. Here is a reliable, repeatable way to pull transcripts from every video on a YouTube channel, using a list call plus a batch fetch.

Chandler Caseyby Chandler Casey

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

  1. List the channel's videos. A channel handle, channel ID, or full URL goes in, a list of video IDs comes out.
  2. 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.

bash
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:

json
{
  "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.

bash
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:

json
{
  "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.

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