yt-dlp Format Selection: -f, -S and Getting Exactly What You Want
Quick answer
Format selection decides resolution, codec, file size and whether the download works at all. It is the one yt-dlp concept worth learning properly. Two selectors cover most needs — the first is a hard requirement, the second a preference that never errors:
yt-dlp -f "bv*[height<=1080]+ba/b[height<=1080]/b" "URL"
yt-dlp -S "res:1080,vcodec:h264" "URL"
Start by looking
Every question about format selection is answerable from the format table:
yt-dlp -F "URL"
Rows marked video only and audio only mean the site splits its
streams — that is where + selectors apply and where ffmpeg becomes mandatory. Rows
showing both mean it does not, and bv* is required for anything to match.
Reading a selector
Four pieces of syntax carry almost all of it:
| Piece | Means |
|---|---|
bv / bestvideo | Best stream with video and no audio |
bv* | Best stream with video, audio optional |
ba / bestaudio | Best audio-only stream |
b / best | Best stream that already has both |
+ | Download both and merge them |
/ | Fallback: try the left, else the right |
[key=value] | Filter — only formats matching this |
So bv*[height<=1080]+ba/b[height<=1080]/b reads as: the best video stream at
or below 1080p plus the best audio, merged; failing that, the best combined stream at or below
1080p; failing that, anything at all. Three attempts, so it cannot produce
Requested format is not
available.
The trap in the word "best"
-f best does not mean best quality. It means the best pre-merged file,
which on YouTube is format 18 — 360p. This is the most-copied wrong command in the ecosystem,
and it is behind a large share of
"yt-dlp only downloads 360p".
yt-dlp's default, with no -f at all, already merges. If you are not sure, pass
nothing.
Filters worth knowing
| Filter | Selects |
|---|---|
[height<=1080] | 1080p or below |
[fps>30] | High frame rate only |
[ext=mp4] | mp4 container |
[vcodec^=avc1] | Codec starts with avc1 — that is H.264 |
[vcodec!*=av01] | Anything that is not AV1 |
[filesize<500M] | Under 500 MB, where the site reports a size |
[protocol^=http] | Plain HTTP rather than HLS or DASH |
Each filter narrows the set that can match. Three at once frequently leaves nothing, which is the usual reason an elaborate selector errors on a video that plays fine in a browser.
-S, and why it is usually the better tool
-f is a requirement. -S is a ranking over whatever exists, so it always
picks something:
yt-dlp -S "res:1080,fps,vcodec:h264,acodec:m4a" "URL"
Read as: prefer 1080p, then higher frame rate, then H.264, then AAC audio. A 720p-only video downloads at 720p instead of erroring.
Useful sort keys: res, fps, vcodec, acodec,
ext, size, br. Prefix with + to reverse —
-S "+size" gets the smallest file, which is the quickest way to check a video is
the one you meant before committing to 4 GB.
Codecs, in practice
| Codec | Trade-off |
|---|---|
| H.264 (avc1) | Plays on everything, hardware-decoded everywhere, largest files |
| VP9 | ~30% smaller at equal quality; decodes in software on older hardware |
| AV1 (av01) | Smallest; stutters badly without hardware support |
For a file destined for a TV, an older laptop or a phone, ask for H.264 and accept the size:
yt-dlp -S "res:1080,vcodec:h264" --merge-output-format mp4 "URL"
A note on resolution and quality
They are not the same thing. A 1080p AV1 stream at a low bitrate can look worse than 720p H.264
at a high one, and YouTube allocates bitrate unevenly across codecs. If a download "looks soft"
despite reporting 1080p, the codec is usually why — which is what the -S above
addresses.
Selectors worth keeping
| Goal | Selector |
|---|---|
| Best available, any container | -f "bv*+ba/b" |
| Best that is already mp4 | -f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b" |
| Cap at 1080p | -f "bv*[height<=1080]+ba/b[height<=1080]/b" |
| Prefer 1080p, accept less | -S "res:1080" |
| Maximum compatibility | -S "res:1080,vcodec:h264,acodec:m4a" --merge-output-format mp4 |
| Smallest file | -S "+size" |
| Audio only, no re-encode | -f "ba/b" -x --audio-format best |
| Avoid AV1 | -S "vcodec:h264,vcodec:vp9" |
Testing without downloading
--simulate runs the whole selection and writes nothing — the right way to check a
selector before pointing it at 900 videos:
yt-dlp --simulate --print "%(format_id)s %(height)sp %(vcodec)s %(filesize_approx)s" -f "bv*[height<=1080]+ba/b" "URL"
Making it permanent
Once a selector works, it belongs in your config file rather than in the one command you remember to type:
-S res:1080,vcodec:h264,acodec:m4a
--merge-output-format mp4
With the corollary that a forgotten -f line in that file is behind a good number of
confusing results later — --ignore-config is the one-run way to rule it out.
Frequently asked
What is the difference between best and bestvideo?
Why bv* and not bv?
Should I use -f or -S?
How do I avoid AV1?
Related
- Fix "Requested format is not available" in yt-dlp This error means your format selector matched nothing — not that the video is unavailable. How to read what -F...
- Why yt-dlp Only Downloads 360p — and How to Get 1080p or 4K yt-dlp defaulting to 360p is a symptom, not a setting. The four causes — no ffmpeg, a PO token gate, a wrong f...
- yt-dlp cheat sheet One page, every yt-dlp command worth memorising: quality, audio, playlists, subtitles, cookies, archives and r...