One API key works everywhere: call the REST API from your code, script it with the CLI, or give your AI agent transcripts through the hosted MCP server.
25 free credits · 1 credit = 1 video · API access included with every credit pack
Get your first transcript
curl -X POST "https://api.youtubetranscripts.fbetteo.com/api/v1/transcripts/single" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video_url": "https://www.youtube.com/watch?v=pddeyCqevnw"}'The YouTube Data API v3 gives you video, channel, and comment metadata, but its captions endpoint requires OAuth and only downloads caption tracks for videos on channels you manage. For public videos you don’t own, there is no official transcript endpoint.
This API fills that gap: one API key, any public video, channel, or playlist, and the existing captions (creator-uploaded or auto-generated) returned as text. It doesn't transcribe audio, so videos with captions turned off have no transcript.
Send your key in the X-API-Key header. MCP clients send the same key as a Bearer token. Create and revoke keys from your dashboard.
Base URL
texthttps://api.youtubetranscripts.fbetteo.com/api/v1Header
textX-API-Key: YOUR_API_KEYPOST /transcripts/single returns the transcript in the response. Set include_timestamps to true for [MM:SS] markers.
Example response
json{
"video_id": "pddeyCqevnw",
"title": "How To Fine-Tune A Large Language Model (Step-By-Step)",
"transcript": "AI is great at a lot of things. Sounding human is not one of them. ...",
"language": "en",
"character_count": 29173,
"credits_used": 1
}Large sources run as background jobs: start a job, poll its status until download_ready is true, then download one ZIP with every transcript. Jobs that partly fail still return what succeeded and refund the rest.
import time
import requests
BASE_URL = "https://api.youtubetranscripts.fbetteo.com/api/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}
# 1. Start the job (credits are reserved; unused ones are refunded)
job = requests.post(
f"{BASE_URL}/transcripts/channel",
headers=HEADERS,
json={"channel": "@AndrejKarpathy", "max_videos": 25},
).json()
# 2. Poll until results can be downloaded
while True:
status = requests.get(f"{BASE_URL}/jobs/{job['job_id']}", headers=HEADERS).json()
print(f"{status['processed_count']}/{status['total_videos']} videos")
if status["download_ready"]:
break
if status["status"] in ("failed", "cancelled"):
raise RuntimeError(status.get("error_message") or status["status"])
time.sleep(5)
# 3. Download every transcript as one ZIP
zip_file = requests.get(f"{BASE_URL}/jobs/{job['job_id']}/download", headers=HEADERS)
with open("transcripts.zip", "wb") as f:
f.write(zip_file.content)All paths are relative to the base URL. The OpenAPI spec has every request and response field.
| Endpoint | Cost | Description |
|---|---|---|
POST /transcripts/single Transcript for one video, returned immediately. | 1 credit | Transcript for one video, returned immediately. |
POST /transcripts/channel Start a background job for a channel. Optional max_videos (up to 2,000) and formatting options. | 1 credit / video | Start a background job for a channel. Optional max_videos (up to 2,000) and formatting options. |
POST /transcripts/playlist Start a background job for a playlist. | 1 credit / video | Start a background job for a playlist. |
GET /jobs/{job_id} Progress, credits used, and download_ready. | Free | Progress, credits used, and download_ready. |
GET /jobs/{job_id}/download ZIP of all transcripts once download_ready is true. | Free | ZIP of all transcripts once download_ready is true. |
POST /jobs/{job_id}/cancel Stop a job, keep partial results, refund unprocessed videos. | Free | Stop a job, keep partial results, refund unprocessed videos. |
GET /jobs Your recent jobs. Optional limit and status_filter. | Free | Your recent jobs. Optional limit and status_filter. |
GET /channels/{channel}/info Validate a channel before starting a job. | Free | Validate a channel before starting a job. |
GET /channels/{channel}/videos List a channel’s videos to preview what a job will cover. | Free | List a channel’s videos to preview what a job will cover. |
GET /account/credits Remaining credits and API usage for your key. | Free | Remaining credits and API usage for your key. |
Errors return JSON with a "detail" message.
| 400 | Invalid input, such as a malformed URL, or a download requested before the job finished. |
| 401 | Missing X-API-Key header. |
| 402 | Not enough credits for the request. |
| 403 | Invalid, revoked, or expired key, or a job that belongs to another account. |
| 404 | Video, channel, playlist, or job not found. |
| 500 | Unexpected server error. Retry the request; videos that fail inside a job are refunded. |
1 credit = 1 video transcript, through the API, CLI, MCP, or web app. Packs are one-time purchases, credits never expire, and status, list, and download calls are free.
| Pack | Credits | Price | Per 1,000 videos |
|---|---|---|---|
| Starter | 100 | $4.99 | $49.90 |
| Plus | 400 | $6.99 | $17.48 |
| Pro | 1,000 | $12.99 | $12.99 |
| Business | 3,000 | $26.99 | $9.00 |
| Scale | 10,000 | $78 | $7.80 |
| Enterprise | 25,000 | $185 | $7.40 |
New accounts get 25 free credits. Jobs reserve credits up front and refund videos that fail on our side.
The CLI and the hosted MCP server use the same key and credits as the REST API.
MCP tools
Works with Claude Code and other MCP clients over HTTP, or locally with npx youtube-transcript-agent mcp.
Agent setup guides
Remote and local MCP setup for Claude Code, plus CLI usage for scripts and agents.
Use with agentsCommon questions about the YouTube Transcript API.
Not for videos you don’t own. The YouTube Data API v3 captions endpoint requires OAuth and only lets you download caption tracks for videos on channels you manage. This API returns the existing captions of any public video with just an API key.
Each video transcript costs 1 credit, whether it comes from /transcripts/single or a channel or playlist job. Credit packs are one-time purchases that never expire, from $4.99 for 100 credits to $185 for 25,000. New accounts get 25 free credits.
Yes. Inside a job, a video with no captions, or one that is private or unavailable, still uses its credit. Failures on our side, such as network or proxy errors, and videos never processed before a cancel or timeout are refunded.
Up to 10,000 videos per channel or playlist job. Pass max_videos (up to 2,000) to process only part of a large channel.
No. The API returns the captions YouTube already has, creator-uploaded or auto-generated. It does not run speech-to-text on audio.
Yes. Set include_timestamps to true and each line starts with its [MM:SS] time. Channel and playlist jobs also accept options for the video title, ID, URL, and view count, or one combined file.
1 credit = 1 video transcript. Credit packs are one-time purchases that never expire, and every pack includes API access.
Need higher volume? Email us
Questions? Email [email protected]
Follow me on @franbetteo
Not affiliated with YouTube or Google.
© 2026 downloadyoutubetranscripts.com