Extract, transcribe, and translate YouTube video transcripts using the YouTubeTranscript.dev V2 API. Supports captions, ASR audio transcription, batch proces...
---
name: youtube-transcript-api
description: Extract, transcribe, and translate YouTube video transcripts using the YouTubeTranscript.dev V2 API. Supports captions, ASR audio transcription, batch processing (up to 100 videos), translation to 100+ languages, and multiple output formats. Use when working with YouTube videos, subtitles, captions, or video-to-text conversion.
license: MIT
compatibility: Requires network access to youtubetranscript.dev API. Works with any language or runtime that can make HTTP requests.
metadata:
author: YouTubeTranscript.dev
version: "2.0"
---
# YouTube Transcript API Skill
Use this skill when the user wants to extract transcripts from YouTube videos, transcribe videos without captions, translate video content, or process multiple videos in batch.
## When to Use
- User asks to get a transcript/subtitles/captions from a YouTube video
- User wants to transcribe a YouTube video that has no captions (ASR)
- User wants to translate a YouTube video transcript to another language
- User needs to process multiple YouTube videos at once
- User wants to build an AI/LLM pipeline that uses YouTube video content
- User wants to repurpose video content into text (blog posts, summaries, etc.)
## API Overview
**Base URL:** `https://youtubetranscript.dev/api/v2`
**Authentication:** Bearer token via `Authorization: Bearer YOUR_API_KEY`
Users can get a free API key at [youtubetranscript.dev](https://youtubetranscript.dev).
### Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/v2/transcribe` | Extract transcript from a single video |
| `POST` | `/api/v2/batch` | Extract transcripts from up to 100 videos |
| `GET` | `/api/v2/jobs/{job_id}` | Check status of an ASR job |
| `GET` | `/api/v2/batch/{batch_id}` | Check status of a batch request |
### Request Fields
| Field | Required | Description |
|-------|----------|-------------|
| `video` | Yes (single) | YouTube URL or 11-character video ID |
| `video_ids` | Yes (batch) | Array of IDs or URLs (up to 100) |
| `language` | No | ISO 639-1 code (e.g., `"es"`, `"fr"`). Omit for best available |
| `source` | No | `auto` (default), `manual`, or `asr` |
| `format` | No | `timestamp`, `paragraphs`, or `words` |
| `webhook_url` | No | URL for async delivery (required for `source="asr"`) |
### Credit Costs
| Method | Cost | Speed |
|--------|------|-------|
| Native Captions | 1 credit | 5–10 seconds |
| Translation | 1 credit per 2,500 chars | 5–10 seconds |
| ASR (Audio) | 1 credit per 90 seconds | 2–20 minutes (async) |
## Examples
### Basic Transcript Extraction (Python)
```python
import requests
API_KEY = "your_api_key"
response = requests.post(
"https://youtubetranscript.dev/api/v2/transcribe",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={"video": "dQw4w9WgXcQ"}
)
data = response.json()
for segment in data["data"]["transcript"]:
print(f"[{segment['start']:.1f}s] {segment['text']}")
```
### Basic Transcript Extraction (JavaScript/Node.js)
```javascript
const response = await fetch("https://youtubetranscript.dev/api/v2/transcribe", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ video: "dQw4w9WgXcQ" }),
});
const { data } = await response.json();
console.log(data.transcript);
```
### Using the Node.js SDK
```bash
npm install youtube-audio-transcript-api
```
```javascript
import { YouTubeTranscript } from "youtube-audio-transcript-api";
const yt = new YouTubeTranscript({ apiKey: "your_api_key" });
// Simple extraction
const result = await yt.getTranscript("dQw4w9WgXcQ");
// With translation
const translated = await yt.transcribe({
video: "dQw4w9WgXcQ",
language: "es",
});
// Batch (up to 100 videos)
const batch = await yt.batch({
video_ids: ["dQw4w9WgXcQ", "jNQXAC9IVRw", "9bZkp7q19f0"],
});
```
### Basic Transcript Extraction (cURL)
```bash
curl -X POST https://youtubetranscript.dev/api/v2/transcribe \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video": "dQw4w9WgXcQ"}'
```
### Batch Processing (up to 100 videos)
```bash
curl -X POST https://youtubetranscript.dev/api/v2/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video_ids": ["dQw4w9WgXcQ", "jNQXAC9IVRw", "9bZkp7q19f0"]}'
```
### Translation
Add `"language": "es"` (or any ISO 639-1 code) to get the transcript translated:
```bash
curl -X POST https://youtubetranscript.dev/api/v2/transcribe \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video": "dQw4w9WgXcQ", "language": "es"}'
```
### ASR Transcription (videos without captions)
For videos that don't have captions, use ASR with a webhook:
```bash
curl -X POST https://youtubetranscript.dev/api/v2/transcribe \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video": "VIDEO_ID", "source": "asr", "webhook_url": "https://yoursite.com/webhook"}'
```
This returns immediately with `status: "processing"`. Results are delivered to the webhook URL when ready. Poll with `GET /api/v2/jobs/{job_id}` if not using webhooks.
## Error Handling
| HTTP Status | Error Code | Description |
|-------------|------------|-------------|
| 400 | `invalid_request` | Invalid JSON or missing required fields |
| 401 | `invalid_api_key` | Missing or invalid API key |
| 402 | `payment_required` | Insufficient credits |
| 404 | `no_captions` | No captions available and ASR not used |
| 429 | `rate_limit_exceeded` | Too many requests — check `Retry-After` header |
## Important Notes
- Always ask the user for their API key if they haven't provided one. Free keys are available at [youtubetranscript.dev](https://youtubetranscript.dev).
- Omitting the `language` parameter returns the best available transcript without translation (saves credits).
- ASR is async — always use a webhook URL or poll the jobs endpoint.
- Batch endpoint accepts both YouTube URLs and 11-character video IDs.
- Re-fetching an already-owned transcript costs 0 credits.
## Resources
- [Website](https://youtubetranscript.dev)
- [Full API Docs & OpenAPI Spec](https://youtubetranscript.dev/api-docs)
- [npm SDK](https://www.npmjs.com/package/youtube-audio-transcript-api)
- [Pricing](https://youtubetranscript.dev/pricing)
don't have the plugin yet? install it then click "run inline in claude" again.
restructured original content into implexa's 6-part format, made decision logic explicit for 8 edge cases (auth, rate limits, no captions, timeouts, etc.), documented all inputs with storage guidance, clarified polling behavior and credit costs, and preserved all code examples and endpoints from original.
extract transcripts from youtube videos using the youtubetranscript.dev v2 api. handles native captions, asr transcription for videos without captions, translation to 100+ languages, and batch processing of up to 100 videos in a single request. use this skill when you need to convert video content to text, build llm pipelines with youtube data, or repurpose videos into written formats.
YOUTUBE_TRANSCRIPT_API_KEY or pass directly.dQw4w9WgXcQ) or full youtube url (e.g., https://www.youtube.com/watch?v=dQw4w9WgXcQ).es, fr, de). omit to skip translation and save credits.auto (default), manual (native captions only), or asr (audio transcription). asr requires webhook_url.timestamp (default, includes timecodes), paragraphs (grouped sentences), or words (individual word tokens)./api/v2/jobs/{job_id} works as fallback.external connection: https://youtubetranscript.dev/api/v2
validate and store api key
normalize video input
(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})choose endpoint based on input count
single video transcription request
https://youtubetranscript.dev/api/v2/transcribeAuthorization: Bearer {api_key}, Content-Type: application/json{video: video_id, language: language, source: source, format: format} (omit optional fields if not provided)asr, require webhook_url in body or set polling modebatch video transcription request
https://youtubetranscript.dev/api/v2/batchAuthorization: Bearer {api_key}, Content-Type: application/json{video_ids: video_ids, language: language, source: source, format: format} (omit optional fields if not provided)handle synchronous response (caption-based or manual)
poll async job status (asr or batch)
https://youtubetranscript.dev/api/v2/jobs/{job_id} or /api/v2/batch/{batch_id}Authorization: Bearer {api_key}completed, extract transcript data and proceed to step 8processing, repeat pollingfailed, proceed to step 9 (error handling)format and validate transcript output
timestamp, keep segments as-is with start/duration fieldsparagraphs, group consecutive segments into logical paragraphs (join when gap < 2 seconds)words, flatten all text into individual word tokens with timingerror handling and fallback
if http 401 (invalid_api_key): api_key is missing, malformed, or expired. ask user to verify key at youtubetranscript.dev or generate a new free key. do not retry.
if http 402 (payment_required): account is out of credits. check remaining balance at account dashboard. for free tier, users must wait for daily reset or upgrade. do not retry immediately.
if http 404 (no_captions): video has no native captions and asr was not requested. ask user if they want asr transcription (slower, async, requires webhook) or if they want to try a different video.
if http 429 (rate_limit_exceeded): too many requests sent. check Retry-After response header for wait time (typically 60-300 seconds). implement exponential backoff and retry up to 3 times. after 3 retries, fail with "rate limit exceeded, please try again later".
if http 400 (invalid_request): request json is malformed or missing required fields. check that video_id is 11 chars, video_ids array has 1-100 items, language is iso 639-1 (2 chars), source is one of auto/manual/asr. do not retry; fix input and resubmit.
if network timeout or connection refused: youtubetranscript.dev api is unreachable. retry up to 3 times with 10-second delay. if still failing after 3 retries, report "api service unavailable" and suggest user check status at youtubetranscript.dev.
if transcript array is empty: video exists but has no transcript in requested language. try omitting language parameter (use default/best available) or try source: auto to allow fallback to asr. do not report as error.
if asr job polling times out after 1 hour: long videos or high server load may exceed expected 2-20 minute window. inform user that job is still processing and provide job_id for manual polling later. do not retry automatically.
if source is asr but webhook_url is missing and polling is not available: require one of webhook_url or explicit polling mode. if neither provided, default to polling mode with 5-second intervals.
single video success response (http 200):
{
"success": true,
"data": {
"video_id": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video)",
"transcript": [
{
"start": 0,
"duration": 2.5,
"text": "We're no strangers to love"
},
{
"start": 2.5,
"duration": 3.1,
"text": "You know the rules and so do I"
}
],
"language": "en",
"source": "manual",
"total_duration": 213.5,
"segment_count": 45
}
}
batch request response (http 200 or 202):
{
"success": true,
"batch_id": "batch_xyz789",
"status": "processing",
"data": [
{
"video_id": "dQw4w9WgXcQ",
"status": "completed",
"transcript": [...]
},
{
"video_id": "jNQXAC9IVRw",
"status": "processing",
"transcript": null
}
]
}
asr job status response (http 200):
{
"success": true,
"job_id": "job_abc123",
"status": "completed",
"data": {
"video_id": "dQw4w9WgXcQ",
"transcript": [...],
"source": "asr",
"confidence": 0.92
}
}
error response (http 4xx/5xx):
{
"success": false,
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests",
"retry_after": 120
}
}
all output saved to variable or file as json. if batch processing, results are in array within data field. timestamps are in seconds (float).
text field populated.status: completed in polling response and transcript data is present.language field matches requested language code and text is in that language (spot-check sentences).source field returns asr (not manual) and webhook receives POST or polling confirms status: completed.