Ir para o conteúdo

YouTube transcript API

Send a YouTube link, get the captions back as JSON with timestamps. One endpoint, API keys you can revoke at any time, and errors you can handle in code.

Quick start

  1. Create a key on your account page. API access is part of the Pro plan.
  2. Copy the key right away. It starts with qt_live_ and is shown only once.
  3. Store it in an environment variable and send it as a Bearer token.
curl
curl -X POST https://querytube.com/api/v1/transcript \
  -H "Authorization: Bearer $QUERYTUBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
JavaScript (Node.js)
// Node.js 18 or newer. Run this on your server, never in browser code.
const response = await fetch("https://querytube.com/api/v1/transcript", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.QUERYTUBE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }),
});

const body = await response.json();

if (!response.ok) {
  // body.error.code is stable: handle it in code. body.error.message is for people.
  throw new Error(`${body.error.code}: ${body.error.message} (${body.error.requestId})`);
}

for (const line of body.data.segments) {
  console.log(`[${line.start}s] ${line.text}`);
}
console.log(`${body.quota.used} of ${body.quota.limit} requests used this month`);

Python example

Coming from the open-source youtube-transcript-api package? The request is a plain HTTPS call, so all you need is requests. The response has the same fields as in the JavaScript example.

Python
# Python 3 with the requests package (pip install requests).
import os
import requests

response = requests.post(
    "https://querytube.com/api/v1/transcript",
    headers={"Authorization": f"Bearer {os.environ['QUERYTUBE_API_KEY']}"},
    json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
    timeout=60,
)
body = response.json()

if not response.ok:
    # body["error"]["code"] is stable: handle it in code.
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")

for line in body["data"]["segments"]:
    print(f"[{line['start']}s] {line['text']}")

Authentication

Send your key in the Authorization header as Bearer qt_live_.... Keys are never accepted in the URL or the body. We store only a hash of each key, so we cannot show it again: if you lose a key, revoke it and create a new one. You can have up to 5 active keys, for example one per application, and revoking a key stops it working immediately.

Get a transcript

POST https://querytube.com/api/v1/transcript with a JSON body that has one field, url: a YouTube video link (watch, youtu.be, Shorts, live or embed). The answer is JSON. Times are seconds from the start of the video.

200 OK
{
  "data": {
    "platform": "youtube",
    "videoId": "dQw4w9WgXcQ",
    "title": "Video title",
    "durationSec": 212,
    "language": "en",
    "source": "captions",
    "isAutoGenerated": false,
    "segments": [
      { "start": 0, "end": 3.2, "text": "First caption line" },
      { "start": 3.2, "end": 6.8, "text": "Second caption line" }
    ]
  },
  "quota": { "used": 1, "limit": 10000, "resetsAt": "2026-12-01T00:00:00.000Z" },
  "requestId": "req_..."
}

language is the language of the captions. isAutoGenerated is true when YouTube made the captions with speech recognition. Titles and caption text come from YouTube: treat them as untrusted text and never insert them into a page as HTML.

Rate limit and monthly quota

  • Rate limit: 60 requests per minute for each key, and 120 per minute for your whole account. Over a limit you get 429 rate_limited and a Retry-After header with the seconds to wait.
  • Monthly quota: 10,000 requests per calendar month (UTC), shared by all the keys of your account. Over the quota you get 429 quota_exceeded, the quota object and a Retry-After until the quota resets on the 1st.
  • Every successful answer has X-Quota-Limit, X-Quota-Remaining and X-Quota-Reset headers, and the same numbers in quota.
  • A request that fails on our side or at YouTube (502, 503, 504, 500) is given back, up to 50 a day. A video without captions or an unavailable video still counts, because we had to look it up.
  • Sending more than 300 requests with bad keys in a minute from one address makes us answer 429 for that address for a minute.

Errors

Every error has the same shape. Branch on error.code, which will not change; the message is for people. Quote requestId when you contact support.

429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 86400

{
  "error": {
    "code": "quota_exceeded",
    "message": "The monthly request quota is used up.",
    "requestId": "req_...",
    "retryAfterSec": 86400,
    "quota": { "used": 10000, "limit": 10000, "resetsAt": "2026-12-01T00:00:00.000Z" }
  }
}
StatusCodeMeaning
401missing_api_keySend your API key as 'Authorization: Bearer qt_live_...'.
401invalid_api_keyThe API key is not valid. It may have been revoked.
403plan_requiredAPI access needs a Pro plan.
429rate_limitedToo many requests. Wait for Retry-After seconds.
429quota_exceededThe monthly request quota is used up.
400invalid_inputThe request body must be JSON like {"url": "..."}.
400invalid_urlThat is not a valid video URL.
400unsupported_platformOnly YouTube video links are supported by the API.
415unsupported_media_typeSend the body as application/json.
413payload_too_largeThe request body is too large.
404no_captionsThis video has no captions.
404video_unavailableThis video is private, removed or unavailable.
502upstream_errorYouTube could not be reached. Try again.
504timeoutYouTube took too long to answer. Try again.
503service_unavailableThe service is temporarily unavailable.
500internal_errorSomething went wrong on our side.

Keep your key safe

  • Call the API from your server only. It sends no CORS headers, on purpose.
  • Keep keys in environment variables or a secrets manager, not in source code.
  • If a key may have leaked, revoke it on your account page. It stops working immediately.

Frequently asked questions

Which videos does the API support?

YouTube videos that have captions, either written by the creator or generated automatically. Links from other platforms are not supported by the API yet.

Who can use the API?

API access is part of the Pro plan. Create keys on your account page, and revoke them there when you no longer need them.

Does a failed request use up my quota?

A request that fails on our side or at YouTube (502, 503 or 504) is given back, up to a daily limit. A video that has no captions or is unavailable still counts, because we had to look it up.

Is this the youtube-transcript-api Python package?

No. That is a separate open-source library you run yourself. This is a hosted API: you send an HTTPS request with your key and get JSON back, from Python, JavaScript or any language. The Python example on this page shows the same request.

Can I call the API from a web page?

No. Calling it from browser code would expose your key to every visitor, so the API does not allow cross-origin requests. Call it from your server and pass the result to your page.