You usually arrive at the YouTube download command line for one reason. A manual workflow broke down.
Maybe you need to archive a training channel before videos disappear. Maybe marketing handed you a spreadsheet of URLs and asked for audio extracts, thumbnails, and mobile-friendly clips by tomorrow. Maybe you started with a browser extension, then hit the wall where every download became a click-heavy chore.
That's where yt-dlp earns its place. It starts as a simple terminal tool, but it scales unusually well. You can use it for a single URL, then for playlists, then for repeatable scripts, and eventually as one piece in a larger media pipeline.
Table of Contents
- Why Use the Command Line for YouTube Downloads
- Prerequisites Getting yt-dlp and FFmpeg Ready
- Your First Downloads Essential yt-dlp Commands
Why Use the Command Line for YouTube Downloads
Desktop downloaders look fine when you're grabbing one video. They fall apart when the job turns repetitive.
A typical example is a content archive. You start with one tutorial, then realize you need the entire channel, then realize you only need new uploads, then realize you also need filenames that won't become garbage six months from now. The command line handles that progression cleanly because the workflow stays scriptable from day one.
The original youtube-dl set the pattern. It was first released as a Python program requiring interpreter versions 2.6, 2.7, or 3.2+, and it was built to download videos from YouTube.com and a few additional sites, which established the architecture that modern CLI downloaders still follow, as documented in the youtube-dl project repository.
That history matters because yt-dlp didn't appear out of nowhere. It inherited the practical model developers already trusted. Feed it URLs, choose formats, process output, move on. No GUI lock-in, no app-specific storage model, no waiting around for someone to add support for your OS workflow.
The command line isn't faster because terminals are magical. It's faster because every manual step disappears.
Three things make this approach stick:
- Automation fits naturally. A one-line command becomes a shell script, then a scheduled job.
- Output stays predictable. You control naming, directories, metadata, and post-processing.
- The tool works where developers already work. macOS, Linux, Windows, CI runners, containers.
There's also a mindset shift. With a GUI, you think in downloads. With the YouTube download command line, you think in pipelines. Download this playlist. Extract audio. Merge streams. Skip duplicates. Save thumbnails. Feed the result to FFmpeg. That's the difference between a one-off task and a system you can trust next week too.
Prerequisites Getting yt-dlp and FFmpeg Ready
yt-dlp fetches media. FFmpeg cleans up the result.
That split is the first thing people miss. YouTube often serves the best video and audio as separate streams. yt-dlp can retrieve them, but without FFmpeg, merging and conversion get messy fast. If you care about reliable output, install both before you do anything else.

Install on macOS
If you use Homebrew:
brew install yt-dlp ffmpeg
Check both tools:
yt-dlp --version
ffmpeg -version
Install on Ubuntu or Debian
sudo apt update
sudo apt install -y yt-dlp ffmpeg
Then verify:
yt-dlp --version
ffmpeg -version
Install on Fedora
sudo dnf install -y yt-dlp ffmpeg
And verify:
yt-dlp --version
ffmpeg -version
Install on Windows
If you use Chocolatey:
choco install yt-dlp ffmpeg -y
Then confirm in PowerShell:
yt-dlp --version
ffmpeg -version
If you install manually on Windows, make sure both executables are available in your PATH. If yt-dlp works but ffmpeg doesn't, most "merge failed" problems trace back to that.
A quick sanity check helps before you start real work:
| Tool | What it does | Verification command |
|---|---|---|
yt-dlp |
Downloads media and metadata from YouTube and many other sites | yt-dlp --version |
ffmpeg |
Merges streams, converts formats, trims, re-encodes | ffmpeg -version |
Practical rule: If you plan to download best quality video, install FFmpeg first. Otherwise you'll spend time debugging a problem that isn't in your command at all.
One more habit is worth adopting early. Keep yt-dlp current. The old youtube-dl workflow included youtube-dl -U for updates, and that culture still matters because extractor logic changes often. If you build scripts later, treat updates as maintenance, not as a rescue move after something breaks.
Your First Downloads Essential yt-dlp Commands
A lot of people start with one command copied from a forum, get a file, and stop there. The better path is to learn the few commands that scale from a one-off download to a script you can trust in a cron job or CI runner.

Start with the default behavior
Begin with the plain command and watch what yt-dlp does before you force format choices:
yt-dlp "https://www.youtube.com/watch?v=VIDEO_ID"
For one video, this is often enough. yt-dlp selects a reasonable format, downloads to the current directory, and uses FFmpeg if a merge is needed.
That baseline matters. If the plain command fails, adding more flags usually hides the actual problem instead of fixing it.
A practical reference for setup and real command patterns is this yt-dlp download guide.
Inspect formats before choosing one
The first command I reach for after a basic download is -F:
yt-dlp -F "https://www.youtube.com/watch?v=VIDEO_ID"
This prints the available format table. You can see which entries are video-only, audio-only, which containers are offered, and what resolutions are available for that specific upload.
Then pick the exact streams you want:
yt-dlp -f 137+140 "https://www.youtube.com/watch?v=VIDEO_ID"
137+140 is a common pattern. It selects one video stream and one audio stream, then FFmpeg merges them into a final file. That gives more control than relying on defaults, especially when you care about resolution, codec compatibility, or archive consistency.
If you plan to automate downloads later, format inspection is not optional. Hardcoding a format without checking availability is how brittle scripts start.
Here's a quick video if you prefer seeing the basics in motion:
Extract audio only
Audio extraction is common for interviews, podcast clips, transcription pipelines, and reference listening:
yt-dlp -x --audio-format mp3 "https://www.youtube.com/watch?v=VIDEO_ID"
The flags are simple:
-xextracts the audio track from the downloaded media--audio-format mp3tells FFmpeg to convert the result to MP3
There is a trade-off here. MP3 is widely compatible, but it is not always the best choice for archival quality. For quick playback across devices, MP3 is fine. For later processing, keeping the original audio or converting to a less lossy format can be better.
For playlists or mixed-quality batches, add -i so one bad item does not stop the whole run:
yt-dlp -x --audio-format mp3 -i "https://www.youtube.com/playlist?list=PLAYLIST_ID"
That small flag matters once you move from manual use to unattended jobs.
Download playlists without babysitting the run
Playlists are where command line workflows start paying off:
yt-dlp "https://www.youtube.com/playlist?list=PLAYLIST_ID"
For testing, pull only part of the list instead of firing off the whole thing:
yt-dlp --playlist-start 2 --playlist-end 5 "https://www.youtube.com/playlist?list=PLAYLIST_ID"
This is safer when you are validating filenames, checking storage usage, or confirming your network can handle the job. It is also the first step toward scriptable batch work. Start with a subset, verify the output, then scale the command into a loop, a scheduled task, or a download archive in the automation section.
If your network path is unstable or region-dependent, proxy routing can become part of the toolchain. This overview of Proxies for YouTube is a useful starting point before you add proxy settings to yt-dlp.
Useful starter commands:
Single video
yt-dlp "https://www.youtube.com/watch?v=VIDEO_ID"List formats
yt-dlp -F "https://www.youtube.com/watch?v=VIDEO_ID"Audio only
yt-dlp -x --audio-format mp3 "https://www.youtube.com/watch?v=VIDEO_ID"Playlist subset
yt-dlp --playlist-start 2 --playlist-end 5 "https://www.youtube.com/playlist?list=PLAYLIST_ID"
Advanced Techniques for Power Users
Once the basics work, the next bottleneck isn't syntax. It's output quality, performance, and repeatability.
Power users don't just download files. They shape filenames so libraries stay organized, tune concurrency for better throughput, and capture enough metadata to make the media useful later.

Control filenames and folder structure
If you leave filenames to defaults, your media folder becomes hard to search fast. Output templates fix that:
yt-dlp -o "%(uploader)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s" "https://www.youtube.com/watch?v=VIDEO_ID"
That command creates a directory per uploader and builds filenames with the upload date, title, and video ID. For recurring jobs, this is much better than a flat folder full of half-readable names.
A few patterns worth keeping:
Archive by channel
yt-dlp -o "%(channel)s/%(title)s.%(ext)s" URLKeep IDs in filenames
yt-dlp -o "%(title)s [%(id)s].%(ext)s" URLSort by date
yt-dlp -o "%(upload_date)s/%(title)s.%(ext)s" URL
Speed up downloads and keep quality sane
For high-throughput downloads, the most important pattern is using the DASH selector with concurrency. The recommended approach is bv*+ba/best together with -N 16, which parallelizes fragment downloads and reduces latency compared with the default single-threaded approach, according to this yt-dlp performance guide.
yt-dlp -f "bv*+ba/best" -N 16 "https://www.youtube.com/watch?v=VIDEO_ID"
If you want to push harder on fast connections, use aria2c as an external downloader:
yt-dlp -f "bv*+ba/best" -N 16 \
--downloader aria2c \
--downloader-args "aria2c:-x 16 -s 16" \
"https://www.youtube.com/watch?v=VIDEO_ID"
That setup is worth it for large playlists and large files. For a single short clip, it's often unnecessary overhead.
When rate limiting or regional restrictions start interfering, a proxy setup becomes part of the job. The trade-offs are explained well in this guide to Proxies for YouTube, especially if you're trying to keep scripted downloads stable across repeated runs.
Fast commands are good. Fast commands that still produce files your pipeline can merge, tag, and process are better.
Capture metadata and partial clips
If you're organizing media for editors, thumbnails and metadata are often as useful as the media file:
yt-dlp --write-thumbnail --embed-metadata "https://www.youtube.com/watch?v=VIDEO_ID"
If you only need thumbnail assets and not the full download:
yt-dlp --ignore-errors --write-thumbnail --skip-download "https://www.youtube.com/watch?v=VIDEO_ID"
Partial clip workflows are less polished. There’s minimal unified documentation for downloading a specific portion directly from the command line, and many people still combine ffmpeg -ss and -to with a direct media URL from youtube-dl or yt-dlp, based on threads like this discussion of downloading a video portion.
A practical pattern looks like this:
ffmpeg -ss 00:00:15 -to 00:01:00 -i "$(yt-dlp -f best --get-url "https://www.youtube.com/watch?v=VIDEO_ID")" -c copy clip.mp4
It works, but it's brittle. If the source stream changes or the selected format isn't what you expected, you end up debugging two tools instead of one. For repeatable clipping, download first if storage isn't your primary constraint.
Automating Downloads with Scripts and Archives
The biggest jump in reliability comes from one flag: --download-archive.
Without it, your script is stateless. It checks a channel or playlist, sees the same URLs again tomorrow, and wastes time reprocessing items you already handled. With it, the script keeps a simple memory of what's done.
Make downloads idempotent
This is the pattern:
yt-dlp \
--download-archive downloaded.txt \
-o "%(channel)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s" \
"https://www.youtube.com/playlist?list=PLAYLIST_ID"
Technical benchmarking found that using --download-archive downloaded.txt prevents duplicate processing and reduces bandwidth consumption by 60-80% in recurring batch jobs compared with scripts that ignore local state, as described in this yt-dlp playlist automation guide.
That’s why I treat the archive file as non-optional. It turns a blunt downloader into a repeatable job.
If a download script might run more than once, make it idempotent on day one.
For teams building longer processing chains, this workflow for downloading and processing with yt-dlp is a useful reference for how downloads connect to downstream media steps.
Build a recurring job
A simple Bash example that reads URLs from a file:
#!/usr/bin/env bash
set -euo pipefail
ARCHIVE_FILE="downloaded.txt"
URL_FILE="channels.txt"
OUTPUT_DIR="media"
mkdir -p "$OUTPUT_DIR"
while IFS= read -r url; do
[ -z "$url" ] && continue
yt-dlp \
--download-archive "$ARCHIVE_FILE" \
-o "$OUTPUT_DIR/%(channel)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s" \
--merge-output-format mp4 \
"$url"
done < "$URL_FILE"
A matching channels.txt might contain playlist URLs, channel feed URLs, or individual video URLs. Run the script daily with cron on Linux or Task Scheduler on Windows.
PowerShell version:
$archive = "downloaded.txt"
$output = "media"
$urls = Get-Content "channels.txt"
New-Item -ItemType Directory -Force -Path $output | Out-Null
foreach ($url in $urls) {
if ([string]::IsNullOrWhiteSpace($url)) { continue }
yt-dlp `
--download-archive $archive `
-o "$output/%(channel)s/%(upload_date)s - %(title)s [%(id)s].%(ext)s" `
--merge-output-format mp4 `
"$url"
}
Handle format and shell pitfalls
Batch jobs usually fail for boring reasons, not dramatic ones.
One issue is format mismatch. If you hardcode MP4 video plus M4A audio selectors, some videos won't provide that exact pair cleanly. A safer approach is to prefer best streams and then force a final container when needed:
yt-dlp -f "bv*+ba/best" --merge-output-format mp4 URL
Another issue is shell quoting. In scripts, quote every URL. Don't rely on shell-specific behavior.
Checklist for sturdier automation:
- Quote inputs. Wrap URLs so shell expansion doesn't break them.
- Persist state. Keep
downloaded.txtin a stable location. - Control output. Use templates that include IDs.
- Force a final container when needed.
--merge-output-format mp4is often the safer output for downstream tools. - Use ignore mode selectively.
-ihelps in playlists where one broken entry shouldn't stop the batch.
The recurring pattern is simple. Small flags make scripts durable. Leaving them out creates cleanup work later.
Beyond the Local Command Line Scaling with an API
Local scripts are phase one. They’re great for personal workflows, prototypes, and moderate batch jobs.
Then the limits show up. Your machine becomes the worker. Your internet connection becomes the bottleneck. Your local disk becomes a staging area you have to clean. If a job needs retries, concurrency control, webhooks, or parallel output variants, shell scripts start accumulating glue code.
Where local scripts start to hurt
A typical local chain might look like this:
yt-dlp -f "bv*+ba/best" --write-thumbnail --embed-metadata \
-o "downloads/%(title)s.%(ext)s" "https://www.youtube.com/watch?v=VIDEO_ID" && \
ffmpeg -i "downloads/input.mp4" -vf "scale=720:-2" -c:v libx264 -c:a aac "outputs/mobile.mp4"
That works. It also means your laptop or server now owns download reliability, storage management, FFmpeg runtime, and error logging.
API-first media processing begins to make sense. Instead of wrapping local binaries with more scripts, you submit the job remotely as structured input. If you're evaluating command-driven video infrastructure, this video editing API documentation is a useful example of how command execution can be exposed cleanly through an API layer.

The API version of the same workflow
The shape changes from shell syntax to JSON payload. Instead of SSH-ing into a box and hoping the environment matches your assumptions, you describe the command and let the service execute it.
For example, an API endpoint built for command execution can accept a yt-dlp job in the same spirit as your local command. A reference for that model is this run yt-dlp command endpoint.
The practical advantages are straightforward:
| Local scripting | API-based execution |
|---|---|
| Uses your machine or your server | Uses remote infrastructure |
| You manage retries and logging | The platform usually exposes job status and errors |
| Scaling means more servers or more queue code | Scaling usually means more requests |
| Geo-restricted access is your problem | Some platforms handle location-sensitive retrieval better |
The key shift isn't convenience. It's operational clarity. Local commands are excellent when you need direct control and low overhead. APIs are better when downloads become product features, scheduled workloads, or team infrastructure.
Troubleshooting Common Issues and FAQs
The most common failure mode is simple. The command worked yesterday and breaks today.
When yesterday's command stops working
Update yt-dlp first:
yt-dlp -U
That's the first move because extractor logic changes frequently. Old binaries age badly.
If downloads are slow, check whether you're using a conservative default path when the workload really needs concurrency. If merges fail, verify ffmpeg is installed and reachable in PATH. If a batch stops on a broken item, rerun with -i so one failure doesn't kill the whole queue.
Most yt-dlp problems aren't mysterious. They're version drift, missing FFmpeg, or a format assumption that no longer matches the source.
Quick answers to common edge cases
How do I download only comments?
Use metadata output without downloading the media file. People often ask for comment-only workflows, and yt-dlp supports this with --dump-single-json and --no-download, as discussed in this Super User thread on downloading only comments.
yt-dlp --dump-single-json --no-download "https://www.youtube.com/watch?v=VIDEO_ID"
You'll usually want jq or another JSON parser afterward.
How do I access members-only or authenticated content?
Use browser cookie import or authenticated session options supported by yt-dlp. The exact method depends on your environment and browser, but the principle is the same: don't try to fake a logged-in session manually if the tool can import it.
Why did my chosen MP4 format fail?
Because the source may offer a better stream in another codec or container pairing. When in doubt, inspect formats first and choose a merge-friendly fallback instead of hardcoding assumptions.
If your local YouTube download command line setup has started turning into queue management, retry logic, and remote worker maintenance, RenderIO is the next step worth testing. It gives you a cloud FFmpeg and yt-dlp API for running media jobs at scale without managing the infrastructure yourself.