YouTube subtitles API & MCP server
Pull YouTube subtitles, transcripts, translations and generated articles from your own code or from an AI agent. Two ways in: a plain REST API, or an MCP server you can connect to Claude Code, Claude.ai and Cursor.
Quickstart
Create an API key, then call the API with it. Manage your keys →
curl -X POST https://api.unwatched.click/api/v1/subtitles \
-H "Authorization: Bearer unw_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","lang":"en"}'Authentication
Every request needs your API key. Both header forms work — MCP clients can only set Authorization, while x-api-key is handier for curl. Keys are stored hashed: if you lose one, revoke it and create another.
Authorization: Bearer unw_sk_YOUR_KEY
# or, equivalently:
x-api-key: unw_sk_YOUR_KEYMCP server
The MCP endpoint is POST https://api.unwatched.click/mcp. Nothing to install — add the URL and your key to any MCP client. In Claude Code:
claude mcp add --transport http unwatched https://api.unwatched.click/mcp \
--header "Authorization: Bearer unw_sk_YOUR_KEY"In Claude.ai: Settings → Connectors → add a custom connector with the same URL and header. In Cursor, add this to mcp.json:
{
"mcpServers": {
"unwatched": {
"url": "https://api.unwatched.click/mcp",
"headers": {
"Authorization": "Bearer unw_sk_YOUR_KEY"
}
}
}
}Available tools
get_video_subtitles— the full transcript with timestampslist_subtitle_tracks— which subtitle languages a video hasget_video_info— title, duration, thumbnail, publish dateget_video_frame— still frame at a timestamp, returned as an imagetranslate_transcript— translate a fetched transcript, keeping timestampssummarize_video— generate a structured article from a videosearch_articles— search articles already generated on the site
REST endpoints
POST /api/v1/subtitles { url | videoId, lang? }
GET /api/v1/videos/:videoId
GET /api/v1/videos/:videoId/tracks
POST /api/v1/frames { url | videoId, t | timestamps[], width?, includeBase64? }
GET /api/v1/videos/:videoId/frame?t=&width=
POST /api/v1/transcripts/translate { videoId, sourceLang, targetLang }
POST /api/v1/summaries { url | videoId, lang, length?, sourceLang? }
GET /api/v1/articles?query=&category=&lang=&page=&limit=
GET /api/v1/creditsTranscripts come back as segments of { start, end, text }, in seconds — end times let you cite exact spans.
Credits
API and MCP calls spend the same credits as the website, and every account gets a free daily allowance. Cached results are free: fetching the same video and language again costs nothing.
| Operation | Price |
|---|---|
| Get subtitles (cache miss) | 2 credits |
| Standard summary | 1 credits / hour |
| ट्रांसक्रिप्ट अनुवाद | 1 credits / hour |
| वीडियो स्क्रीनशॉट | 1 credits |
| Metadata, track list, article search | Included |
Errors
Failures always return { "error": { "code", "message" } }, so you only need to parse one shape.
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST | Missing or malformed parameters. |
| 401 | INVALID_API_KEY | Key missing, invalid, revoked or expired. |
| 402 | INSUFFICIENT_CREDITS | Not enough credits for this operation. |
| 404 | TRANSCRIPT_NOT_FOUND | No stored transcript — fetch subtitles first. |
| 422 | NO_SUBTITLES | This video has no usable subtitles. |
| 429 | RATE_LIMITED | Too many requests. Default limit is 60 per minute per key. |
| 502 | EXTRACTION_FAILED | Subtitle extraction failed for this video. |
| 503 | SERVICE_BUSY | Extraction capacity saturated. Retry shortly. |

