One API call. Timestamped JSON. No proxy setup, no RequestBlocked errors, no credits vanishing at midnight. Extract any YouTube transcript in your language, your format. Call it from Python, JavaScript, PHP, or plain curl — anything that speaks HTTP.
# 1 credit · enqueue, then poll until completed curl -X POST https://api.youtubetranscripts.co/v1/transcript \ -H "Authorization: Bearer yt_live_••••••••" \ -d '{"url":"https://youtu.be/dQw4w9WgXcQ","format":"json"}' # 202 queued → poll GET /v1/transcript/:id → completed { "status": "completed", "video_id": "dQw4w9WgXcQ", "result": { "language": "en", "source": "native_captions", "credits_used": 1, "credits_remaining": 99, "segments": [ { "start": 1.36, "duration": 1.68, "text": "We're no strangers to love" } ] } }
“Deployed to Railway Sunday night. Got RequestBlocked within the hour. Client demo Monday morning.”- Actual developer, actual Slack message
The open-source youtube-transcript-api library is brilliant on localhost. The moment it hits a cloud IP - AWS, GCP, Railway, Render, Vercel - YouTube sees it and blocks it. Every time.
So you spend a weekend on proxy rotation. Then the proxies get flagged. Then YouTube updates something and the whole thing breaks again. This is not a problem worth solving yourself.
No infrastructure to manage. No proxies to rotate. No YouTube bot detection to battle. Just a clean YouTube Transcript API that returns what you need.
Create an account with your email and password, confirm via the verification link, then generate an API key in your dashboard. No credit card, no approval queue.
Pass any public YouTube URL. Choose your language and format (json, text, srt, vtt). Whisper fallback runs automatically when a video has no captions.
Timestamped segments, word count, balance remaining, video metadata - all in one response. Pipe it straight into your LLM, vector DB, or content pipeline.
Native caption extraction is fast, and anything we've fetched before is served straight from cache — often before your UI spinner completes its first rotation.
Every segment returns start and duration in seconds. Build transcript viewers, chapter markers, and searchable archives.
Buy once. Use whenever. No monthly resets, no “use it or lose it” anxiety.
Video has no captions? We run OpenAI Whisper automatically — no flag needed (or set native_only=true to skip it). 1 credit per video-minute. Response includes source: "whisper".
Auto-detect or pass an ISO-639 code. 45 languages supported, with optional translation.
Choose json, text, text-timestamps, srt, or vtt. Works as a YouTube captions API, subtitles API, or raw transcript source.
Title, channel, duration, and thumbnail — bundled with every transcript call at no extra cost. Never a separate API hit.
Handles proxy rotation, IP management, and YouTube changes automatically. No more RequestBlocked errors on AWS, GCP, or Railway.
The same API. Six completely different products.
Feed transcripts into your vector DB. Let users ask questions about any video. Build knowledge bases from entire channels in hours.
One 20-minute video becomes a blog post, 10 tweets, a newsletter section, and show notes. No manual copy-paste.
Track what's being said about your brand across YouTube at scale. Mine transcripts for signals competitors haven't noticed.
Meet ADA, WCAG, and EU accessibility mandates. AI fallback generates captions even when YouTube doesn't provide them.
Search engines can't watch video. Publish the full transcript alongside each video. More text means more index surface.
Process entire channels or curated playlists. Clean JSON straight into your labelling pipeline. Up to 100 videos per batch call.
A plain REST API, an MCP server, and no-code connectors — all from one API key. No SDK lock-in.
import time, requests API = "https://api.youtubetranscripts.co" headers = {"Authorization": "Bearer yt_your_key"} # Enqueue — 1 credit, native captions job = requests.post(f"{API}/v1/transcript", json={"url": "https://youtu.be/VIDEO_ID", "language": "en", "format": "json"}, headers=headers).json() # Poll until status == "completed" res = requests.get(f"{API}/v1/transcript/{job['id']}", headers=headers).json() data = res["result"] # segments carry start + duration (seconds) for seg in data["segments"]: print(f"{seg['start']}s → {seg['text']}") print(data["source"], data["credits_remaining"])
const API = 'https://api.youtubetranscripts.co' const headers = { Authorization: 'Bearer yt_your_key', 'Content-Type': 'application/json', } // Enqueue — 1 credit const job = await (await fetch(`${API}/v1/transcript`, { method: 'POST', headers, body: JSON.stringify({ url: 'https://youtu.be/VIDEO_ID', format: 'json' }), })).json() // Poll GET /v1/transcript/:id until status === 'completed' const res = await (await fetch(`${API}/v1/transcript/${job.id}`, { headers })).json() console.log(res.result.transcript, res.result.credits_remaining)
$ch = curl_init("https://api.youtubetranscripts.co/v1/transcript"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer yt_your_key", "Content-Type: application/json"], CURLOPT_POSTFIELDS => json_encode(["url" => "https://youtu.be/VIDEO_ID", "format" => "json"]), ]); $job = json_decode(curl_exec($ch), true); // Poll GET /v1/transcript/{id} until status == "completed" echo $job["id"];
# Enqueue a transcript (1 credit) curl -X POST https://api.youtubetranscripts.co/v1/transcript \ -H "Authorization: Bearer yt_your_key" \ -d '{"url":"https://youtu.be/VIDEO_ID","format":"json"}' # Poll until status is "completed" curl https://api.youtubetranscripts.co/v1/transcript/REQUEST_ID \ -H "Authorization: Bearer yt_your_key" # Bulk — a playlist, a channel, or up to 100 URLs curl -X POST https://api.youtubetranscripts.co/v1/transcripts/bulk \ -H "Authorization: Bearer yt_your_key" \ -d '{"urls":["ID_1","ID_2","ID_3"]}' # Remaining balance curl https://api.youtubetranscripts.co/v1/credits \ -H "Authorization: Bearer yt_your_key"
Pull transcripts directly inside Claude conversations via MCP
Transcribe YouTube from your code editor, no context switching
MCP server installs in under 30 seconds
The only YouTube Transcript API with never-expire credits, AI fallback, and no subscription. Get YouTube transcripts in production without IP blocks or broken scrapers.
| Provider | Credits expire? | AI fallback | No subscription | Entry price | Works in production? |
|---|---|---|---|---|---|
| YouTubeTranscripts.co us | ✓ Never expire | ✓ Whisper | ✓ Pay once | $5 for 300 | ✓ Always |
| Supadata | ⚠ Monthly reset | ✓ | ✗ Sub only | $5/mo → 300 | ⚠ Intermittent |
| ScrapeCreators | ✓ Never expire | ✓ | ✓ | $10 for 1,000 | ✓ |
| TranscriptAPI.com | ⚠ End of period | ✗ | ✗ Sub only | ~$10/mo | ✓ |
| Transcribr.io | ⚠ 6-month limit | ✗ | ✓ | $9 for 500 | ✗ |
| Open-source library | N/A - free | ✗ | ✓ | $0 | ✗ Blocked by cloud IPs |
No subscriptions. No resets. No auto-charge. Credits stack - buy multiple packs and balances combine.
requests — no SDK to install. POST to /v1/transcript with an Authorization: Bearer header and a video URL. The API is asynchronous: you get back a queued request, then poll GET /v1/transcript/{id} until status is completed. The result holds transcript, a segments array (each with start and duration in seconds), language, source, and credits_remaining. Full examples in the API docs.source: "whisper" so you always know which path ran. Set native_only: true to skip Whisper and fail fast instead. On the free tier (native captions only), uncaptioned videos return a clear error.fetch or axios works in Node.js 18+, Bun, and Deno with full async/await. POST to /v1/transcript and poll GET /v1/transcript/{id} until it's complete. There's also an MCP server for Claude Desktop, Cursor, and Windsurf - pull YouTube transcripts inside your AI assistant without writing any HTTP calls.X-RateLimit-Limit, -Remaining, and -Reset headers plus credits_remaining — so you never need a separate balance call.A YouTube Transcript API is a programmatic interface for extracting the text content of YouTube videos: auto-generated captions, manually uploaded subtitles, and AI-generated transcriptions for uncaptioned videos. It is also commonly referred to as a YouTube captions API or YouTube subtitles API — all three terms describe the same underlying capability. YouTube's official Data API v3 does not expose transcripts to third-party developers, so every service in this category works by accessing YouTube's public caption infrastructure directly.
The key differences between providers are: reliability in cloud environments, pricing model, and what happens when a video has no captions. The open-source youtube-transcript-api Python library is the most popular starting point, but it fails consistently when deployed to cloud providers because YouTube blocks their IP ranges.
Common production use cases include:
There's no SDK to install — it's a plain REST API you call with requests. Enqueue a request, poll until it's done, and get structured data back with timestamps and metadata included.
The response includes credits_remaining in every call. You never need a separate balance endpoint. Full API reference at the API docs.
100 free credits. No card. No subscription. Credits that actually stay in your account.
Get Started Free →No credit card. No subscription. Free credits never expire.