M: Trying to download a playlist from YouTube using yt-dlp. There are way too many options for me not to try asking you. I’m trying to get an MP4, doesn’t need to be the highest resolution.
G: Here's a clean and simple
yt-dlp command that will download a YouTube playlist as MP4
video files in decent quality (not the highest, but good enough):
yt-dlp -f "mp4[height<=720]" -o "%(playlist_index)s - %(title)s.%(ext)s" URLBreakdown:
-f "mp4[height<=720]" – selects MP4 videos with
resolution 720p or lower (to avoid huge files).-o "%(playlist_index)s - %(title)s.%(ext)s" – saves
files as 01 - Title.mp4, 02 - Title.mp4,
etc.URL – replace with the actual playlist URL.Optional: If you want to avoid re-downloading files you already got earlier:
--download-archive downloaded.txtLet me know if you also want to grab just audio or subtitles or strip metadata.
M: It’s saying: Got error: HTTPSConnectionPool(host=‘rr2—sn-8xgp1vo-gpjl.googlevideo.com’, port=443): Read Timed out. (Read timeout=20.0). Retrying
G: That timeout message means
yt-dlp is having trouble getting data from one of YouTube’s
video servers—usually due to a slow or unstable connection, temporary
server issues, or overaggressive default timeout settings.
Try one or more of these fixes:
yt-dlp -f "mp4[height<=720]" --socket-timeout 60 URLThat gives YouTube’s servers more time to respond.
yt-dlp -f "mp4[height<=720]" --limit-rate 500K URLSlowing it down a little can improve stability, especially on flaky connections.
yt-dlp -f "mp4[height<=720]" --retries 10 --fragment-retries 10 URLUseful if only a few files are failing intermittently.
Sometimes MP4 downloads are served via fragmented streams (more prone to failure). This alternative format selection avoids that:
yt-dlp -f "bestvideo[ext=mp4][height<=720]+bestaudio[ext=m4a]/best[ext=mp4][height<=720]" URLLet me know if you want to just resume from where it failed. There's a flag for that too.
M: Still giving a time error - and it’s streaming fine on browser, so it shouldn’t be just the connection.
G: Got it. If it's streaming fine
in the browser but yt-dlp is timing out, that usually
points to one of these:
yt-dlp or ffmpeg, so signatures/URLs
are handled wrong.Let’s fix it systematically.
Run:
yt-dlp -UAlso make sure ffmpeg is installed and up-to-date. You
can check with:
ffmpeg -versionIf it's not installed, install it (on most Linux distros:
sudo dnf install ffmpeg or
sudo apt install ffmpeg).
Googlevideo sometimes times out over IPv6. Force IPv4:
yt-dlp -f "mp4[height<=720]" --force-ipv4 URLyt-dlp -f "mp4[height<=720]" --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" URL--http-chunk-size (forces smaller download
chunks)yt-dlp -f "mp4[height<=720]" --http-chunk-size 1M URLThis helps on flaky CDN segments.
yt-dlp -f "mp4[height<=720]" --force-ipv4 --user-agent "Mozilla/5.0" --http-chunk-size 1M --retries 10 --fragment-retries 10 URLLet me know if you want to test just a single video from the playlist to troubleshoot more easily.
M: Hold on, accidentally hit enter. Before the errors I reported before, it gives me: [youtube:tab] PL5j80D9V7lqZwWY6qGgp5Iae06A4o2eqn page 1: Downloading API JSON WARNING: [youtube:tab] Incomplete data received. Retrying (1/3)…
G: That warning:
[youtube:tab] Incomplete data received. Retrying (1/3)…
means YouTube gave yt-dlp partial or malformed playlist
data. Combined with your earlier HTTPSConnectionPool
timeout, this strongly suggests YouTube is rate-limiting or
throttling API-style access, not regular streaming.
--extractor-args "youtube:player_client=web"This forces yt-dlp to use the same client type as the
browser (which works for you), avoiding mobile/API-specific issues:
yt-dlp -f "mp4[height<=720]" --extractor-args "youtube:player_client=web" URL--flat-playlist to avoid parsing all
metadata upfrontThis just gets video URLs fast, downloads them one by one:
yt-dlp --flat-playlist URL(Then you can feed the individual URLs to yt-dlp for
actual downloads.)
If it's from a logged-in account, YouTube might serve garbage to non-authenticated requests.
You can export cookies using a browser extension like Get cookies.txt and then:
yt-dlp --cookies cookies.txt -f "mp4[height<=720]" URLWant me to condense this into a “just works” one-liner based on what seems most likely in your case?
M: yes please
G: Here’s a “just works” version that avoids API errors, rate-limits, and CDN timeouts:
yt-dlp -f "mp4[height<=720]" --extractor-args "youtube:player_client=web" --force-ipv4 --user-agent "Mozilla/5.0" --http-chunk-size 1M --retries 10 --fragment-retries 10 URLReplace URL with your playlist link.
If that still fails, your next best move is exporting your browser
cookies and adding --cookies cookies.txt to the same line.
Let me know if you want a one-liner with that added too.
M: my cookies are an .sqlite file. can i use that directly or do i need to export from fedora linux
G: yt-dlp
can’t use .sqlite directly — it expects a
cookies.txt format (Netscape-style). But since you're on
Fedora Linux, you can extract the cookies easily using a tool.
browser_cookie3 (cleanest way,
Python-based)pip install browser-cookie3browser-cookie3 firefox > cookies.txtThen use:
yt-dlp --cookies cookies.txt -f "mp4[height<=720]" --extractor-args "youtube:player_client=web" --force-ipv4 --user-agent "Mozilla/5.0" --http-chunk-size 1M --retries 10 --fragment-retries 10 URLInstall this in Firefox or Chrome:
Go to YouTube, export cookies via the extension, save as
cookies.txt, and use the same command above.
Let me know which method you prefer, or if you want a script version that does this automatically.
M: browser-cookie3 isn’t running as a command. do i need to preface it with something involving python
G: If browser-cookie3
isn’t available as a direct command after install, it may not have
linked properly, or you might be in a Python environment where the
binary path isn’t exposed.
Try running it like this:
python3 -m browser_cookie3 firefox > cookies.txtOr if you're using pipx:
pipx run browser-cookie3 firefox > cookies.txtIf neither works, check installation with:
pip show browser-cookie3Let me know what it says — I can help adapt based on where it’s installed.
M: location: /home/david/miniconda3/lib/python3.11/site-packages Requires: jeepney, lz4, pycryptodomex
G: Thanks — since you're using
Miniconda, the browser-cookie3 script likely wasn’t added
to your system’s PATH. But you can still run it directly
via Python:
python3 -m browser_cookie3 firefox > cookies.txtThat should extract cookies from Firefox into
cookies.txt, which you can then feed to yt-dlp
like so:
yt-dlp --cookies cookies.txt -f "mp4[height<=720]" --extractor-args "youtube:player_client=web" --force-ipv4 --user-agent "Mozilla/5.0" --http-chunk-size 1M --retries 10 --fragment-retries 10 URLLet me know if Firefox isn’t your default or if it still throws issues.
M: main.py: error: the following arguments are required: name
G: Ah, right —
browser-cookie3 changed its CLI a while back. It now
requires you to specify the domain (or use --browser if you
want to force the browser).
Try this instead:
python3 -m browser_cookie3 --browser firefox youtube.com > cookies.txtThat grabs YouTube-related cookies from Firefox and saves them to
cookies.txt.
Then plug that into yt-dlp:
yt-dlp --cookies cookies.txt -f "mp4[height<=720]" --extractor-args "youtube:player_client=web" --force-ipv4 --user-agent "Mozilla/5.0" --http-chunk-size 1M --retries 10 --fragment-retries 10 URLM: New wrinkle: I tried directly downloading a video on the list. Worked fine. So it’s likely to do with how the playlist version is being read. Is there a workaround? Like, can I tell it to download the entire playlist based on the list the video I downloaded will follow?
G: Yes — if the individual video downloads fine, but the playlist view is unreliable, you can bypass playlist parsing entirely and just extract all the video URLs first, then download them one by one.
yt-dlp --flat-playlist --print "%(url)s" PLAYLIST_URL > urls.txtyt-dlp -a urls.txt -f "mp4[height<=720]" [other flags...]This skips all the API/metadata weirdness and just downloads videos as if they were independent.
yt-dlp -f "mp4[height<=720]" $(yt-dlp --flat-playlist --print "%(url)s" PLAYLIST_URL)(Use with caution if the playlist is huge — the shell might hit an argument-length limit.)
Let me know if you want to preserve playlist order or naming structure in filenames — that can be added too.
M: what flag would make the program wait a few seconds between each download? it’s almost working, but it seems to be resistant to giving it up all at once
G: To add a pause between downloads, use:
--sleep-interval 5That tells yt-dlp to wait 5 seconds between video
downloads.
If you want to randomize it a bit (to look more human), you can combine:
--sleep-interval 5 --max-sleep-interval 10That adds a random delay between 5 and 10 seconds after each video.
So your full command might look like:
yt-dlp -a urls.txt -f "mp4[height<=720]" --sleep-interval 5 --max-sleep-interval 10 --retries 10 --fragment-retries 10 --http-chunk-size 1MThat should help ease the throttling or API resistance.
M: Last thing for the night. I’m working off of the url file. Is there a simple way to add a number to the downloaded file so that it has some kind of order? I can’t use the automatic numbering from the playlist because of the workaround.
G: Yep — you can add numbering
manually based on the order in your urls.txt by using
--output with %(autonumber)s, which assigns
numbers based on position in the input list:
yt-dlp -a urls.txt -f "mp4[height<=720]" \
--output "%(autonumber)03d - %(title)s.%(ext)s" \
--sleep-interval 5 --max-sleep-interval 10That gives you filenames like:
001 - Video Title.mp4
002 - Another Video.mp4
...
Adjust 03d to 02d, 04d, etc.,
depending on how many digits you want.
Sleep well — this setup should run quietly overnight.