If you've ever wanted to save a video — a conference talk, a music video, a documentary that keeps disappearing — yt-dlp is the tool I keep coming back to. It supports a huge range of sites, handles most formats cleanly, and has enough flags for tricky cases.
What yt-dlp is
yt-dlp is a fork of the older youtube-dl project, maintained at a much faster pace with broader site support, better format selection, and active bug fixes. Despite the name, it handles far more than YouTube — Vimeo, Twitter/X, Twitch, Reddit, TikTok, BBC iPlayer, and hundreds more.1
It's a CLI tool: no GUI, no browser extension required. You give it a URL, it figures out the available streams, and it downloads what you asked for.
Installation
If a package manager is not your preferred route, you can download the standalone binary from the releases page. On Windows and macOS, download the build for the correct operating system and CPU architecture, then place the executable in a directory on your PATH.
Windows
The simplest route is winget:
winget install yt-dlp
macOS
The simplest route is Homebrew:
brew install yt-dlp
Linux
Most package managers have it:
# Debian/Ubuntu
sudo apt install yt-dlp
# Arch
sudo pacman -S yt-dlp
# Fedora
sudo dnf install yt-dlp
Or install via pip if you want the latest version regardless of distro:
python3 -m pip install -U yt-dlp
Keeping it up to date
yt-dlp updates frequently — sites change their internals and extractors need to keep up. Run this to update in place:
yt-dlp -U
ffmpeg
Install ffmpeg alongside yt-dlp. Without it, format merging and post-processing won't work — you'll be stuck with whatever single stream the site serves rather than the best video merged with the best audio.2
Basic usage
Downloading a video is one command:
yt-dlp "https://www.youtube.com/watch?v=VIDEO_ID"
By default, yt-dlp picks the best available quality and saves the file to the current directory with an auto-generated filename. That's often exactly what you want.
Format selection
YouTube and many other sites serve video and audio as separate streams. yt-dlp merges them automatically, but you can control exactly what you get with --format (short: -f).
List all available formats for a URL before downloading:
yt-dlp --list-formats "https://www.youtube.com/watch?v=VIDEO_ID"
This outputs a table of format codes, resolutions, codecs, and file sizes. You can then pass a specific format code:
yt-dlp -f 137+140 "https://www.youtube.com/watch?v=VIDEO_ID"
Or use yt-dlp's format selection syntax for something more readable:
# Best video + best audio, merged into mp4
yt-dlp -f "bv*+ba/b" --merge-output-format mp4 "https://www.youtube.com/watch?v=VIDEO_ID"
# Best quality up to 1080p
yt-dlp -f "bv*[height<=1080]+ba/b[height<=1080]" "https://www.youtube.com/watch?v=VIDEO_ID"
# Prefer VP9/opus over AVC/AAC (better compression)
yt-dlp -f "bv[vcodec^=vp9]+ba[acodec^=opus]/bv*+ba/b" "https://www.youtube.com/watch?v=VIDEO_ID"
Audio-only downloads
To extract just the audio and convert it to mp3:
yt-dlp --extract-audio --audio-format mp3 --audio-quality 0 "https://www.youtube.com/watch?v=VIDEO_ID"
--audio-quality 0 means best quality (VBR)3. For a specific bitrate, pass a value like 192K.
For formats that don't need conversion (e.g., keeping the native audio stream as m4a or opus):
yt-dlp -f "ba" "https://www.youtube.com/watch?v=VIDEO_ID"
Subtitles
Download a video with its subtitles:
# List available subtitles first
yt-dlp --list-subs "https://www.youtube.com/watch?v=VIDEO_ID"
# Download with English subtitles embedded
yt-dlp --write-subs --sub-lang en --embed-subs "https://www.youtube.com/watch?v=VIDEO_ID"
# Auto-generated subtitles (YouTube's auto-captions)
yt-dlp --write-auto-subs --sub-lang en "https://www.youtube.com/watch?v=VIDEO_ID"
Subtitles are saved as .vtt or .srt files alongside the video unless you use --embed-subs to bake them in.
Playlists
Pass a playlist URL and yt-dlp downloads every video in it:
yt-dlp "https://www.youtube.com/playlist?list=PLAYLIST_ID"
Useful playlist options:
# Download only items 5 through 10
yt-dlp --playlist-start 5 --playlist-end 10 "PLAYLIST_URL"
# Download specific items by index
yt-dlp --playlist-items 1,3,5-7 "PLAYLIST_URL"
# Skip videos you've already downloaded (safe to re-run)
yt-dlp --download-archive archive.txt "PLAYLIST_URL"
The --download-archive flag is especially useful for ongoing playlists or channels — it writes downloaded video IDs to a file and skips them on subsequent runs.
Output templates
Control where files are saved and what they're named with --output (short: -o):
# Save to a Videos folder, named by uploader and title
yt-dlp -o "~/Videos/%(uploader)s/%(title)s.%(ext)s" "https://www.youtube.com/watch?v=VIDEO_ID"
# Include upload date
yt-dlp -o "%(upload_date)s - %(title)s.%(ext)s" "https://www.youtube.com/watch?v=VIDEO_ID"
Available template fields include %(title)s, %(uploader)s, %(upload_date)s, %(id)s, %(ext)s, %(resolution)s, and many more.
Rate limiting
If a site throttles you or you want to be polite:
# Limit download speed to 2 MB/s
yt-dlp --limit-rate 2M "https://www.youtube.com/watch?v=VIDEO_ID"
# Add a random sleep between downloads in a playlist
yt-dlp --sleep-interval 2 --max-sleep-interval 8 "PLAYLIST_URL"
Using cookies
Some content requires you to be logged in — age-restricted videos, members-only content, private videos. yt-dlp can use your browser's cookies:
yt-dlp --cookies-from-browser chrome "https://www.youtube.com/watch?v=VIDEO_ID"
Supported browsers: chrome, firefox, edge, safari, brave, and opera.
Alternatively, export cookies to a Netscape-format file from a browser extension and pass it directly:
yt-dlp --cookies cookies.txt "https://www.youtube.com/watch?v=VIDEO_ID"
Embedding metadata and thumbnails
yt-dlp --embed-metadata --embed-thumbnail "https://www.youtube.com/watch?v=VIDEO_ID"
This writes title, uploader, description, chapters, and other metadata into the file container, and embeds the thumbnail as cover art — useful if you're building a local media library.
A configuration file
If you find yourself repeating the same flags, put them in a config file. yt-dlp reads from %APPDATA%\yt-dlp\config.txt on Windows and ~/.config/yt-dlp/config on Linux/macOS.
Set a default download location
Add these lines to your config file so every download lands in the same place with predictable names.
Windows
--paths home:C:/Users/<your-username>/Downloads/yt-dlp
--output %(uploader)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s
Linux/macOS
--paths home:~/Downloads/yt-dlp
--output %(uploader)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s
You can verify your configured destination without downloading anything:
yt-dlp --simulate --print after_move:filepath "https://www.youtube.com/watch?v=BaW_jenozKc"
If the printed path points to your folder, your default location is set correctly.
A reasonable default config:
--format bv*+ba/b
--merge-output-format mp4
--embed-metadata
--embed-thumbnail
--output ~/Downloads/%(uploader)s - %(title)s.%(ext)s
--no-playlist
--no-playlist is worth calling out: if you pass a URL that could be interpreted as either a single video or a playlist (e.g., a YouTube video that's part of a playlist), this flag ensures you only get the video.
Real-world examples
# Download a YouTube video at 1080p as mp4 with embedded subtitles and metadata
yt-dlp \
-f "bv*[height<=1080]+ba/b" \
--merge-output-format mp4 \
--write-subs --sub-lang en --embed-subs \
--embed-metadata --embed-thumbnail \
-o "%(title)s.%(ext)s" \
"https://www.youtube.com/watch?v=VIDEO_ID"
# Download audio only from a playlist, skipping already-downloaded items
yt-dlp \
--extract-audio --audio-format mp3 --audio-quality 0 \
--download-archive archive.txt \
-o "%(playlist_index)s - %(title)s.%(ext)s" \
"PLAYLIST_URL"
# Download from a site that needs login cookies
yt-dlp --cookies-from-browser firefox --limit-rate 1M "https://example.com/video"
Batch downloads
If you have multiple URLs, put one link per line in urls.txt and run:
yt-dlp -a urls.txt --download-archive downloaded.txt
-a reads URLs from a file, and --download-archive prevents re-downloading items you already fetched.
Troubleshooting
ffmpeg not found (merge or conversion fails). Install FFmpeg and make sure it is available on your PATH.
ffmpeg -version
Age-restricted or member-only content fails. Reuse your browser session cookies:
yt-dlp --cookies-from-browser chrome "https://www.youtube.com/watch?v=VIDEO_ID"
Rate limits (for example, HTTP Error 429). Slow requests and add jitter:
yt-dlp --sleep-interval 2 --max-sleep-interval 8 "https://www.youtube.com/watch?v=VIDEO_ID"
Extractor breaks after a site update. Update yt-dlp to the latest release:
yt-dlp -U
Tips
Check the extractor list before assuming a site isn't supported. Run yt-dlp --list-extractors or search the supported sites list. It's longer than you'd expect.
Use --simulate --verbose to debug without downloading. This prints everything yt-dlp resolves without writing any files — useful when a download fails and you need to understand why.
The --sponsorblock-remove flag skips sponsor segments in YouTube videos using SponsorBlock data. Pass --sponsorblock-remove sponsor,selfpromo,interaction to cut the most common filler.
For large playlists, --concurrent-fragments speeds things up by downloading multiple fragments of a single video in parallel:
yt-dlp --concurrent-fragments 4 "PLAYLIST_URL"
Keep it reasonable — pushing this too high on rate-limited connections won't help and may get you throttled.
The yt-dlp README is worth reading end to end at least once. It's dense, but it answers most of the questions you run into later.
Start with a simple command, then move your most-used flags into config as your workflow grows. That small habit keeps downloads consistent and saves a lot of repetitive typing over time.
Footnotes
-
The full list of supported sites is maintained in supportedsites.md in the repository. It currently runs to over a thousand entries. ↩
-
On YouTube, the highest-resolution streams (1080p60 and above) are only available as separate video and audio streams. Without
ffmpegto merge them, yt-dlp falls back to a lower-quality combined format. ↩ -
VBR means variable bitrate: the encoder uses more bits for complex audio sections and fewer for simpler ones, which usually improves perceived quality at a given file size. ↩
