Skip to main content

Faster yt-dlp downloads with aria2

yt-dlp grabs the stream URLs, cookies and headers. aria2c then pulls the bytes with up to 16 parallel connections per file, turning a CDN-throttled single socket into a saturated pipe. This guide is the complete, practical reference: install, tune, automate, verify and troubleshoot.

Last reviewed 2026-09 · aria2 v1.37.0 · requires yt-dlp 2024+ and ffmpeg

Before you start

Only download content you are allowed to. Respect each site's Terms of Service and local copyright law.

How it works (and when it actually helps)

yt-dlp is a resolver: it negotiates the site, selects stream formats, and writes the exact request (URL, cookies, headers, byte ranges). aria2c is a transport engine: it opens many sockets to one host and downloads chunks in parallel. Pairing them gives you yt-dlp's correctness with aria2's raw throughput.

aria2 helps a lot for

  • Direct HTTP(S) media files (large video/audio tracks downloaded as one file)
  • YouTube-style DASH where the video and audio tracks are separate whole files
  • Multi-gigabyte 4K/8K downloads on a fast (500 Mbps+) link
  • Servers that throttle a single TCP connection but allow many byte-range requests

aria2 does not help for

  • Live streams (no fixed file length)
  • Fragmented HLS/DASH (thousands of tiny segments) — yt-dlp's native/ffmpeg downloader handles these; tune with -N instead
  • Servers that explicitly block parallel ranges (you'll see 403/429 — reduce -x)

Rule of thumb: if yt-dlp reports a single Destination file with a known size, aria2 will accelerate it. If it reports hundreds of small fragments, use -N 8 and skip the external downloader for that job.

Install & keep updated

yt-dlp is updated very frequently to keep up with site changes. Running an old build is the single most common cause of sudden failures.

# aria2
sudo apt install aria2          # Debian/Ubuntu
brew install aria2              # macOS
winget install aria2.aria2      # Windows (or: scoop install aria2)

# ffmpeg (needed to merge video+audio)
sudo apt install ffmpeg
brew install ffmpeg
winget install Gyan.FFmpeg

# yt-dlp - standalone binary (recommended), then self-update
yt-dlp -U

# yt-dlp - via Python/pip (then update with pip, not -U)
python -m pip install -U yt-dlp

Verify everything is on your PATH:

aria2c --version && yt-dlp --version && ffmpeg -version

Quickstart (one command)

Hand the download off to aria2 with --downloader and pass aria2 flags through --downloader-args using the aria2c: prefix:

yt-dlp --downloader aria2c --downloader-args "aria2c:-x 16 -s 16 -k 1M" "URL"

Flag anatomy

  • --downloader aria2c — use the aria2c external downloader for HTTP(S) downloads. (Older youtube-dl used --external-downloader; yt-dlp's modern name is --downloader.)
  • --downloader-args "aria2c:…" — everything after aria2c: is passed verbatim to the aria2c process.
  • -x 16 = --max-connection-per-server=16 (sockets per host)
  • -s 16 = --split=16 (file split into 16 chunks)
  • -k 1M = --min-split-size=1M (avoid connection churn on smaller files)

yt-dlp automatically forwards the cookies, User-Agent and required headers to aria2c, so signed URLs keep working.

Prove it is working: add --verbose and look for the aria2c invocation and its progress lines (see Verify & monitor).

Interactive yt-dlp + aria2 command generator

Pick your options and copy a ready-to-run command.

yt-dlp --downloader aria2c --downloader-args "aria2c:-x 16 -s 16 -k 1M" -f "bestvideo+bestaudio/best" --merge-output-format mkv --embed-subs --embed-chapters "URL"

Tune connections & splits

For a single file, aria2 opens up to min(split, max-connection-per-server) connections. Start at 16, then back off if a site rejects you.

Recommended aria2 settings by situation
Situation-x-s-kNotes
Fast home line / VPS (500 Mbps+)16161MMaximum throughput
Typical broadband881MGood balance, fewer blocks
Strict CDN / frequent 403 or 429442MLooks less like a scraper
Many items in a playlist16161MAlso raise aria2 -j (concurrency) with care
# Playlist-friendly: cap parallel files at 4 and add retries
yt-dlp --downloader aria2c \
  --downloader-args "aria2c:-x 16 -s 16 -k 1M -j 4 --retry-wait=3 --max-tries=5" \
  "PLAYLIST_URL"

Fragmented streams (HLS/DASH) are a different path: leave aria2 out and raise yt-dlp's own parallel fragments with -N 8 (e.g. yt-dlp -N 8 URL).

Format selection & merging

yt-dlp downloads video and audio as separate tracks, then ffmpeg merges them. This is independent of aria2 (are the tracks single files? then aria2 accelerates each one).

# Best quality, remux to MKV
-f "bestvideo+bestaudio/best" --merge-output-format mkv

# Cap resolution without losing the best audio
-S "res:1080" -f "bv*+ba/b"

# Audio only (to MP3 via ffmpeg)
-x --audio-format mp3 --audio-quality 0

# Show every available format first
-F URL

-S (sort) is usually cleaner than hard-coding -f filters. --merge-output-format requires ffmpeg.

Make it permanent

Instead of retyping flags, put them in a yt-dlp config file.

yt-dlp config (one flag per line)
--downloader aria2c
--downloader-args "aria2c:-x 16 -s 16 -k 1M --file-allocation=falloc --retry-wait=3 --max-tries=5"
-f "bestvideo+bestaudio/best"
--merge-output-format mkv
--embed-metadata
--embed-chapters
--embed-thumbnail
-o "%(title)s [%(id)s].%(ext)s"

Windows quoting: the double quotes around the aria2c: value are required. In PowerShell they work as-is; in a config file use literal double quotes as shown.

Production recipes

Copy-paste starting points for the jobs people actually run.

Download a whole playlist/channel without re-downloading

yt-dlp --downloader aria2c \
  --downloader-args "aria2c:-x 16 -s 16 -k 1M -j 3" \
  --download-archive archive.txt \
  -o "%(playlist_title)s/%(playlist_index)s - %(title)s.%(ext)s" \
  "PLAYLIST_URL"

Private / age-restricted videos (cookies)

yt-dlp --cookies-from-browser firefox \
  --downloader aria2c --downloader-args "aria2c:-x 16 -s 16 -k 1M" "URL"

# or a Netscape cookies.txt exported earlier
yt-dlp --cookies cookies.txt ... "URL"

Route through a proxy

yt-dlp --proxy "http://127.0.0.1:8080" \
  --downloader aria2c \
  --downloader-args "aria2c:--all-proxy=http://127.0.0.1:8080 -x 8 -s 8" "URL"

Set the proxy for yt-dlp (metadata) and for aria2 (payload). aria2 only accepts HTTP proxies: if yours is SOCKS5, keep it for yt-dlp and give aria2 a local HTTP-to-SOCKS bridge (privoxy, gost).

Limit bandwidth so you don't saturate the link

yt-dlp --downloader aria2c \
  --downloader-args "aria2c:-x 8 -s 8 --max-download-limit=5M" "URL"

# or cap yt-dlp/aria2 overall
yt-dlp -r 5M --downloader aria2c --downloader-args "aria2c:-x 8 -s 8" "URL"

Only a clip, subtitles, thumbnail, metadata, SponsorBlock

# a 5-minute slice
yt-dlp --download-sections "*10:15-15:00" ... "URL"

# subtitles + thumbnail + metadata, embedded
yt-dlp --write-subs --sub-langs "en.*" --embed-subs \
  --embed-thumbnail --embed-metadata --embed-chapters ... "URL"

# remove sponsor segments (needs ffmpeg)
yt-dlp --sponsorblock-remove sponsor ... "URL"

Batch a list of URLs

yt-dlp --downloader aria2c --downloader-args "aria2c:-x 16 -s 16 -k 1M -j 3" \
  --batch-file urls.txt

Verify & monitor

Confirm aria2 is really doing the download:

yt-dlp --verbose --downloader aria2c \
  --downloader-args "aria2c:-x 16 -s 16 -k 1M --summary-interval=5" "URL"

Troubleshooting

HTTP 403 Forbidden / aria2 exited with code 1, 3 or 9

Cause: the CDN URL is a short-lived signed link, or the site dislikes many parallel connections / a non-browser User-Agent.
Fix: update yt-dlp (yt-dlp -U), reduce to -x 8 -s 8, and pass cookies with --cookies-from-browser. yt-dlp forwards headers automatically, so avoid overriding the User-Agent unless the site requires it.

"external downloader ... not installed" / aria2c not found

Cause: aria2c is not on your PATH (or yt-dlp can't find it).
Fix: install aria2 (see Installation above); on Windows place aria2c.exe next to yt-dlp.exe or add its folder to Path; reopen the terminal.

Download is a folder of tiny fragments / very slow

Cause: the source is a fragmented HLS/DASH stream, which aria2 doesn't accelerate.
Fix: drop the external downloader for that job and use yt-dlp's native fragments: yt-dlp -N 8 URL.

HTTP 429 Too Many Requests

Cause: too many connections/requests in a short window.
Fix: reduce -j and -x, add --sleep-requests 1, and slow concurrent items.

Merge/remux fails or output has no audio

Cause: ffmpeg missing, or the chosen container is incompatible with the codecs.
Fix: install ffmpeg and verify with ffmpeg -version; use --merge-output-format mkv (most tolerant) instead of mp4.

Live stream never finishes

Cause: live streams have no fixed size. aria2 waits for a Content-Length that never comes.
Fix: don't use the aria2 downloader for live; use yt-dlp's default (--live-from-start to record from the beginning where supported).

Windows: "aria2c:-x is not recognized" / args ignored

Cause: shell quoting split the aria2c: value.
Fix: wrap the whole value in double quotes: --downloader-args "aria2c:-x 16 -s 16 -k 1M"; avoid mixing single and double quotes in PowerShell.

FAQ

Is 16 connections always better?

No. Beyond your link's capacity extra connections add overhead and can trigger rate limits. 8 is a safer default; drop to 4 on strict servers.

Does this work for YouTube playlists and channels?

Yes. aria2 downloads each track in parallel; use --download-archive to avoid re-downloading and keep -j modest to avoid throttling.

Can I use aria2 with yt-dlp --newline for logs?

Yes — --newline just changes yt-dlp's progress formatting; it doesn't affect the external downloader.

Where do downloads land?

In the current directory, or wherever -P/-o points. Example: -P ~/Downloads.

Use this only for content you have the right to download.