yt-dlp Downloader¶
Probe-driven download workflow with explicit format selection and safe retry defaults.
Quick Reference¶
| If you need to… | Go to |
|---|---|
| Choose scenario (single video / audio / playlist / subtitles / live / SponsorBlock) | §1 Scope Classification |
| Handle specific resolution, codec, HDR, or AV1 | Load references/format-selection-guide.md |
| Handle private / age-gated / login-required content | §5 Auth Safety Gate + Load references/safety-and-recovery.md |
| Fix extraction errors, throttling, or YouTube failures | Load references/safety-and-recovery.md |
| Check the output contract fields (Scenario / Probe / Command…) | §Output Contract |
Mandatory Gates¶
Gates execute in strict serial order. Any gate failure blocks all subsequent steps.
1) Scope 2) Dependency 3) Ambiguity 4) Probe
Classification → Check → Resolution → Before Download
│ │ │ │
scenario type yt-dlp+ffmpeg unclear? -F / --list-subs
→ classify → verify → STOP+ASK → inspect first
│ │ │ │
5) Auth Safety 6) Execution 7) Execution
Gate → Mode → Integrity
│ │ │
cookies/DRM full/degraded actually ran?
→ enforce → auto-select → report honestly
1) Scope Classification Gate¶
Map every request into exactly one scenario before proceeding:
| Scenario | Trigger |
|---|---|
| Single video | One URL, default quality or specific format |
| Fixed resolution | User mentions 720p, 1080p, 4K, or specific codec |
| Playlist | Playlist URL, "all videos", "course", "channel" |
| Audio extraction | "mp3", "audio only", "podcast", "music" |
| Subtitles | "subtitles", "captions", "srt", specific language |
| Authenticated | "private", "members-only", "age-gated", login required |
| Live stream | "live", "stream", "premiere", "currently streaming" |
| SponsorBlock | "skip sponsors", "remove intros", "no ads" |
Goal: Determine which scenario template to use from references/scenario-templates.md.
Composite requests: When multiple scenarios apply (e.g., playlist + resolution cap + subtitles), choose the primary scenario as the template base (typically the delivery mechanism — single video, playlist, or audio extraction), then overlay flags from secondary scenarios. Document the composition in the Output Contract's Scenario field.
2) Dependency Gate¶
Before execution, verify:
ffmpeg is required when: merging video+audio (-f bv*+ba), embedding subtitles (--embed-subs), extracting audio (-x), embedding thumbnails (--embed-thumbnail), or using --merge-output-format.
yt-dlp-ejs + JS runtime: Full YouTube support requires yt-dlp-ejs and a JavaScript runtime. Runtimes are tried in priority order deno > node > quickjs > bun, and only deno is enabled by default — to use a lower-priority one, pass --no-js-runtimes before --js-runtimes <name>.
Minimum versions, from the yt-dlp/ejs "Runtime requirements" table (not the "Development requirements" table below it, which is stricter and applies to developing ejs itself):
| Runtime | Required | Note |
|---|---|---|
| deno | >=2.3 | recommended |
| node | >=22 | |
| bun | >=1.2.11, <=1.3.14 | deprecated |
| quickjs | see the ejs README | supported, lowest priority |
Version floors move with ejs releases — confirm against https://github.com/yt-dlp/ejs rather than trusting this table if a runtime is rejected.
If a dependency is missing: state Not available in this environment, name the exact missing dependency, and provide the install command.
3) Ambiguity Resolution Gate¶
STOP and ASK if: - URL is not provided - Output directory is unspecified and matters (batch/playlist) - A stated constraint cannot be satisfied without a number (a storage cap, a target device, "must fit on X") — ask for the number - Playlist scope is ambiguous (full playlist vs single video from playlist URL) - Subtitle language is needed but not specified - Multiple URLs given without clear batch vs individual intent
Do not stop for vague quality wording. "Good quality", "high quality" and "best" all resolve to the default best-practical selector. Apply it, and state the assumption in the Output Contract's Inputs field: the user can correct one line of a delivered command far more cheaply than answering a question they did not think they had to answer. Ask only when a constraint makes the number load-bearing (see above).
4) Probe Gate¶
Do not guess format availability. Run a probe first when any of these apply:
| Condition | Probe Command |
|---|---|
| Specific resolution/codec/format requested | yt-dlp -F "<url>" |
| Subtitle language availability unknown | yt-dlp --list-subs "<url>" |
| Playlist scope unclear or very large | yt-dlp --flat-playlist --print "%(playlist_index)s %(title)s" "<url>" |
| URL may require auth or redirect | yt-dlp --simulate --skip-download "<url>" |
| Site often changes formats | yt-dlp -F "<url>" |
Skip the probe only for simple, public, single-video downloads where default best quality is acceptable.
5) Auth Safety Gate¶
- Use cookies only for content the user is authorized to access
- Prefer
--cookies-from-browser <browser>over raw cookie files - Never ask the user to paste cookie contents into chat
- Never describe cookies as a way to bypass paywalls or DRM
- Never help circumvent geographic restrictions on copyrighted content
- If auth is required but unavailable, stop at the command recommendation
6) Execution Mode Gate¶
Auto-select mode based on environment:
| Signal | → Mode |
|---|---|
| Shell access available, yt-dlp installed | Full |
| Shell available but yt-dlp missing | Blocked (install first) |
| No shell access / sandbox environment | Degraded |
7) Execution Integrity Gate¶
Never claim a download succeeded unless the command actually ran.
If executed: report final command, destination path, success/failure, key stderr/stdout summary. If not executed: report Not run in this environment, reason, exact command to run.
Defaults¶
Apply these unless the user requests otherwise:
--download-archive "<dir>/.yt-dlp-archive.txt"
--continue
--no-overwrites
--retries 10 --fragment-retries 10
-o "<dir>/%(title).200s [%(id)s].%(ext)s"
When logging is useful (batch, troubleshooting, unstable network), tee the output — but set pipefail first, or the shell reports tee's exit status and a failed download looks like a success, which contradicts the Execution Integrity Gate:
If pipefail is unavailable (plain sh, some CI runners), use yt-dlp's own sink instead of a pipe: --print-to-file "%(filepath)s" "<dir>/yt-dlp.log" for paths, or simply redirect with > "<dir>/yt-dlp.log" 2>&1, which preserves the exit status.
Anti-Examples (Core Mistakes)¶
For the full set of 9 anti-examples, read references/anti-examples.md. The four most critical are inlined here (numbering is shared with the full catalog):
-
Guessing format availability without probing — formats change per site and per video. Probe first.
-
Omitting
--no-playlistfor single-video watch URLs — YouTube watch URLs can trigger full playlist download. -
Claiming download success without running the command — if you did not execute it, say so.
-
Re-starting from scratch when YouTube throttles mid-download — the
.partfile is preserved; re-run with--continue --limit-rate 2M --concurrent-fragments 1to resume, not restart. Seereferences/safety-and-recovery.md § YouTube throttling mid-download.
Honest Degradation¶
| Level | Condition | Action |
|---|---|---|
| Full | yt-dlp + ffmpeg available, shell access, command executed | Complete execution report with all 7 output fields |
| Degraded | No shell access or sandbox environment | Provide recommended command + state assumptions + suggest probe command if confidence is low |
| Blocked | yt-dlp not installed, or request involves DRM/unauthorized access | State the blocker + provide install command or explain why the request cannot proceed |
Never report download success, file size, or format availability in Degraded or Blocked mode.
Safety Rules¶
- Never help download content the user is not authorized to access
- Never describe cookies as a DRM/paywall bypass method
- Never ask the user to paste cookie contents into chat
- Never claim a download ran unless it actually executed
- Never hardcode format IDs without probing the specific video
- Always include
--no-playlistfor single-video watch URLs with playlist parameters - Always verify ffmpeg before merge/extract/embed operations
- Always pair
--embed-subswith--write-subs(or--write-auto-subs) —--embed-subsalone does not download subtitles
Output Contract¶
Every response must include these 7 fields:
- Scenario — which template was selected
- Inputs — URL, output dir, format preference, subtitle needs, auth method
- Probe — probe command + results summary, or "skipped" with reason
- Final command — one complete, copy-pasteable command
- Execution status — ran successfully / failed (with key error) / not run (with reason)
- Output location — expected file path pattern
- Next step — corrective action if failed, or confirmation if succeeded
Load References Selectively¶
A simple public single-video request needs no reference file. The template below plus §Defaults is the whole command; loading more costs context and buys nothing:
yt-dlp --no-playlist -f "bv*+ba/b" --merge-output-format mp4 \
--download-archive "<dir>/.yt-dlp-archive.txt" --continue --no-overwrites \
--retries 10 --fragment-retries 10 \
-o "<dir>/%(title).200s [%(id)s].%(ext)s" "<url>"
For any other scenario — playlist, audio, subtitles, auth, live, SponsorBlock, resolution or codec constraints: → Load references/scenario-templates.md for the complete templates (including 1b for a guaranteed-H.264/AAC MP4) to use as the base command.
When the output contract's shape is unclear, or the scenario is composite: → Load references/golden-examples.md for fully worked examples showing correct Scenario / Command / Defaults / Execution / Output fields per scenario type.
When choosing between format selectors, playlist modes, or subtitle strategies: → Load references/decision-rules.md for decision trees covering format selector priority (bv*+ba vs -f best), playlist scope flags, subtitle embedding vs external file, and archive file usage.
When the request specifies quality, codec, HDR, AV1, or specific resolution: → Load references/format-selection-guide.md for probe output interpretation, codec ranking tables, and HDR/AV1 selection flags.
When the user reports auth errors, extraction failures, or throttling, or when cookies or private content are involved: → Load references/safety-and-recovery.md for browser cookie extraction steps, retry flags, yt-dlp-ejs install guide, and throttling recovery patterns.
When reviewing or self-checking a generated command for common mistakes: → Load references/anti-examples.md for the remaining 5 of the 9 anti-examples (2, 4, 6, 7, 8) with corrected alternatives.
Bundled Assets¶
- Contract tests:
scripts/tests/test_skill_contract.py - Golden scenario tests:
scripts/tests/test_golden_scenarios.py - Regression runner:
scripts/run_regression.sh