How to get a YouTube transcript with an API (curl, Python, JavaScript)
Fetch any public YouTube transcript with one HTTP request. Working curl, Python and JavaScript examples, output formats, error codes and costs.

To get a YouTube transcript with an API, send one HTTP request with a video URL or ID and an API key, and read the transcript from the response. This guide shows the request in curl, Python and JavaScript using the sum.video Transcript API, then covers formats, errors and cost.
What the API returns
The endpoint returns the existing captions of a public YouTube video, either written by the creator or auto-generated by YouTube. It does not transcribe audio. If a video has no captions, you get an error instead of a guess (more on that below).
The basics:
- Endpoint:
POST https://sum.video/api/v1/transcript(GETworks too) - Auth: your key in the
X-API-Keyheader, orAuthorization: Bearer <key> - Input:
urlorvideo_id - Optional
lang(defaulten) - Optional
format:json,textorsrt
The response also tells you the real language of the caption track and whether it is auto-generated, so you know what quality to expect.
Step 1: Create an API key
Sign in and create a key on the API dashboard (/dashboard/api on sum.video). You can have up to 5 active keys, which is handy for separating a staging key from a production key. Your first key comes with 10 free credits, enough for 5 transcripts, so you can test everything below at no cost.
Step 2: Make your first request
curl
curl -X POST https://sum.video/api/v1/transcript \
-H "X-API-Key: $SUMVIDEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "lang": "en", "format": "text"}'
Because GET works too, you can also test from a script that only builds URLs. Prefer the header for the key, so it does not end up in logs.
Python
import os
import requests
resp = requests.post(
"https://sum.video/api/v1/transcript",
headers={"X-API-Key": os.environ["SUMVIDEO_API_KEY"]},
json={"video_id": "dQw4w9WgXcQ", "lang": "en", "format": "text"},
timeout=30,
)
if resp.status_code == 404:
print("No captions for this video")
else:
resp.raise_for_status()
print(resp.text)
JavaScript (Node 18+ or the browser)
const resp = await fetch("https://sum.video/api/v1/transcript", {
method: "POST",
headers: {
"X-API-Key": process.env.SUMVIDEO_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
video_id: "dQw4w9WgXcQ",
lang: "en",
format: "text",
}),
});
if (resp.status === 404) {
console.log("No captions for this video");
} else if (!resp.ok) {
throw new Error(`Request failed: ${resp.status}`);
} else {
console.log(await resp.text());
}
Keep the key on a server. A key placed in browser code can be copied by anyone who opens the developer tools.
Step 3: Pick the right format
| Format | What you get | Best for |
|---|---|---|
json |
Segments, each with offset and duration in seconds |
Timestamps, deep links to a moment, chunking by time |
text |
Plain transcript | Prompts, search indexes, summaries |
srt |
Subtitle file content | Video editors, subtitle tools |
If you plan to link back to a moment in the video, use json and build the link from the segment's offset. For feeding an LLM, text is smaller and simpler. If you later want to search inside a transcript by hand, see how to search inside a YouTube video's transcript.
Step 4: Choose a language
lang defaults to en. Set it to the language you want, for example de or es. The response reports the language of the track that was actually returned, so check it instead of assuming. A video often has only one caption track, and the API returns real captions, so it does not translate them for you.
Step 5: Handle errors
Plan for these cases from day one:
404 no_transcript: the video has no captions, or it is a live stream, a private video or a removed video. There is nothing to retry. Skip it, or ask the user for another video.402 budget_exceeded: you hit the monthly credit limit you configured. See the next section.- Rate limit: each key allows 60 requests per minute. Space out batch jobs, and back off when you are throttled.
- Failures on our side: retry with a short delay. These cost nothing.
A simple loop with a retry on server errors and a skip on 404 covers most production needs.
What it costs
Each transcript costs 2 credits. Requests that return no transcript, or that fail on sum.video's side, cost nothing, so a 404 never drains your balance. You can check your balance with GET /api/v1/credits.
Credits are sold in one-time packs that never expire:
| Pack | Price | Per transcript |
|---|---|---|
| 100 credits | $4.49 | $0.090 |
| 500 credits | $13.99 | $0.056 |
| 2,000 credits | $37.99 | $0.038 |
| 5,000 credits | $74.99 | $0.030 |
Pro subscribers also get 100 bonus credits each month. For a heavier workload, such as ingesting a whole channel, read the scenario YouTube transcripts for a RAG app at scale, which covers auto top-up and budgets. See also pricing.
Limits to know before you build
- Only videos with captions work. This is the main reason for
404 no_transcript. - Auto-generated captions can contain mistakes, especially with names, accents and technical terms.
- The API returns the transcript only. It does not summarize. If you want summaries, timestamps and chat on top of a transcript, the YouTube summarizer does that, and the transcript tool is the no-code version for one video.
- The official YouTube Data API is not a substitute here. Its captions download method requires permission to edit the video, so it is meant for your own videos (Google documentation).
Sources
Frequently asked questions
Can I get a YouTube transcript without the official YouTube Data API?
Yes. The sum.video Transcript API takes a video URL or ID and returns the existing captions, with no Google Cloud project needed. Google's own captions download method requires permission to edit the video, so it only suits your own videos.
Does the API transcribe videos that have no captions?
No. It returns existing YouTube captions, manual or auto-generated. Videos without captions, live streams, private videos and removed videos return 404 no_transcript, and that request costs nothing.
How much does one transcript cost?
2 credits per transcript. Packs run from 100 credits for $4.49 ($0.090 per transcript) to 5,000 credits for $74.99 ($0.030 per transcript), and credits never expire.
Which output formats are available?
json (segments with offset and duration in seconds), text, and srt. Set the format field in the request.
How do I test it for free?
Your first API key comes with 10 free credits, which is 5 transcripts. Pro subscribers also get 100 bonus credits each month.
Related reading
Best YouTube transcript APIs compared: sum.video, Supadata, Transcribr and the Python libraryFour ways to get YouTube transcripts in code, compared on price, limits and reliability: sum.video, Supadata, Transcribr and youtube-transcript-api.
YouTube transcripts for a RAG app at scale: credits, auto top-up and budgetsA developer ingests 10,000 YouTube videos into a RAG app. See the cost, the rate limit math, and how auto top-up and budgets keep the spend predictable.
Build a personal knowledge base from YouTube videosTurn the YouTube videos you learn from into a searchable library of summaries and saved points, with a weekly recap, so you can find an idea again months later.
Latest posts
Best YouTube transcript APIs compared: sum.video, Supadata, Transcribr and the Python libraryFour ways to get YouTube transcripts in code, compared on price, limits and reliability: sum.video, Supadata, Transcribr and youtube-transcript-api.
YouTube transcripts for a RAG app at scale: credits, auto top-up and budgetsA developer ingests 10,000 YouTube videos into a RAG app. See the cost, the rate limit math, and how auto top-up and budgets keep the spend predictable.
Build a personal knowledge base from YouTube videosTurn the YouTube videos you learn from into a searchable library of summaries and saved points, with a weekly recap, so you can find an idea again months later.