Captions API for public YouTube videos

The YouTube transcript API that never guesses.

Get a YouTube transcript from any public video URL in one API call. Name the language and the caption source, and that exact track comes back as JSON, plain text, SRT, or WebVTT. No silent language fallback, and no speech recognition standing in for captions that were never published.

The exact track, or an error
Ask for manual Spanish captions and you get manual Spanish captions. If that track is not published, you get track_not_available and no charge.
Proof attached to every transcript
Track ID, caption kind, observation time, source market, cache status, and a SHA-256 of the content.

Interactive demo: find and pick a caption track

Live demo · paste a YouTube URLPOST /v1/transcripts

This demo runs on sample fixtures inside your browser, so any YouTube link resolves to one of them. The real API answers the same shapes.

Billing, retries, and batches

Cache hit or miss

One price either way

A completed caption track costs one credit. A cached YouTube transcript comes straight back from storage at the same price as a fresh extraction.

Failed requests

Zero credits

No captions, private video, upstream refusal, our own fault: the request is free and the reason is a machine-readable error code.

Safe retries

Idempotency-Key

Replay the same key with the same body and the original transcript comes back. A different body returns 409. A timeout never bills you twice.

Bulk transcripts

1,000 videos per batch

Send explicit video inputs, reserve credits atomically, read per-item status, and page through the finished items.

How to get a YouTube transcript in one call.

The POST commits your request before it waits. If the selected track finishes inside the wait budget you get HTTP 200 and the transcript. If it does not, you get HTTP 202 with the same transcript ID and a poll URL. Nothing is charged twice, and a subtitle download is a separate free call.

Ask for the track you want

Send the YouTube URL plus language preferences and caption kinds, or an exact track_id returned by an earlier call.

Take the answer

HTTP 200 with the finished transcript, or 202 with poll_url and Retry-After. One schema in both, and in every batch item.

HTTP/1.1 202 Accepted
Retry-After: 3

{ "id": "tr_9Qv…",
  "status": "processing",
  "poll_url": "/v1/transcripts/tr_9Qv…" }

Download SRT or WebVTT

Optional. The same stored artifact renders as JSON, plain text, SRT, or WebVTT. Downloads cost no credits.

GET /v1/transcripts/tr_9Qv…/content?format=srt
GET /v1/transcripts/tr_9Qv…/content?format=vtt

One schema. Four downloads.

Every YouTube transcript comes back as segments with start_ms, duration_ms, and text. The four formats are renderings of that one artifact, so your subtitle file and your search index never disagree.

  • jsonThe full transcript resource: selected track, available tracks, retrieval provenance, credits used.
  • textPlain reading copy for embeddings, summarizers, RAG pipelines, and full-text search.
  • srtNumbered cues with comma milliseconds, for video editors and players.
  • vttWebVTT for the browser <track> element and accessibility work.
Same track, four renderings

Pull your first YouTube transcript today.

Create an account, take an API key, and spend one credit on the caption track you named. Failed requests cost nothing, so a bad video ID costs you nothing but a retry.

Get an API keyRead the API docs