cheat sheet

aria2c Download Utility

Fast, multi-protocol download utility supporting HTTP(S), FTP, SFTP, BitTorrent, and Metalink with resumption and parallel connections.

aria2c Download Utility

What it is

aria2c is a lightweight, open-source command-line download utility that supports HTTP(S), FTP, SFTP, BitTorrent, and Metalink from a single tool. It can open multiple parallel connections per file, resume interrupted transfers, and batch-download from URL lists or Metalink descriptors, making it substantially faster than single-connection tools like wget for large files. Reach for aria2c when you need parallel segmented downloading, built-in torrent support, or reliable resumption across flaky connections.

The current release is 1.37.0 (November 2023) — development has slowed to security/dependency fixes only, with no new feature release in over two years. The binary is stable and ships in every major distro repo (apt install aria2, brew install aria2, winget install aria2.aria2), but for new projects also weigh wget2 (HTTP/2, multithreaded, drop-in wget CLI) and curl --parallel (built into curl ≥ 7.66, parallel transfers without segmenting a single file).

Basic downloads

By default aria2c saves the file to the current directory, naming it from the URL's last path component. Use --out to override the filename, --dir to set the destination directory, and -c to resume a partial download automatically.

bash
# Download a file (HTTP, HTTPS, FTP, or magnet link)
aria2c https://example.com/file.iso

# Rename the output file
aria2c --out=ubuntu-24.04.iso https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso

# Resume an interrupted download
aria2c -c https://example.com/large-file.tar.gz

Output (aria2c https://example.com/file.iso):

css
04/26 10:14:32 [NOTICE] Downloading 1 item(s)
[#a1b2c3 120MiB/700MiB(17%) CN:1 DL:4.2MiB ETA:2m48s]
[#a1b2c3 420MiB/700MiB(60%) CN:1 DL:4.5MiB ETA:1m02s]
04/26 10:17:01 [NOTICE] Download complete: /home/user/file.iso

Output (aria2c -c https://example.com/large-file.tar.gz):

csharp
04/26 10:18:05 [NOTICE] Downloading 1 item(s)
04/26 10:18:05 [NOTICE] Resume file found — continuing from byte 314572800
[#d4e5f6 300MiB/1200MiB(25%) CN:1 DL:3.8MiB ETA:3m45s]

Parallel connections & speed

--split (or -s) divides a single file into segments downloaded simultaneously from the same server; -x caps how many connections are opened to any one server. Together they dramatically reduce download time from servers that throttle per-connection bandwidth — a common pattern is -x 8 -s 8 to open eight parallel segments.

bash
# Open 8 connections to the same file (faster on slow servers)
aria2c --split=8 https://example.com/large.iso

# Set maximum download speed (bytes/sec; use K/M suffixes)
aria2c --max-download-limit=2M https://example.com/large.iso

# Download multiple files in parallel (not sequentially)
aria2c --force-sequential=false https://example.com/a.zip https://example.com/b.zip

Output (aria2c --split=8 https://example.com/large.iso):

css
04/26 10:20:11 [NOTICE] Downloading 1 item(s)
[#f7a8b9 512MiB/2048MiB(25%) CN:8 DL:18.3MiB ETA:1m25s]
[#f7a8b9 1024MiB/2048MiB(50%) CN:8 DL:17.9MiB ETA:0m42s]
04/26 10:21:39 [NOTICE] Download complete: /home/user/large.iso

Batch downloads from a file

--input-file (-i) reads a list of URIs from a text file, one per line, and downloads them according to the concurrency settings. The file format also supports per-URI options on indented lines immediately below the URI, letting you set a custom filename or destination directory for individual entries.

bash
# Download URLs listed one-per-line in a text file
aria2c --input-file=/path/to/urls.txt

# Download 1 at a time, resume partials, save to ~/Downloads
aria2c -j 1 -c -d ~/Downloads --input-file=/path/to/urls.txt

# Allow up to 4 parallel downloads from the list
aria2c --input-file=urls.txt --max-concurrent-downloads=4

Output: (none — exits 0 on success)

urls.txt format — each URI on its own line; options can follow the URI line:

text
https://example.com/file1.tar.gz
  out=file1.tar.gz
https://example.com/file2.zip
https://mirror.example.com/file3.iso
  dir=/tmp/isos

aria2c has a built-in BitTorrent client: pass a .torrent file URL or a magnet link and it handles peer discovery, piece verification, and seeding automatically. Metalink (.metalink / .meta4) is an XML format that lists multiple mirrors and checksums for a single file; aria2c downloads from them in parallel and verifies the result, making it ideal for large official releases.

bash
# Download via torrent file
aria2c https://example.com/ubuntu.torrent

# Download magnet link
aria2c "magnet:?xt=urn:btih:…"

# Download from torrent WITHOUT saving the .torrent file itself
aria2c --follow-torrent=mem "magnet:?xt=urn:btih:…"

# Seed ratio limit (stop seeding after uploading 2× what was downloaded)
aria2c --seed-ratio=2.0 ubuntu.torrent

Output: (none — exits 0 on success)

FTP / SFTP with authentication

aria2c supports both plain FTP and SFTP using --ftp-user and --ftp-passwd; the same flags cover both protocols. SFTP transfers are encrypted end-to-end, making them the right choice when you're fetching from a server that exposes only an SSH endpoint rather than a public HTTP mirror.

bash
# FTP download with credentials
aria2c --ftp-user=myuser --ftp-passwd=mypassword ftp://ftp.example.com/pub/file.tar

# SFTP (requires private key or password)
aria2c --ftp-user=myuser sftp://server.example.com/home/myuser/data.tar.gz

Output: (none — exits 0 on success)

Useful flags reference

FlagDefaultEffect
-c / --continuefalseResume partially downloaded file
-d DIR.Save directory
-o NAMEfrom URLOutput filename
-j N / --max-concurrent-downloads5Max parallel downloads
-x N / --max-connection-per-server1Connections per server
-s N / --split5Chunks per file
--max-download-limit0 (unlimited)Max speed (bytes/s)
--max-upload-limit0 (unlimited)Max seed speed
-i FILEURL list file
--follow-torrenttruemem = don't save .torrent

Checksum verification

--checksum accepts a hash algorithm and digest (sha-256=<hex>) and verifies the completed file against it, deleting the file and failing if the hash doesn't match. This is especially useful for OS images and large archives where a silent corruption would waste significant time.

bash
# Verify downloaded file against a known hash
aria2c --checksum=sha-256=<hash> https://example.com/file.iso

# Verify against multiple hashes (any one matching is OK)
aria2c --checksum=sha-256=<hex> --checksum=sha-1=<hex> https://example.com/file.iso

# Use SHA-512 for high-value artefacts
aria2c --checksum=sha-512=<128-char-hex> https://example.com/release.tar.gz

Output: (none — exits 0 on success)

A failed checksum exits with code 32 and deletes the bad file. Combine with --allow-overwrite=true and a wrapper script that retries on mismatch — silent disk-cache corruption from a flaky mirror will fail this check while bandwidth-saturated HTTP downloads succeed.

Connection tuning (-x, -s, -k, -j)

The four knobs that control aria2c's parallelism interact in a way that confuses newcomers: -j is the count of concurrent downloads, -s (--split) is the count of segments per file, -x (--max-connection-per-server) caps connections to a single host, and -k (--min-split-size) sets the smallest segment aria2c will create. For a single-host download, -s 16 -x 16 opens up to 16 parallel ranges; for a Metalink with multiple mirrors, -x 4 -s 16 still uses 16 segments but no more than 4 to any one mirror.

bash
# Maximum throughput on a fast mirror
aria2c -x 16 -s 16 -k 1M https://example.com/large.iso

# Be polite — at most 2 connections per server, 8 segments overall
aria2c -x 2 -s 8 https://example.com/large.iso

# Skip splitting small files (segments below -k are kept as one piece)
aria2c -k 5M -s 16 https://example.com/medium.tar.gz

# Run 4 downloads concurrently, each with 8 segments
aria2c -j 4 -s 8 -i urls.txt

Output: (none — exits 0 on success)

Many servers cap per-IP connections (HTTP 503 or RST after N parallel ranges). Start with -x 4 -s 8 and only raise it if the mirror tolerates it — going wider than needed slows downloads and gets your IP rate-limited.

--min-split-size defaults to 20 MB. Setting it lower (e.g. 1M) helps with small-to-medium files; setting it higher avoids tiny ranges that waste range-request overhead on multi-GB downloads.

Input file format reference

--input-file (-i) parses a plain-text URI list where each line is one URI, optionally followed by indented lines containing per-URI options. Lines beginning with # are comments and blank lines are ignored. The format is significantly richer than wget -i and supports almost every command-line option as a per-URI override.

text
# urls.txt
https://example.com/release.iso
  dir=/srv/iso
  out=release-stable.iso
  checksum=sha-256=abc123…

https://mirror1.example.com/big.tar.gz https://mirror2.example.com/big.tar.gz
  out=big.tar.gz
  split=8

# Magnet line — torrent options on following lines
magnet:?xt=urn:btih:abc123...
  seed-time=0
  bt-stop-timeout=300

# FTP with credentials
ftp://ftp.example.com/pub/file.tar
  ftp-user=alicedev
  ftp-passwd=secret

Two URIs separated by a space on the same line are treated as mirrors of the same file — aria2c will pick between them for each segment, which is the easy way to fan out across multiple CDNs.

bash
# Process a list, polite to mirrors, save each file's status
aria2c -j 2 -x 4 -i urls.txt --save-session=/tmp/aria2.session

Output: (none — exits 0 on success)

aria2c bundles a fully functional BitTorrent engine (DHT, PEX, UDP/TCP trackers, peer encryption) and a Metalink 3/4 parser. It can act as a standalone BitTorrent client, including seeding, and will follow .torrent files that are themselves the result of an HTTP download.

bash
# Magnet — keep .torrent only in memory, don't write it out
aria2c --follow-torrent=mem "magnet:?xt=urn:btih:<info-hash>"

# Disable DHT + PEX (private trackers; using them risks a ban)
aria2c --enable-dht=false --enable-peer-exchange=false private.torrent

# Force IPv4-only swarm
aria2c --disable-ipv6 my.torrent

# Listen on a specific port range (open these in your firewall)
aria2c --listen-port=51413 --dht-listen-port=51413 my.torrent

# Seed for at most 2 hours after completion
aria2c --seed-time=120 my.torrent

# Stop seeding once ratio 1.5 is reached
aria2c --seed-ratio=1.5 my.torrent

# Stop entirely when no peers for 5 min
aria2c --bt-stop-timeout=300 my.torrent

# Select specific files inside a multi-file torrent (indices)
aria2c --select-file=1,3,5-7 multi.torrent

# Metalink with mirror selection
aria2c --metalink-location=us,ca --metalink-preferred-protocol=https file.metalink

Output: (none — exits 0 on success)

aria2c will seed indefinitely by default after a torrent completes. Always set --seed-ratio, --seed-time, or --bt-stop-timeout — or pass --seed-ratio=0 to exit immediately on completion.

BitTorrent v2 / hybrid torrents

aria2c 1.37.0 added partial support for hybrid torrents — single .torrent files that carry both a BitTorrent v1 infohash and a v2 (BEP-52, SHA-256-keyed) infohash so they can be seeded into either swarm. aria2c will accept and download from a hybrid torrent's v1 swarm without extra flags; the v2 infohash is parsed but the v2-only swarm is not yet a first-class transport, so for v2-only torrents (no v1 hash) prefer a dedicated client like libtorrent-rasterbar-based clients (qBittorrent, deluge, transmission ≥ 4.0). If you maintain torrent infrastructure, generating hybrid torrents with mktorrent or transmission-create --tracker URL -o file.torrent --pieces 18 --v2 keeps both clients working.

bash
# Hybrid torrent — aria2c uses the v1 swarm transparently
aria2c hybrid.torrent

# Inspect a torrent before downloading (shows v1/v2 hashes and tree)
aria2c --show-files=true hybrid.torrent

Output (--show-files=true on a hybrid torrent):

text
*** Download Progress Summary ***
idx|path/length
===+===========================================================================
  1|./ubuntu-24.10-desktop-amd64.iso
   |5.7GiB (6,012,956,672)
---+---------------------------------------------------------------------------
Info Hash: 6a9759bffd5c0af65319979f2728c5b…  (v1)
           1234abc…f00d                       (v2)

RPC mode and JSON-RPC API

--enable-rpc starts aria2c as a long-running daemon that accepts JSON-RPC calls over HTTP or WebSocket on port 6800 by default. This is the foundation for every aria2 web UI (AriaNg, webui-aria2, Persepolis) and is the right architecture when you want to manage downloads from a different machine or script.

bash
# Start RPC daemon
aria2c --enable-rpc \
       --rpc-listen-all=true \
       --rpc-allow-origin-all=true \
       --rpc-secret=changeme \
       --dir=/srv/downloads \
       --max-concurrent-downloads=5 \
       --daemon=true

# Add a download via JSON-RPC
curl -sS http://127.0.0.1:6800/jsonrpc \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc":"2.0", "id":"1", "method":"aria2.addUri",
    "params": ["token:changeme", ["https://example.com/file.iso"]]
  }' | jq

# List active downloads
curl -sS http://127.0.0.1:6800/jsonrpc \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"1","method":"aria2.tellActive","params":["token:changeme"]}' | jq

# Pause / resume / remove a GID
curl -sS http://127.0.0.1:6800/jsonrpc -d \
  '{"jsonrpc":"2.0","id":"1","method":"aria2.pause","params":["token:changeme","<gid>"]}'

# Shutdown the daemon
curl -sS http://127.0.0.1:6800/jsonrpc -d \
  '{"jsonrpc":"2.0","id":"1","method":"aria2.shutdown","params":["token:changeme"]}'

Output: (aria2.addUri JSON-RPC response)

text
{"id":"1","jsonrpc":"2.0","result":"2089b05ecca3d829"}

--rpc-listen-all=true binds to every interface, including public ones. Combine with --rpc-secret (always) and a firewall rule that restricts source IPs — never expose port 6800 directly to the internet without authentication.

For WebSocket access (used by AriaNg and other browser UIs), the URL is ws://host:6800/jsonrpc; the protocol envelope is identical to HTTP JSON-RPC.

Session save and restore

--save-session writes the queue (active, waiting, paused) to a session file on exit, and --input-file (or --continue) replays it. Together they let aria2c survive restarts without losing the queue — essential for long mirror jobs and headless boxes.

bash
# Save queue on exit
aria2c --save-session=/var/lib/aria2/session.gz \
       --save-session-interval=60 \
       --input-file=/var/lib/aria2/session.gz \
       --continue=true \
       --enable-rpc \
       --daemon

Output: (none — exits 0 on success)

The combination of --save-session-interval=60 (rewrite the session every minute) and --continue=true (resume the actual file bytes) means a crash or systemctl restart loses at most one minute of progress and zero queue state.

Headers, cookies, and auth

Custom headers and cookie jars are supported for all HTTP sources. Cookies use the Netscape format (the same as wget and curl's cookie jars), so a session captured by curl can be replayed by aria2c directly.

bash
# Bearer token
aria2c --header="Authorization: Bearer TOKEN" https://api.example.com/blob

# Multiple headers
aria2c --header="Accept: application/octet-stream" \
       --header="X-Request-ID: 42" \
       https://example.com/file

# Cookie jar (Netscape format)
aria2c --load-cookies=cookies.txt https://example.com/protected/file.zip

# HTTP Basic auth
aria2c --http-user=alicedev --http-passwd=secret https://example.com/private

# Per-URI auth via input-file (cleaner — keeps creds out of process list)
# urls.txt:
#   https://example.com/private
#     http-user=alicedev
#     http-passwd=secret
aria2c -i urls.txt

Output: (none — exits 0 on success)

Proxy and network controls

aria2c respects the standard http_proxy / https_proxy / ftp_proxy environment variables and also takes per-protocol flags. SOCKS5 is supported through --all-proxy=socks5://... (libcurl-style URIs).

bash
# HTTP proxy
aria2c --http-proxy=http://proxy.example.com:8080 https://example.com/file

# Different proxies per protocol
aria2c --http-proxy=http://hproxy:8080 --https-proxy=http://sproxy:8443 URL

# SOCKS5 (with remote DNS — see ssh-tunnels page)
aria2c --all-proxy=socks5://127.0.0.1:1080 https://example.com/file

# Bypass proxy for selected hosts
aria2c --no-proxy="localhost,10.0.0.0/8,*.internal" URL

# Bind to a specific local interface (multi-homed host)
aria2c --interface=10.0.0.5 https://example.com/file

Output: (none — exits 0 on success)

Configuration file

aria2c reads ~/.aria2/aria2.conf (or --conf-path=FILE) at startup. Options in the file use long names without the leading --; the file is the right place to pin connection tuning, default directory, and RPC settings so command lines stay short.

text
# ~/.aria2/aria2.conf
dir=${HOME}/Downloads
continue=true
max-connection-per-server=8
split=8
min-split-size=1M
max-concurrent-downloads=4
file-allocation=falloc
remote-time=true
allow-overwrite=true
auto-file-renaming=false

# Logging
log=${HOME}/.aria2/aria2.log
log-level=notice

# RPC daemon (uncomment to enable)
# enable-rpc=true
# rpc-listen-all=false
# rpc-secret=changeme

file-allocation=falloc pre-allocates disk space using fallocate(2), eliminating fragmentation; on macOS or filesystems without fallocate support, use prealloc (slower) or none (fastest but fragments).

Common recipes

Mirror an HTTP directory listing

aria2c doesn't recurse into HTML directory listings the way wget --mirror does, so the pattern is "list URLs once, feed them in".

bash
# Get the listing, extract hrefs ending in .iso, feed into aria2c
curl -sS https://releases.example.com/iso/ \
  | grep -Eo 'href="[^"]+\.iso"' \
  | sed -E 's/href="([^"]+)"/https:\/\/releases.example.com\/iso\/\1/' \
  | aria2c -j 4 -x 4 -d /srv/iso -i -

Output: (none — exits 0 on success)

Resume a 50 GB download across reboots

bash
aria2c -c -x 8 -s 8 -k 4M \
       --file-allocation=falloc \
       --save-session=/tmp/big.session \
       --save-session-interval=30 \
       https://example.com/release-50gb.tar

Output: (none — exits 0 on success)

Headless seedbox with web UI

bash
# Daemon with persistent queue + RPC
aria2c --enable-rpc --rpc-listen-all=true --rpc-secret=changeme \
       --dir=/srv/dl --continue=true \
       --save-session=/srv/dl/.session --save-session-interval=60 \
       --input-file=/srv/dl/.session \
       --daemon
# Point AriaNg / webui-aria2 at http://myhost:6800/jsonrpc, secret=changeme

Output: (none — exits 0 on success)

Download from N mirrors of the same file

bash
aria2c -x 8 -s 16 \
       https://mirror1.example.com/big.iso \
       https://mirror2.example.com/big.iso \
       https://mirror3.example.com/big.iso

Output: (none — exits 0 on success)

Convert a wget -i list.txt workflow

bash
# wget pattern: wget -c -i list.txt -P /downloads
# aria2c equivalent (faster + parallel)
aria2c -c -j 4 -x 4 -d /downloads -i list.txt

Output: (none — exits 0 on success)

Exit codes

CodeMeaning
0All downloads finished successfully
1Unknown error
2Timeout
3Resource not found (404 etc.)
5Aborted because download speed too slow
6Network problem
7Unfinished downloads in queue at exit
8Remote server did not support resume
9Not enough disk space
15Renaming failed
24HTTP auth failed
25Could not create or open destination file
32Checksum validation failed

Script-friendly check:

bash
if ! aria2c --checksum=sha-256=$HASH "$URL"; then
  rc=$?
  echo "aria2c failed with code $rc — see exit-code table"
  exit $rc
fi

Output: (none — exits 0 on success)

aria2c vs wget vs wget2 vs curl vs yt-dlp

NeedBest tool
Single-connection scripted downloadcurl (API work) or wget (file save)
Mirror a website (recursive HTML crawl)wget --mirror or wget2 --mirror (HTTP/2, multithreaded)
Multi-segment / parallel acceleration on one filearia2c -x N -s N
Parallel transfers of many small filescurl --parallel --parallel-max N (curl ≥ 7.66)
Lightweight HTTP-only accelerationaxel -n N (smaller deps than aria2)
BitTorrent / magnet (v1 or hybrid)aria2c (v2-only: qBittorrent / transmission ≥ 4)
Mirror Metalink with checksumsaria2c
Resume after disconnectAll; aria2c handles partials cleanest
Long-lived daemon with web UIaria2c --enable-rpc
Video site extraction (YouTube, etc.)yt-dlp
Large file from a single fast mirrorcurl -O or wget — extra connections won't help

Don't reflexively reach for -x 16 -s 16. For a single fast HTTPS mirror, two or four connections is usually enough — going wider increases latency, raises the chance of mid-stream errors, and burns server resources. Multi-segment downloading shines on multi-mirror Metalink files and on servers that throttle per-connection bandwidth.

Sources