Transcript generator › API

YouTube transcript API

One GET request. Six output formats. No key, no SDK, no sign-up — the same endpoint this site's own tool calls.

Quick start

curl "https://youtubegpt.ai/api/transcript?v=aircAruvnKk&format=txt"

That is the whole API. Everything below is detail.

Not the Python package

Searching this term usually turns up youtube-transcript-api, the Python package by jdepoix that has been maintained since 2018. It is a good library and this is not a replacement for it. The difference is where the work happens: the package runs the extraction from wherever your code runs, so it inherits your machine's IP reputation and you maintain it as YouTube changes. This is a hosted HTTP endpoint — no install, no language lock-in, and the extraction runs from an IP that is kept working on our side. Reach for the package when you want no external dependency and control over the internals; reach for this when you want one GET request from any language, or when self-hosted extraction has started returning empty results.

Endpoint

GET https://youtubegpt.ai/api/transcript

Parameters

NameRequiredDescription
url or vyesA YouTube URL in any common shape, or the bare 11-character video ID. Watch links, youtu.be short links, Shorts and embed URLs all parse.
formatnoOutput format. Defaults to json. See the table below.
langnoPreferred caption language, e.g. en, es, ja. Defaults to en. Falls back to a human track, then an auto track, then English, then whatever exists.
downloadnoSet to 1 to receive a Content-Disposition attachment header with a filename derived from the video title.

Formats

formatContent-TypeDescription
jsonapplication/jsonFull structure: video metadata, chosen track, all available tracks, and every segment with millisecond timings
txttext/plainOne continuous block, no timecodes, no line breaks
paragraphstext/plainFragments reassembled into readable paragraphs
txt-timestampstext/plainOne line per caption, prefixed [m:ss]
llmtext/markdownTitle, channel, duration and source URL as a header, then paragraphs with timestamp anchors
srtapplication/x-subripSubRip subtitle file
vtttext/vttWebVTT subtitle file

JSON response

{
  "ok": true,
  "video": {
    "id": "aircAruvnKk",
    "title": "But what is a neural network?",
    "author": "3Blue1Brown",
    "durationSeconds": 1140,
    "thumbnail": "https://i.ytimg.com/vi/…"
  },
  "track": {
    "language": "en",
    "name": "English",
    "generated": false
  },
  "availableTracks": [
    { "language": "en", "name": "English", "generated": false },
    { "language": "es", "name": "Spanish", "generated": false }
  ],
  "segments": [
    { "start": 4200, "dur": 3160, "text": "This is a 3." }
  ]
}

start and dur are milliseconds. dur may be null on the final segment of some tracks, which is how the upstream caption data arrives; treat it as "until the next segment" if you need an end time.

generated: true means the track came from speech recognition rather than a human. Worth surfacing to your users — auto tracks mishear names, jargon and anything spoken over music.

Examples

JavaScript

const res = await fetch(
  'https://youtubegpt.ai/api/transcript?v=aircAruvnKk&format=json'
);
const data = await res.json();
if (!data.ok) throw new Error(data.message);

console.log(data.video.title, data.segments.length + ' segments');

Python

import urllib.request, json

url = "https://youtubegpt.ai/api/transcript?v=aircAruvnKk&format=json"
data = json.load(urllib.request.urlopen(url))

if not data.get("ok"):
    raise RuntimeError(data["message"])

text = " ".join(s["text"] for s in data["segments"])
print(data["video"]["title"], len(text.split()), "words")

Feeding a language model

The llm format exists for exactly this. It ships the title, channel, duration and source URL as a header, so the model is not guessing at context, and puts a timestamp anchor on each paragraph so it can cite specific moments back:

curl -s "https://youtubegpt.ai/api/transcript?v=VIDEO_ID&format=llm" \
  | llm "Summarise this talk in five bullet points, citing timestamps"

Errors

Failures return a non-2xx status with a JSON body carrying a stable code and a human-readable message. Branch on code, display message.

{ "ok": false, "code": "no_captions", "message": "..." }
CodeHTTPMeaning
bad_input400Could not parse a video ID from what you sent
bad_format400format is not one of the supported values
no_captions404The video has no caption track at all
not_found404The video ID does not resolve
login_required451Age-restricted or private; captions unreachable without a signed-in session
unplayable451Blocked, removed, or otherwise unplayable
offline409A live stream that has not finished
empty502A track exists but returned no content
node_unreachable503The extraction node is down — retry shortly

Handle no_captions as a normal outcome

It is not a bug or an outage — plenty of videos genuinely have no caption track, and no tool can produce a transcript from one. This API reads captions that already exist; it does not run speech recognition. Build the empty case into your flow rather than treating it as a failure.

Practical notes

Caching and rate

Successful responses carry Cache-Control: public, max-age=3600, so repeated requests for the same video are cheap. Please cache on your side too. There is no hard published rate limit; extraction is real work against upstream, so batch politely — a short pause between requests rather than firing hundreds in parallel.

CORS

Responses include Access-Control-Allow-Origin: *, so you can call it straight from browser JavaScript without a proxy of your own.

Long videos

No length cap. The longest video in our testing was a 266-minute course, which returned 2,935 segments and 50,862 words in a single response. Allow a generous client timeout for videos of that size.

Rights

The transcript is the video creator's words, and this API does not transfer any rights to them. Whatever you build on top should credit the source video and link back to it.

Frequently asked

Do I need an API key?

No. There is no key, no account and no SDK — it is a plain GET request.

Can I use it in production?

It is a free public endpoint with no uptime guarantee. Cache aggressively, handle the error codes above, and do not build something where a failed transcript fetch breaks your whole product.

How do I get a transcript in a specific language?

Pass lang. Request format=json first if you need to know what exists — availableTracks lists every track on the video.

Can it transcribe a video that has no captions?

No. It reads existing caption tracks. A video with no captions returns no_captions.

How do I fetch many videos?

Call it once per video ID, sequentially or with modest concurrency, and cache the results. There is no batch parameter.

More guides

Independent tool. youtubegpt.ai is not affiliated with, endorsed by, or operated by YouTube or Google. It works with publicly available caption data from YouTube and does not host, mirror or re-upload any video. Transcript text belongs to the original video creators. "YouTube" is a trademark of Google LLC.