Skip to content

Repository files navigation

yt2md

Dump a YouTube video's transcript as Markdown.

Fetches the transcript (no API key needed), looks up the video title, and emits a Markdown document with a metadata header. By default the transcript is rendered as flowing paragraphs; pass --timestamps for one timestamped line per snippet, or --claude to reflow the raw transcript into readable prose with claude -p.

Install

uv sync            # dev setup inside the repo
# or as a tool:
uv tool install .

Usage

yt2md "https://www.youtube.com/watch?v=jNQXAC9IVRw"     # flowing paragraphs to stdout
yt2md jNQXAC9IVRw -o transcript.md                      # bare ID, write to file
yt2md "https://youtu.be/jNQXAC9IVRw" --timestamps       # one timestamped line per snippet
yt2md "https://youtu.be/jNQXAC9IVRw" --claude           # reflow into prose via claude -p
yt2md "https://www.youtube.com/watch?v=..." -l it,en    # language preference order

Accepted inputs: bare 11-character video IDs and watch, youtu.be, shorts, embed, live URLs on any youtube.com subdomain (www., m., music., ...).

Options

Flag Meaning
-l, --languages Comma-separated language codes in order of preference (default: en)
--timestamps One timestamped line per snippet instead of the default flowing paragraphs
--claude Consolidate the transcript into readable prose via claude -p (see below)
-o, --output Write to a file instead of stdout

--claude

The default paragraph mode preserves the raw transcript wording, broken every ~minute of video. --claude instead pipes the transcript into claude -p, which restores punctuation, joins fragments into complete sentences, and groups them into thematic paragraphs, without summarising or altering meaning. It requires the claude CLI on your PATH; if it is missing or fails, yt2md prints a yt2md: warning: ... line and falls back to the raw paragraphs, so the run still succeeds. Because the reflowed prose has no per-snippet positions, --claude overrides --timestamps when it succeeds.

Output format

The document header is the same in every mode; only the ## Transcript body differs. With --timestamps:

# Me at the zoo

- **Source:** <https://www.youtube.com/watch?v=jNQXAC9IVRw>
- **Language:** English (en, manual)

## Transcript

**[00:01]** All right, so here we are, in front of the elephants

Without it (the default), the body is flowing paragraphs of the same text; with --claude, it is that text reflowed into punctuated prose.

Exit code is 0 on success, 1 on bad input or when no transcript is available (disabled subtitles, unavailable video, no matching language), and 2 for a usage error (missing argument, empty --languages).

Claude Code skill

A Claude Code skill turns yt2md into a one-line /yt2md command that fetches a transcript and then acts on it with a free-form prompt:

/yt2md <video-url-or-id> [prompt]
  • /yt2md jNQXAC9IVRw — no prompt: a structured summary (TL;DR + key points).
  • /yt2md jNQXAC9IVRw draft a LinkedIn post — the prompt drives the output.
  • /yt2md jNQXAC9IVRw where does he mention the trunks? — position-style prompts fetch with --timestamps so answers can cite [MM:SS].

The skill runs a globally installed yt2md if present, otherwise it falls back to uvx --from git+https://github.com/mauromedda/yt2md yt2md, so no manual install is required. Everything is grounded in the transcript; the skill never answers from the title alone.

Install it by copying skill/SKILL.md to ~/.claude/skills/yt2md/SKILL.md (personal, available everywhere) or to .claude/skills/yt2md/SKILL.md inside a project.

Robustness

Adversarial testing shaped the error handling; the tool aims to fail cleanly, never with a stack trace, on the following:

  • Environment errors (unwritable -o path, output to a directory, a closed pipe such as | head, a non-UTF-8 terminal) print a single yt2md: error: ... line.
  • Library errors surface their one-line cause (e.g. Subtitles are disabled for this video) rather than the multi-line boilerplate.
  • Hostile transcript or video-title content (embedded newlines, markdown metacharacters) is neutralized so it cannot inject fake headers or metadata into the document.
  • Non-finite or negative snippet timestamps render as 00:00.
  • A bare video ID beginning with - is accepted (e.g. yt2md -wtIMTCHWuI).

Legal & responsible use

This is not legal advice. Read this before you use yt2md.

yt2md fetches transcripts through the youtube-transcript-api library, which reads YouTube's internal (undocumented) caption endpoints rather than the official YouTube Data API. That has consequences you should understand:

  • YouTube Terms of Service. YouTube's ToS prohibit accessing content by automated means except through the API or the embeddable player. Fetching captions this way is very likely a violation of those terms. The practical enforcement is technical and account-level (rate limiting, IP blocks, or a ban on the Google account associated with the requests), not criminal.
  • Copyright. A transcript is the spoken content of a copyrighted work. yt2md downloads it locally and never hosts, republishes, or redistributes anything, which keeps personal use low-harm. Redistributing, republishing, or feeding the output into a product or model is a materially different and higher-risk activity that this tool takes no position on and does not license you to do.
  • Scope of intended use. yt2md is meant as a personal, local utility for content you are authorised to access (e.g. your own videos, or videos whose captions you are entitled to use). Using it to bulk-harvest third-party content, or as the backend of a hosted service, is outside its intended scope.

The title lookup uses YouTube's public, documented oEmbed endpoint and is not subject to the concerns above. The --claude reflow runs entirely on your machine and is governed only by your own agreement with Anthropic.

You are responsible for how you use this tool. If ToS compliance matters for your use case, the sanctioned path is the official YouTube Data API v3 (captions.download), which only permits caption downloads for videos you own or where the owner has enabled third-party contributions.

yt2md is an independent project and is not affiliated with, endorsed by, or sponsored by YouTube or Google LLC. "YouTube" is a trademark of Google LLC.

Development

uv run pytest                                   # tests
uv run ruff check . && uv run ruff format .     # lint + format
uvx ty check                                    # type check

License

MIT © Mauro Medda

About

Dump a YouTube video's transcript as Markdown

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages