Handles YouTube downloads and HLS streams using yt-dlp and ffmpeg, with built-in workarounds for the bot detection and format availability issues that break basic yt-dlp usage. Sets up PO token providers automatically (tries Docker, falls back to browser-based), extracts cookies from Chrome when needed, and defaults to a non-technical UX where you just ask for a URL and get a file. The SOP is particularly solid on the failure modes: quotes URLs for zsh, rewrites localhost proxies for Docker, treats "only images available" as a token failure, keeps browser windows open during WPC minting. Useful when you need reliable high-quality downloads without debugging yt-dlp's increasingly fragile YouTube support yourself.
npx -y skills add daymade/claude-code-skills --skill youtube-downloader --agent claude-codeInstalls into .claude/skills of the current project.
Enable reliable video and audio downloads from YouTube and HLS streaming platforms (Mux, Vimeo, etc.) using yt-dlp and ffmpeg. This skill provides workflows for:
Assume the user is non-technical. Do not ask them to run commands. Execute everything yourself and report progress in plain language. Avoid mentioning tooling unless the user asks.
Default flow:
Offer choices in user-friendly terms:
Always render the thumbnail when available:
.Ask before doing extra work:
Legal/Safety reminder (brief):
Response template (use plain language, no commands):

Title: …
Channel: …
Duration: …
I can help you:
1) Download the video (best quality, MP4)
2) Download audio only (MP3)
3) Pick a specific quality (1080p/720p/480p/360p)
4) Include subtitles (if available)
Where should I save it? (Default: Downloads folder)
If the user says “just download”:
Follow this SOP to avoid common failures and confusion:
? as a glob). Example: 'https://www.youtube.com/watch?v=VIDEO_ID'.web_safari player client. Otherwise prefer mweb for PO tokens.scripts/download_video.py URL --info (add --cookies-from-browser chrome if permission granted) to fetch metadata and thumbnail.--subtitles and the requested --sub-lang.web_safari.--auto-po-token default). Fail fast if it cannot start.host.docker.internal for Docker.This skill should be invoked when users:
which yt-dlp
yt-dlp --version
If not installed or outdated (< 2025.10.22):
brew upgrade yt-dlp # macOS
# or
pip install --upgrade yt-dlp # Cross-platform
Critical: Outdated yt-dlp versions cause nsig extraction failures and missing formats.
Before downloading, check available formats:
yt-dlp -F "https://youtu.be/VIDEO_ID"
If only format 18 (360p) appears: PO token provider setup needed for high-quality access.
For 1080p/1440p/4K access, install a PO token provider plugin into yt-dlp's Python environment:
# Find yt-dlp's Python path (interpreter used by yt-dlp)
head -1 $(which yt-dlp)
# Install plugin using the interpreter from the line above
<YTDLP_PYTHON> -m pip install bgutil-ytdlp-pot-provider
Verification: Run yt-dlp -F "VIDEO_URL" again. Look for formats 137 (1080p), 271 (1440p), or 313 (4K).
See references/po-token-setup.md for detailed setup instructions and troubleshooting.
Once PO token provider is installed:
# Download best quality up to 1080p
yt-dlp -f "bestvideo[height<=1080]+bestaudio/best" "VIDEO_URL"
# Download best available quality (4K if available)
yt-dlp -f "bestvideo+bestaudio/best" "VIDEO_URL"
# Check video resolution
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,codec_name -of default=noprint_wrappers=1 video.mp4
Expected output for 1080p:
codec_name=vp9
width=1920
height=1080
If PO token provider setup is problematic, use browser cookies:
# Firefox
yt-dlp --cookies-from-browser firefox -f "bestvideo[height<=1080]+bestaudio/best" "VIDEO_URL"
# Chrome
yt-dlp --cookies-from-browser chrome -f "bestvideo[height<=1080]+bestaudio/best" "VIDEO_URL"
Benefits: Access to age-restricted and members-only content. Requirements:
Extract audio as MP3:
yt-dlp -x --audio-format mp3 "VIDEO_URL"
yt-dlp -P ~/Downloads/YouTube "VIDEO_URL"
yt-dlp --write-subs --sub-lang en "VIDEO_URL"
yt-dlp -f "bestvideo[height<=1080]+bestaudio/best" "PLAYLIST_URL"
YouTube high-quality downloads often use WebM format (VP9 codec). Convert to MP4 for wider compatibility:
# Check if ffmpeg is installed
which ffmpeg || brew install ffmpeg # macOS
# Convert WebM to MP4 with good quality settings
ffmpeg -i "video.webm" -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k "video.mp4"
Parameters explained:
-c:v libx264: Use H.264 video codec (widely compatible)-preset medium: Balance between encoding speed and file size-crf 23: Constant Rate Factor for quality (18-28 range, lower = better quality)-c:a aac: Use AAC audio codec-b:a 128k: Audio bitrate 128 kbpsTip: Conversion maintains 1080p resolution and provides ~6x encoding speed on modern hardware.
Cause: Missing PO token provider or outdated yt-dlp.
Solution:
brew upgrade yt-dlpCause: YouTube requires authentication to proceed.
Solution:
--cookies-from-browser chrome).web_safari client if needed.Cause: PO tokens not applied or provider/browser verification failed.
Solution:
web_safari client and retry.Symptoms:
WARNING: [youtube] nsig extraction failed: Some formats may be missing
Solution:
yt-dlp --extractor-args "youtube:player_client=android" "VIDEO_URL"Cause: Proxy or network instability.
Solution:
For users in China or behind restrictive proxies:
WARNING: android client https formats require a GVS PO Token
Action: Ignore if download succeeds. This indicates Android client has limited format access without PO tokens.
Use this convenience wrapper to auto-start a PO Token provider by default for high-quality downloads. Use it yourself and report results to the user without asking them to run commands.
Basic usage:
scripts/download_video.py "VIDEO_URL"
Arguments:
url - YouTube video URL (required)-o, --output-dir - Output directory--output-template - Output filename template (yt-dlp syntax)-f, --format - Format specification-q, --quality - Quality preset (best, 1080p, 720p, 480p, 360p, worst). Default: best (skipped for --audio-only)-a, --audio-only - Extract audio as MP3--subtitles - Download subtitles if available--sub-lang - Subtitle languages (comma-separated, default: en)--cookies-from-browser - Load cookies from a browser (e.g., chrome, firefox)--cookies-file - Load cookies from a cookies.txt file--player-client - Use a specific YouTube player client (e.g., web_safari)--auto-po-token - Auto-start PO Token provider (default; uses Docker if available, otherwise switches to browser-based provider)--no-auto-po-token - Disable auto PO Token setup--proxy - Proxy URL for yt-dlp and the PO Token provider (e.g., http://127.0.0.1:1082)--wpc-browser-path - Browser executable path for WPC provider-F, --list-formats - List available formats--merge-format - Merge output container (e.g., mp4, mkv). Default: mp4--playlist - Allow playlist downloads (default: single video only)--info - Print title/uploader/duration/thumbnail and exit--no-android-client - Disable Android client fallbackNote: Use the Android client only when PO tokens are disabled. Keep PO tokens enabled for high quality.
| Setup | 360p | 720p | 1080p | 1440p | 4K |
|---|---|---|---|---|---|
| Auto PO token (default) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Android client only | ✓ | ✗ | ✗ | ✗ | ✗ |
| PO token provider (manual) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Browser cookies | ✓ | ✓ | ✓ | ✓ | ✓ |
For streaming platforms like Mux, Vimeo, and other HLS-based services, use ffmpeg as the primary tool. These streams often require authentication headers that yt-dlp may not handle correctly.
HLS streams use .m3u8 playlist files:
Get the m3u8 URL from the video source. For protected streams:
Many CDNs require authentication headers:
https://maven.com/)Check the Network tab to see which headers the browser sends.
Use ffmpeg with the -headers flag for protected streams:
ffmpeg -headers "Referer: https://example.com/" \
-protocol_whitelist file,http,https,tcp,tls,crypto,httpproxy \
-i "https://cdn.example.com/path/rendition.m3u8?params" \
-c copy -bsf:a aac_adtstoasc \
output.mp4
Key parameters:
-headers: Set HTTP headers (critical for authentication)-protocol_whitelist: Enable required protocols for HLS-c copy: Stream copy (no re-encoding, faster)-bsf:a aac_adtstoasc: Fix AAC audio compatibilityCommon header patterns:
# Single header
-headers "Referer: https://example.com/"
# Multiple headers
-headers "Referer: https://example.com/" \
-headers "User-Agent: Mozilla/5.0..."
# Alternative syntax
-headers $'Referer: https://example.com/\r\nUser-Agent: Mozilla/5.0...'
Some platforms (like Mux) deliver audio and video separately:
ffmpeg -headers "Referer: https://example.com/" \
-protocol_whitelist file,http,https,tcp,tls,crypto,httpproxy \
-i "https://cdn.example.com/audio/rendition.m3u8" \
-c copy audio.m4a
ffmpeg -headers "Referer: https://example.com/" \
-protocol_whitelist file,http,https,tcp,tls,crypto,httpproxy \
-i "https://cdn.example.com/video/rendition.m3u8" \
-c copy video.mp4
ffmpeg -i video.mp4 -i audio.m4a -c copy merged.mp4
Cause: Missing or incorrect authentication headers.
Solution:
Symptom: Extracting cookies from chrome hangs indefinitely.
Solution: Use ffmpeg directly instead of yt-dlp for HLS streams.
Error: Protocol 'https' not on whitelist 'file,crypto,data'
Solution: Add -protocol_whitelist file,http,https,tcp,tls,crypto,httpproxy
Cause: Expired signatures in the m3u8 URLs.
Solution:
-c copy (fastest)references/po-token-setup.md for detailed installation and troubleshootingAfter downloading, if the user's goal involves getting text from the video (transcription, subtitles, meeting notes), proactively suggest:
Download complete: [filename]
If you need the spoken content as text, I can transcribe it for you.
Options:
A) Transcribe with /daymade-audio:asr-transcribe-to-text (Recommended for speech-to-text)
B) No thanks — I just needed the video file
juliusbrussee/caveman
mattpocock/skills
shadcn/improve
obra/superpowers
forrestchang/andrej-karpathy-skills
vercel-labs/skills