Skip to main content

Fetch, clean, and search YouTube transcripts — captions-first (rate-limit resistant) with optional Whisper fallback and an MCP server

Project description

yttranscript-mcp

Fetch, clean, and search YouTube transcripts — captions-first (fast, light, rate‑limit resistant) with an optional local Whisper fallback, an MCP server, a CLI, and an async Python library. No YouTube Data API key required.

Built for feeding transcripts to LLMs: the clean format strips rolling auto‑caption duplication, HTML entities, markup, and timestamps so you spend the fewest tokens possible.

Why it avoids rate limits

  • Captions first, audio last. It pulls YouTube's own caption tracks (a few KB) instead of downloading audio. Whisper only runs when no captions exist.
  • No watch‑page scrape on the hot path. A hardcoded public Innertube key skips the ~1 MB HTML fetch that triggers bot detection.
  • Realistic headers. Every request sends a browser/app User-Agent and language headers (the default python-requests UA is the #1 cause of 429s).
  • Multi‑client fallback. Tries ANDROID_VR → WEB → MWEB → watch‑page until one returns captions, sidestepping client‑specific blocks.
  • Retry/backoff. Transient 429/5xx are retried with exponential backoff + jitter, honoring Retry-After.
  • Escape hatches. YTT_PROXY and YTT_COOKIES_FILE route around IP‑level blocks and age/region gates.
  • Caching. SQLite cache avoids re‑fetching.

Install

pip install yttranscript-mcp            # core: captions + CLI + library
pip install "yttranscript-mcp[mcp]"     # + MCP server
pip install "yttranscript-mcp[whisper]" # + local Whisper fallback (needs ffmpeg)
pip install "yttranscript-mcp[whisper,torch]"  # + GPU

The Whisper fallback needs ffmpeg: winget install ffmpeg (Windows) · brew install ffmpeg (macOS) · sudo apt install ffmpeg (Linux).

CLI

ytt transcript VIDEO_ID                     # clean, LLM-ready text (default)
ytt transcript "https://youtu.be/VIDEO_ID"  # URLs work too
ytt transcript VIDEO_ID -f json             # or text | srt | vtt
ytt transcript VIDEO_ID -o out.txt          # save to file
ytt transcript VIDEO_ID --no-whisper        # captions only, never download audio

ytt batch VID1 VID2 VID3                     # many videos, concurrent
ytt search "python tutorial" -n 5            # search
ytt search "python tutorial" --with-transcripts
ytt cache-stats [--clean]

Python library

import asyncio
from ytt import get_transcript, search, search_and_get_transcripts

async def main():
    # clean = deduplicated, no timestamps — best for LLMs
    r = await get_transcript("dQw4w9WgXcQ", output_format="clean")
    print(r.source, r.language, r.content[:200])

    for v in await search("python tutorial", max_results=5):
        print(v.video_id, v.title)

    for video, transcript in await search_and_get_transcripts("python", max_results=3):
        if transcript:
            print(video.title, "→", transcript.content[:80])

asyncio.run(main())

output_format: clean (default for the CLI/MCP), text, json, srt, vtt, summary.

Local summarization (save tokens)

Compress a transcript to a short summary with a local LLM, so the agent that consumes it ingests a summary instead of the whole transcript. Nothing leaves the machine. Opt-in; needs a local model (default Ollama).

ollama serve
ollama pull qwen3.6:27b      # default — smaller: qwen3:8b, qwen3:4b, qwen3.5:2b
ytt transcript VIDEO_ID --summarize
ytt transcript VIDEO_ID --summarize --summary-model qwen3:8b
from ytt import get_transcript
r = await get_transcript("VIDEO_ID", output_format="summary")
print(r.content)   # bullet-point summary
  • Long transcripts are summarized map-reduce (chunk → reduce) to fit context.
  • YTT_SUMMARY_KEEP_ALIVE keeps the model hot between calls (-1 = forever).
  • YTT_SUMMARY_AUTO_PULL=1 pulls a missing model on demand.
  • YTT_SUMMARY_PROVIDER=openai targets any OpenAI-compatible server (llama.cpp, LM Studio, vLLM) via YTT_SUMMARY_OPENAI_BASE.

MCP server

yttranscript-mcp          # or: python -m ytt.mcp.server

Claude Desktop / Cursor config:

{
  "mcpServers": {
    "yt-transcript": {
      "command": "yttranscript-mcp"
    }
  }
}

Tools: get_transcript, get_transcripts_batch, search_videos (all default to the clean format), summarize_video (local-LLM summary), plus setup_gpu / download_cuda.

Configuration (environment variables)

Everything is tunable without code via YTT_* env vars:

Variable Default Purpose
YTT_PROXY http://user:pass@host:port — route every request through a proxy
YTT_COOKIES_FILE Netscape cookies.txt for age/region‑restricted videos
YTT_MAX_RETRIES 4 Retry attempts on 429/5xx
YTT_RATE / YTT_BURST 1.0 / 5 Client‑side token‑bucket rate limit
YTT_TIMEOUT 15 Per‑request timeout (s)
YTT_CACHE_DB .transcript_cache.db Cache path
YTT_CACHE_TTL_DAYS 7 Cache TTL
YTT_WHISPER_MODEL base tiny/base/small/medium/large
YTT_WHISPER_GPU true Use GPU for Whisper if available
YTT_SUMMARY_PROVIDER ollama ollama or openai (OpenAI-compatible)
YTT_SUMMARY_MODEL qwen3.6:27b Local summary model
YTT_OLLAMA_URL http://localhost:11434 Ollama endpoint
YTT_SUMMARY_KEEP_ALIVE 5m Keep model hot (-1 = forever)
YTT_SUMMARY_AUTO_PULL false Pull missing model on demand

How it works

video id / url → cache → captions (ANDROID_VR → WEB → MWEB → watch page)
                                  ↓ none?
                          Whisper fallback (download audio, transcribe locally)
                                  ↓
                          cache → format (clean / text / json / srt / vtt)

Development

uv sync --extra dev --extra mcp
uv run pytest
uv run ruff check ytt/ && uv run black --check ytt/

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yttranscript_mcp-0.3.0.tar.gz (47.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yttranscript_mcp-0.3.0-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

File details

Details for the file yttranscript_mcp-0.3.0.tar.gz.

File metadata

  • Download URL: yttranscript_mcp-0.3.0.tar.gz
  • Upload date:
  • Size: 47.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yttranscript_mcp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 40837098d7c0a7006b44f0df81333bea25a85663d26a5b7666733ff3eb5dc59e
MD5 c3b5ad52446cd7eeeb9fb05933873624
BLAKE2b-256 63af91201b30f90397cc37d598d3309897d23dd241a23c11363ea3dd8e173382

See more details on using hashes here.

File details

Details for the file yttranscript_mcp-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: yttranscript_mcp-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 48.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yttranscript_mcp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce342a142881f5e123bf9b960aa90d1e9577347dd51115e2888c1334e9cc0eef
MD5 4131cdc538d239dce7d264d7caa8f45f
BLAKE2b-256 b7a72d50d450f3e6d1e0f20072da102e1f353ea322a0e4c8a55c99fc7807caf6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page