Skip to main content

aria2

The best SDK for aria2 — async JSON-RPC client for Python 3.14+ with WebSocket events, full static typing, and bundled binary.

import asyncio
from aria2 import Aria2Client, DownloadStatus

async def main():
    async with Aria2Client(secret="mytoken") as client:
        gid = await client.downloads.add_uri(["https://example.com/file.zip"])
        status = await client.status.tell_status(gid)
        print(f"Progress: {status.progress_pct:.1f}%")
        print(f"Speed: {status.speed_kbps:.0f} KB/s")

asyncio.run(main())

Features

  • 🚀 Async — built on asyncio, httpx, and websockets
  • 🔌 Dual transport — WebSocket primary, HTTP fallback
  • 🔔 Push events — download start/pause/stop/complete/error via WebSocket
  • 📦 Binary bundling — ships with aria2c (linux x86_64)
  • 🎯 Full static typing — pydantic models, StrEnums, type-checked via ty
  • 🛡️ Error hierarchy — Aria2RpcError, Aria2ConnectionError, etc.
  • 📋 CLI — aria2 start, aria2 status, aria2 check
  • 🧩 Sub-manager API — <10 public methods per class (downloads, status, options, system, events)

Quickstart

Install

pip install aria2-sdk

Requires Python ≥3.14. Dependencies: httpx, pydantic, websockets.

Usage

import asyncio
from aria2 import Aria2Client

async def main():
    async with Aria2Client(host="localhost", port=6800, secret="mytoken") as c:
        # Add a download
        gid = await c.downloads.add_uri(["https://example.com/video.mp4"])

        # Check status
        status = await c.status.tell_status(gid)
        print(f"Status: {status.status}")
        print(f"Progress: {status.progress_pct:.1f}%")
        print(f"Speed: {status.speed_kbps:.0f} KB/s")

        # Control
        await c.downloads.pause(gid)
        await c.downloads.unpause(gid)
        await c.downloads.remove(gid, force=True)

        # Global stats
        stat = await c.status.get_global_stat()
        print(f"Global speed: {stat.download_speed_kbps:.0f} KB/s")

        # System info
        version = await c.system.get_version()
        print(f"aria2 version: {version.version}")

asyncio.run(main())

Event callbacks (WebSocket)

from aria2 import Aria2Client

def on_start(gid: str) -> None:
    print(f"Download started: {gid}")

def on_complete(gid: str) -> None:
    print(f"Download complete: {gid}")

async with Aria2Client(secret="mytoken") as client:
    client.events.on_download_start(on_start)
    client.events.on_download_complete(on_complete)
    gid = await client.downloads.add_uri(["https://example.com/file.zip"])
    await asyncio.sleep(10)

API

Client lifecycle

# Context manager (recommended)
async with Aria2Client(secret="token") as client:
    ...

# Manual
client = Aria2Client(secret="token")
await client.connect()
...
await client.close()

Constructor

Aria2Client(
    host: str = "localhost",
    port: int = 6800,
    secret: str | None = None,
    *,
    enable_ws: bool = True,
    timeout: float = 30.0,
)

Sub-managers

All domain operations are grouped into 5 sub-managers, each with ≤10 public methods:

Manager Property Methods Description
DownloadManager client.downloads 9 Add, remove, pause, control downloads
StatusManager client.status 9 Query download status, files, peers
OptionsManager client.options 4 Get/set per-download and global options
SystemManager client.system 9 Daemon version, session, shutdown
EventManager client.events 6 Register WebSocket event callbacks

Downloads

# Add
gid = await client.downloads.add_uri(["https://example.com/file.zip"])
gid = await client.downloads.add_torrent(torrent_bytes, uris=["https://..."])
gids = await client.downloads.add_metalink(metalink_bytes)

# Control
await client.downloads.remove(gid, force=True)
await client.downloads.pause(gid)
await client.downloads.pause_all()
await client.downloads.unpause(gid)
await client.downloads.unpause_all()
await client.downloads.change_position(gid, 1, "POS_CUR")

Status

# Single download
status = await client.status.tell_status(gid)
status.progress_pct      # float
status.speed_kbps        # float
status.is_active         # bool
status.is_complete       # bool

# Batches
active = await client.status.tell_active()
waiting = await client.status.tell_waiting(offset=0, num=10)
stopped = await client.status.tell_stopped(offset=0, num=10)

# Details
files = await client.status.get_files(gid)       # list[FileInfo]
uris = await client.status.get_uris(gid)         # list[UriInfo]
servers = await client.status.get_servers(gid)   # list[ServerInfo]
peers = await client.status.get_peers(gid)       # list[PeerInfo]
stat = await client.status.get_global_stat()     # GlobalStat

Options

opts = await client.options.get_option(gid)           # dict[str, str]
await client.options.change_option(gid, {"max-connection-per-server": "4"})

global_opts = await client.options.get_global_option()
await client.options.change_global_option({"max-concurrent-downloads": "5"})

System

version = await client.system.get_version()         # Aria2Version
info = await client.system.get_session_info()       # dict[str, str]
methods = await client.system.list_methods()        # list[str]
notifications = await client.system.list_notifications()  # list[str]

await client.system.shutdown()
await client.system.save_session()
await client.system.purge_download_result()
await client.system.remove_download_result(gid)

# Batch RPC calls
results = await client.system.multicall([
    {"methodName": "aria2.tellStatus", "params": [gid]},
    {"methodName": "aria2.getGlobalStat"},
])

Errors

from aria2 import Aria2Error, Aria2ConnectionError, Aria2RpcError

try:
    status = await client.status.tell_status("invalid-gid")
except Aria2RpcError as e:
    print(f"RPC error [{e.code}]: {e.message}")
except Aria2ConnectionError:
    print("Cannot connect to aria2")

Models (pydantic)

All status methods return pydantic BaseModel instances with typed fields and convenience properties:

status = await client.status.tell_status(gid)
status.progress_pct      # float: 0.0–100.0
status.speed_kbps        # float: download speed in KB/s
status.is_active         # bool
status.is_complete       # bool
status.is_error          # bool

stat = await client.status.get_global_stat()
stat.download_speed_kbps # float
stat.upload_speed_kbps   # float

Download status responses use a discriminated union — each status variant (ActiveStatus, PausedStatus, ErrorStatus, CompleteStatus, RemovedStatus) is its own model, selected automatically at parse time:

status = await client.status.tell_status(gid)
match status.status:
    case DownloadStatus.ACTIVE:
        print(f"Downloading: {status.progress_pct:.1f}%")
    case DownloadStatus.COMPLETE:
        print(f"Completed at {status.completed_time}")

CLI

# Start aria2c daemon
aria2 start --secret mytoken --dir /downloads

# Check binary
aria2 check

# Query running daemon
aria2 status --secret mytoken

# Start in background
aria2 start --secret mytoken --daemon

Binary bundling

This package can bundle the aria2c binary inside the wheel. During build, a Hatchling build hook downloads the pre-compiled static binary from abcfy2/aria2-static-build for the detected platform.

At runtime, the SDK discovers the binary by trying:

  1. Bundled binary (wheel install)
  2. System aria2c from PATH
from aria2.bin import get_binary_path, get_binary_version

path = get_binary_path()       # Path to aria2c
ver = get_binary_version()     # Release tag (e.g. "release-1.37.0")

Development

# Setup
uv sync

# Type checking
ty check src/aria2/

# Lint
ruff check src tests

# Tests
uv run pytest tests/

Project structure

src/aria2/
├── __init__.py           # Public API re-exports
├── __main__.py           # CLI entry point
├── py.typed              # PEP 561 marker
├── bin/
│   └── __init__.py       # Binary discovery
├── cli/
│   └── __init__.py       # CLI commands (start, stop, status)
├── client/
│   ├── __init__.py       # Aria2Client lifecycle
│   ├── download.py       # DownloadManager (9 methods)
│   ├── status.py         # StatusManager (9 methods)
│   ├── options.py        # OptionsManager (4 methods)
│   ├── system.py         # SystemManager (9 methods)
│   ├── events.py         # EventManager (6 methods)
│   ├── _helpers.py       # Internal utilities
│   └── transport/
│       ├── __init__.py   # Transport ABC
│       ├── http.py       # HTTP via httpx
│       └── ws.py         # WebSocket + events
├── errors/
│   └── __init__.py       # Error hierarchy
├── models/
│   ├── __init__.py       # Re-exports all models
│   ├── base.py           # _BaseDownloadStatus
│   ├── download_response.py  # Discriminated union
│   ├── file.py, uri.py, peer.py, server.py, bittorrent.py
│   ├── global_stat.py, version.py, session.py
│   └── status_active.py, status_complete.py, status_error.py,
│       status_paused.py, status_removed.py
├── rpc/
│   └── __init__.py       # JSON-RPC 2.0 protocol
└── types/
    └── __init__.py       # GID, DownloadStatus, PositionHow

License

MIT

Metadata

Release files for aria2-sdk 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aria2-sdk 0.1.0
File Size Uploaded Provenance Actions
aria2_sdk-0.1.0.tar.gz 20.4 kB Without provenance Details for aria2_sdk-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for aria2-sdk 0.1.0
File Interpreter ABI Platform Actions
aria2_sdk-0.1.0-py3-none-any.whl Python 3 none any Details for aria2_sdk-0.1.0-py3-none-any.whl

Total release size: 5.5 MB

Release files / aria2_sdk-0.1.0.tar.gz

Download URL aria2_sdk-0.1.0.tar.gz
Size 20.4 kB
Tags Source
SHA-256 checksum
How to use checksums
71301684b164aa5a6a3c56b26bdb5f1a99c2944da7770ae5a66b5854ee74a0e5
BLAKE2b-256 checksum
How to use checksums
48e81a221b3cc3f6a77e580f6db8be5dfe0912d1e9cb0c7a654d845eb36d5b14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / aria2_sdk-0.1.0-py3-none-any.whl

Download URL aria2_sdk-0.1.0-py3-none-any.whl
Size 5.5 MB
Tags Python 3
SHA-256 checksum
How to use checksums
76aeca3c195289df7e0e3b408f812e7a6eb4f16b732a1527742fb3ab802bd9c3
BLAKE2b-256 checksum
How to use checksums
bfec5ccdf21c5c529c91b3fd642d4c662a4b1dac2095a7c5c3c803e0d486c7c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for aria2-sdk 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page