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_KEY

MCP 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 timestamps
  • list_subtitle_tracks — which subtitle languages a video has
  • get_video_info — title, duration, thumbnail, publish date
  • get_video_frame — still frame at a timestamp, returned as an image
  • translate_transcript — translate a fetched transcript, keeping timestamps
  • summarize_video — generate a structured article from a video
  • search_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/credits

Transcripts 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.

OperationPrice
Get subtitles (cache miss)2 credits
Standard summary1 credits / hour
자막 번역1 credits / hour
동영상 스크린샷1 credits
Metadata, track list, article searchIncluded

Errors

Failures always return { "error": { "code", "message" } }, so you only need to parse one shape.

StatusCodeMeaning
400INVALID_REQUESTMissing or malformed parameters.
401INVALID_API_KEYKey missing, invalid, revoked or expired.
402INSUFFICIENT_CREDITSNot enough credits for this operation.
404TRANSCRIPT_NOT_FOUNDNo stored transcript — fetch subtitles first.
422NO_SUBTITLESThis video has no usable subtitles.
429RATE_LIMITEDToo many requests. Default limit is 60 per minute per key.
502EXTRACTION_FAILEDSubtitle extraction failed for this video.
503SERVICE_BUSYExtraction capacity saturated. Retry shortly.