pickuma.
AI & Dev Tools

yt-dlp: The CLI Video Downloader Developers Actually Use in 2026

yt-dlp replaced youtube-dl as the default for programmatic video and audio extraction. Installation, format selectors, the Python API, and the production gotchas we hit running it across three real workflows.

6 min read

yt-dlp has become the default tool when you need to programmatically pull video or audio from a URL. It started as a fork of youtube-dl in late 2020, picking up active maintenance after the original project’s release cadence slowed. The GitHub repository has crossed 100,000 stars, the extractor list covers well over a thousand sites, and the project ships builds on a regular schedule. We spent a week using it across three workflows — bulk podcast archiving, transcript collection for a speech model, and a small CI job that mirrors a lecture series — and this is what stuck.

Why yt-dlp Replaced youtube-dl

youtube-dl’s update cadence slowed in 2020, and YouTube’s player kept changing in ways that broke extraction. yt-dlp emerged as a community fork that merged outstanding patches faster, added extractors aggressively, and accepted features the upstream project had declined to ship. The features that matter most for developer workflows:

  • SponsorBlock integration via --sponsorblock-mark and --sponsorblock-remove
  • Native chapter splitting with --split-chapters
  • Concurrent fragment downloads via --concurrent-fragments N
  • A more flexible output template system using Python format-string syntax
  • Plugin architecture for custom extractors and post-processors
  • Live HLS/DASH stream recording with --live-from-start

Most CLI flags from youtube-dl still work, which means existing scripts port over by changing the install command and nothing else. If you have a 2019-era cron job still pointing at youtube-dl, you can usually swap the binary name and keep moving.

Installation and First Run

You have four practical install paths:

Terminal window
# pipx (recommended — isolated environment)
pipx install yt-dlp
# Homebrew on macOS
brew install yt-dlp
# Standalone binary (no Python required on host)
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o yt-dlp
chmod +x yt-dlp
# pip
pip install -U yt-dlp

The standalone binary embeds Python via PyInstaller, which is the right choice for Docker images where you don’t want to maintain a Python toolchain just for downloads. For a one-shot test:

Terminal window
yt-dlp -f "bestvideo[height<=1080]+bestaudio/best" \
--merge-output-format mp4 \
'https://www.youtube.com/watch?v=dQw4w9WgXcQ'

That format expression is the bread and butter of yt-dlp. The + joins separate video and audio streams, and --merge-output-format mp4 runs the ffmpeg merge automatically — provided ffmpeg is on your PATH.

Building Pipelines: The Python API

For automation, the CLI is only half the story. yt-dlp is also a Python library, and importing it gives you direct access to the same options without shelling out:

import yt_dlp
opts = {
'format': 'bestaudio/best',
'outtmpl': 'downloads/%(channel)s/%(upload_date)s_%(id)s.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'download_archive': 'archive.txt',
'ignoreerrors': True,
}
with yt_dlp.YoutubeDL(opts) as ydl:
ydl.download(['https://www.youtube.com/@somechannel'])

Three flags do the heavy lifting in production pipelines:

--download-archive archive.txt appends each successfully downloaded video ID to a file. On the next run, anything already in the archive is skipped. This is the single most useful flag for cron-driven mirroring of channels or playlists.

-o output template uses Python format-string syntax with metadata fields. %(channel)s, %(upload_date)s, %(id)s, %(title)s, %(ext)s cover most needs. Always include %(id)s somewhere in the path — titles can collide and IDs cannot.

--cookies-from-browser firefox (also accepts chrome, edge, brave, safari, vivaldi) pulls auth cookies from a local browser profile so age-gated, region-gated, or members-only content works. For headless servers, export cookies once with the browser extension of your choice and pass --cookies cookies.txt.

For dataset collection workflows where you only need metadata and captions, combine --write-info-json --write-subs --sub-langs en --skip-download. We used this pattern to build a transcript corpus from a 600-video channel in about 40 minutes — most of the time was waiting on YouTube’s subtitle endpoints, not yt-dlp itself.

The --extractor-args flag is the escape hatch when YouTube ships a player change. Something like --extractor-args "youtube:player_client=web,web_safari" forces specific clients when the default starts returning empty format lists. The yt-dlp issue tracker is the canonical place to find the current incantation when extraction suddenly breaks.

Notion

Once you start mirroring channels, you need somewhere to track what you have, why you collected it, and what license applies. A Notion database with a row per source channel works as a low-friction archive index that lives next to the files.

Free for personal use; team plans from $10/user/month

Try Notion

Affiliate link · We earn a commission at no cost to you.

Three things bite people in production:

Rate limiting. Hitting YouTube with --concurrent-fragments 16 from a single IP will get you throttled or temporarily blocked. For unattended jobs, throttle yourself: --limit-rate 5M --sleep-interval 5 --max-sleep-interval 15. Slower than you’d like, but it survives the night without a 429 storm.

Site terms of service. yt-dlp can technically download from YouTube, Vimeo, Twitch, SoundCloud, and many other platforms, but most of those services prohibit downloading in their terms. The defensible cases are personal archives of your own uploads, Creative Commons content, content explicitly licensed for redistribution, or material you have written permission to mirror. Building a commercial product on top of scraped video invites takedowns and, in some jurisdictions, civil liability. Talk to a lawyer before you ship a training-data pipeline that ingests anyone else’s video.

Format availability changes. Numeric format codes (137, 248, 251, etc.) that worked last quarter may not exist next month — YouTube reshuffles the list when it adds or deprecates encodings. Always use expressions like bestvideo[height<=1080]+bestaudio rather than hard-coding numeric codes. The selector resolves against whatever the extractor returns at runtime.

For long-running pipelines, pin the yt-dlp version. The nightly channel is useful when you need a fresh extractor patch immediately, but breaks reproducibility. Lock to a stable release in production and rebuild the image weekly against the newest stable.

FAQ

Does yt-dlp work with sites other than YouTube? +
Yes. The extractor list covers more than 1700 sites including Vimeo, Twitch, SoundCloud, BBC iPlayer, Twitter/X, TikTok, Bandcamp, and many regional broadcasters. Run `yt-dlp --list-extractors` to see the current set installed locally.
Is yt-dlp safe to use commercially? +
The tool itself is released under the Unlicense, so the code is unrestricted. The legal question is what you download and what you do with it — the terms of service of each source site apply to the downloaded content, not the tool. Personal archives, your own uploads, and Creative Commons material are the safe cases.
What happened to youtube-dl? +
youtube-dl still exists and still receives occasional updates, but yt-dlp ships extractor patches faster and supports more sites. Most developers who actively use the tool migrated to yt-dlp between 2021 and 2023, and most ecosystem projects now default to yt-dlp as the backend.