Fetch transcripts from YouTube videos. Version 0.2.0. This file is generated by yt-transcript describe --skill; edit the manifest, not the copy.
Check the CLI is there
Run yt-transcript describe first. If the command is not found, install it:
uv tool install git+https://github.com/sleeplessv/youtube-transcript
# no uv on this machine
pip install git+https://github.com/sleeplessv/youtube-transcript
Both need network access to GitHub. If neither install works, say so and stop; there is no offline path to a transcript.
How it behaves
- stdout carries the payload and nothing else. Progress and errors go to stderr, so
> fileis always safe. - Text output is the default. Pass --json for a machine-readable envelope.
- Language selection is strict: asking for a language you cannot have is an error, never a silent substitution.
- Every error names the command that will get you unstuck. Read the hint before guessing.
Commands
fetch
Fetch the transcript of one video in one language.
video: YouTube URL (watch, youtu.be, shorts, embed, live) or bare 11-character video ID.-l, --language: Language code to fetch. Defaults to 'en'. Fails if that exact language has no track.-o, --output: Write to this file instead of stdout.--no-timestamps: Text output only: drop the [MM:SS] prefixes.--clean: Text output only: strip residual HTML tags and collapse whitespace.--json: Emit JSON on stdout instead of human-readable text.--proxy: Route requests through an HTTP/SOCKS proxy. Use this when you hit theblockederror.
Output fields:
video_id: stringlanguage: string, the human-readable name of the track that answeredlanguage_code: string, e.g. 'en'kind: one of manual, generated, translatedsnippet_count: integerduration_seconds: float, end of the last snippettext: string, the whole transcript with whitespace collapsedsnippets: array of {text, start, duration}; start and duration are seconds
yt-transcript fetch 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
yt-transcript fetch dQw4w9WgXcQ --json > transcript.json
yt-transcript fetch dQw4w9WgXcQ --clean --no-timestamps
yt-transcript fetch dQw4w9WgXcQ -l de
languages
List every track on a video and what it can be translated into. Run this first when fetch reports language_unavailable.
video: YouTube URL (watch, youtu.be, shorts, embed, live) or bare 11-character video ID.--json: Emit JSON on stdout instead of human-readable text.--proxy: Route requests through an HTTP/SOCKS proxy. Use this when you hit theblockederror.
Output fields:
video_id: stringtracks: array of {language_code, language, kind, translatable}translation_targets: array of language codes YouTube will translate into (--json only; text output shows a count)
yt-transcript languages dQw4w9WgXcQ
yt-transcript languages dQw4w9WgXcQ --json
translate
Machine-translate an existing track into another language.
video: YouTube URL (watch, youtu.be, shorts, embed, live) or bare 11-character video ID.--to: Target language code. Required.--from: Source track to translate from. Defaults to 'en'.-o, --output: Write to this file instead of stdout.--no-timestamps: Text output only: drop the [MM:SS] prefixes.--clean: Text output only: strip residual HTML tags and collapse whitespace.--json: Emit JSON on stdout instead of human-readable text.--proxy: Route requests through an HTTP/SOCKS proxy. Use this when you hit theblockederror.
Output fields:
video_id: stringlanguage: string, the human-readable name of the track that answeredlanguage_code: string, e.g. 'en'kind: always 'translated'snippet_count: integerduration_seconds: float, end of the last snippettext: string, the whole transcript with whitespace collapsedsnippets: array of {text, start, duration}; start and duration are seconds
yt-transcript translate dQw4w9WgXcQ --to es
yt-transcript translate dQw4w9WgXcQ --from de --to fr --json
describe
Print this manifest as JSON, or agent instructions as Markdown.
--skill: Print Markdown instructions for an agent instead of JSON.
yt-transcript describe
yt-transcript describe --skill > .claude/skills/yt-transcript/SKILL.md
When a command fails
The exit code says what went wrong and the message on stderr says what to do next. Read it before you retry with different arguments.
0: success1: unknown: an unrecognised failure. The message is passed through from the underlying library.2: invalid_input: the argument was not a usable URL or video ID.3: video_unavailable: private, deleted, age-restricted, or otherwise unplayable.4: transcripts_disabled: the uploader turned captions off. Nothing will fix this.5: language_unavailable: no track in that language. Runlanguagesnext.6: not_translatable: that track cannot be translated, or not into that target. Runlanguagesnext.7: blocked: YouTube is refusing this IP. Retry from a residential connection or pass --proxy.