# Yt Transcript

> Fetch the transcript of a YouTube video from the command line. Use when a prompt carries a YouTube URL or an 11-character video ID and asks for the transcript, the captions, what was said in the video, a summary of the video, a caption track in a particular language, or a translated transcript.

- Skill: `sleeplessv/yt-transcript` (Agent Skill)
- Install (CLI): `npx skillmds@latest add sleeplessv/yt-transcript`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sleeplessv/yt-transcript/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: sleeplessv (https://skillmd.com/u/sleeplessv)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/sleeplessv/yt-transcript

---


# yt-transcript

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:

```bash
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 `> file` is 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 the `blocked` error.

Output fields:

- `video_id`: string
- `language`: string, the human-readable name of the track that answered
- `language_code`: string, e.g. 'en'
- `kind`: one of manual, generated, translated
- `snippet_count`: integer
- `duration_seconds`: float, end of the last snippet
- `text`: string, the whole transcript with whitespace collapsed
- `snippets`: array of {text, start, duration}; start and duration are seconds

```bash
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 the `blocked` error.

Output fields:

- `video_id`: string
- `tracks`: array of {language_code, language, kind, translatable}
- `translation_targets`: array of language codes YouTube will translate into (--json only; text output shows a count)

```bash
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 the `blocked` error.

Output fields:

- `video_id`: string
- `language`: string, the human-readable name of the track that answered
- `language_code`: string, e.g. 'en'
- `kind`: always 'translated'
- `snippet_count`: integer
- `duration_seconds`: float, end of the last snippet
- `text`: string, the whole transcript with whitespace collapsed
- `snippets`: array of {text, start, duration}; start and duration are seconds

```bash
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.

```bash
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`: success
- `1`: 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. Run `languages` next.
- `6`: not_translatable: that track cannot be translated, or not into that target. Run `languages` next.
- `7`: blocked: YouTube is refusing this IP. Retry from a residential connection or pass --proxy.


