NanoTorrent

NanoTorrentA tiny, hackable
BitTorrent client

NanoTorrent is a pure-Rust port of PicoTorrent — the same lean application, rebuilt without a single C++ dependency, now on Windows, macOS and Linux. One Slint window everywhere, dark mode, a built-in web remote, and it reads your existing PicoTorrent settings on first run.

Written in Rust 2024 Windows · macOS · Linux Slint UI Dark mode DHT · PeX · MSE/PE uTP · LSD · web seeds BitTorrent v1 · v2 · hybrid Built-in web remote Headless mode Stream while downloading Rhai plugins Strict network mode 76 languages

Windows installer Microsoft Store macOS disk image Debian / Ubuntu .deb Fedora / RHEL .rpm Linux AppImage

Windows 10 / 11 · macOS · Linux

A look inside

One window, three platforms

The desktop client is drawn by Slint, so Windows, macOS and Linux get the same window rather than three approximations of it — and the web interface it ships with follows the same theme and the same language.

The NanoTorrent main window in its dark theme
The main window. The torrent list with all 16 columns and a rendered progress bar, the icon toolbar above it, and the details panel below. Everything here is drawn by Slint, so it is the same window on Windows, macOS and Linux.
The main window in its light theme
Light theme. Follows the OS by default, or is pinned in Preferences. The toolbar glyphs are drawn rather than shipped as images, so one set works on both palettes.
The Files tab of the details panel
Details ▸ Files. A real tree: folders that fold, the connector lines a file manager draws, and an icon per file type. Per-file size, progress, include toggle and priority; Peers — with GeoIP country and flag — and Trackers sit beside it.
The Preferences dialog
Preferences. Six tabs, applied live on OK: the session is rebuilt rather than requiring a restart, so rate limits, DHT, PeX, encryption and the proxy take effect at once.
The built-in web interface in its dark theme
The web interface. An authenticated HTTPS remote that ships in the binary, and it now draws what the app draws: the same file trees with the same icons, tabbed Details, and a toolbar that folds into the menu as the window narrows rather than wrapping.
The web interface in its light theme
It follows the theme too, and renders in the configured language — substituted server-side, so there is no flash of English and no second request.
The web interface Preferences drawer
The same settings, remotely. The drawer behind the hamburger is generated from the command line’s settings registry, so the desktop dialog, the terminal and the browser share one list, one set of types and one validator.

The torrents shown are Linux distribution images, used as sample data.

Latest release

What’s new

Straight from the release on GitHub, so this page cannot fall behind the code.

The notes for the current release live on the releases page.

What you get

Everything the original did — and then some

The full PicoTorrent feature set, ported across: settings database, translations, layout and all. Plus three things it never had — three platforms, a web interface, and plugins.

Windows, macOS and Linux

One window and one codebase on all three, drawn by Slint. Ships as an installer, a .dmg, .deb and .rpm packages, an AppImage that needs no install, and on the Microsoft Store.

Built-in web interface

An Actix server over HTTPS — Argon2id hashing, a per-address lockout, and it refuses to listen off-loopback in plaintext. State arrives as a server-sent event stream, not four polls a second. It carries the desktop’s toolbar, charts, file trees and every preference the dialog has, in your language.

Watch it before it finishes

A Play button in the Files tab serves byte ranges out of a file that is still downloading, seekable — the reader blocks on the piece under the read head and the engine fetches it. The URL carries a token good for one file for half an hour, never your password.

Headless, and scriptable

Build with --no-default-features for no window at all, driven entirely from the browser. Every preference the dialog offers is settable without one: --list-settings, --get, --set.

Plugins, on a leash

Optional Rhai scripts, off by default. Eleven permissions declared in a one-line header read before the script runs, so a plugin gets an engine holding only what was approved and reaching past it fails with “function not found”. An RSS auto-downloader and a media-player launcher ship as examples. Write one ▸

BitTorrent v2, not just the checkbox

v2-only .torrent files and v2-only magnets both download and seed, verified against their merkle piece hashes. No librqbit release implements BEP 52, so it is written here: the piece layers a magnet cannot carry are fetched with the v2 hash messages and checked against each file’s pieces root first. Hybrids announce under both info hashes at once.

The protocol, spelled out

Eighteen BEPs, fifteen in full: DHT, metadata exchange, PeX, multitracker tiers, UDP trackers, the fast extension, padding files and more. MSE/PE encryption both ways, µTP (BEP 29) for where TCP is throttled, and local discovery (BEP 14). Web seeds (BEP 19 and 17) arrive as synthetic peers, so their pieces are hash-checked exactly like a real peer’s.

Queues, limits and labels

Stop seeding at a ratio, a time, or whichever comes first, then pause or remove — global, overridable per torrent, off by default. Alternative speed limits on a schedule, with a turtle to force them. Queue order from the toolbar, per-file priorities, tags, coloured labels, and the PQL filter subset.

Where the files go

Watched folders that rename a .torrent aside rather than delete it, a separate incomplete folder, Move storage to relocate the files and Set location to relocate the torrent, and a low-disk guard that pauses everything below a percentage of the volume.

The list, and the details

Sixteen sortable columns with a rendered progress bar, multi-select, and widths remembered per list. Below it: a piece-availability bar, a folding file tree with per-type icons, include toggles and priorities, peers with GeoIP country and flag, and editable announce tiers. Two live speed charts in the toolbar, and native notifications on completion.

Adding, and creating

Magnet links fetch their metadata first, then show the real file list in the same dialog a .torrent gets — pick your files before it starts. Creating one does v1, v2 or hybrid, with trackers, comment and the private flag.

Strict network mode

Stop rather than leak. It switches off whatever your VPN interface or SOCKS proxy cannot cover — DHT, uTP, local discovery, UPnP — refuses to start if the named interface is missing, and pauses every torrent if it disappears. It is not a firewall: it stops this client talking around the tunnel, nothing else on the machine. Beside it: DB-IP country lookup and eMule / PeerGuardian blocklists.

An encrypted settings file

The whole database, in pure Rust, with the key in DPAPI on Windows and a 0600 file elsewhere — no password to type, and a change made outside NanoTorrent is detected rather than accepted. Preferences ▸ OK rebuilds the session live, so rate limits, DHT, encryption and the proxy take effect without a restart.

Bring your setup along

On Windows, first run copies your existing %LOCALAPPDATA%\PicoTorrent folder, leaving the original untouched. File ▸ Import from PicoTorrent then brings every torrent across with its save path and label, and reports what arrived, what was already there and what failed.

Every translation

All 76 languages, complete — every string the UI can show, and a translated --help to go with it. Compiled into the executable, listed by their native names, switchable live without a restart.

One file, no baggage

Languages, 252 country flags and the web interface are all embedded at build time, so the binary ships standalone. Builds are reproducible too: two builds of the same source are byte-identical.

Under the hood

Same job, three foundations

NanoTorrent against the client it is a port of, and against the one most people actually use. qBittorrent ships in two flavours — a libtorrent 1.2 build that speaks BitTorrent v1, and a libtorrent 2.0 build that adds v2 — so both are named wherever the answer differs between them.

Aspect PicoTorrent (C++) qBittorrent (C++ / Qt) NanoTorrent (Rust)
PlatformsWindowsWindows, macOS, Linux, FreeBSDWindows, macOS, Linux — plus a headless build
BitTorrent engineRasterbar-libtorrentlibtorrent-rasterbar, shipped as both a 1.2 and a 2.0 buildlibrqbit 9.0.1, vendored and patched
BitTorrent v2—Complete on the 2.0 build — v2-only torrents and btmh magnets included. The 1.2 build has none of it, and loads a hybrid as its v1 halfEvery build, with no second download to pick. Hybrids announce in both swarms
GUIwxWidgets (native Win32)QtSlint — one window on all three, dark mode included
Remote control—WebUI and a Web API, polled on an intervalActix over HTTPS with the desktop’s toolbar, charts and file trees, pushed as a server-sent event stream
Extensibility—Python search pluginsRhai plugins with eleven declared, enforced permissions — network, storage, a window of their own, and starting a program
Leak protection—Interface binding and a proxy, honoured wherever the engine canStrict network mode — refuses to start if the interface is missing, and pauses everything if it disappears
Settings storageSQLite (PicoTorrent.sqlite).conf files, plus a .fastresume per torrentThe same SQLite schema, optionally encrypted, and exportable as JSON
Translationslang/*.json embedded in a DBAround 70, community-translated76, complete, compiled into the exe and switchable live
Command lineTorrent and magnet argumentsqbittorrent-nox, driven by the Web APIEvery preference settable — and --help in all 76 languages
NotificationsTray balloonsNative, per platformNative on all three, plus in-app toasts
PackagingNSIS installerInstaller, .dmg, distro packages, Flatpak.exe · .dmg · .deb · .rpm · AppImage · Microsoft Store
Streaming while downloading——Byte ranges out of an unfinished file, seekable, behind a per-file token
Build requirementsMSVC and a C++ dependency treeQt, Boost and libtorrentRust 1.85+ · cargo build --release, and byte-for-byte reproducible
Standing on shoulders

Built on PicoTorrent

NanoTorrent is a port, not a rewrite from scratch. It owes its application structure, its settings database schema, its dialogs and its whole design philosophy to PicoTorrent — the excellent, deliberately small Windows BitTorrent client by Viktor Elofsson and contributors.

PicoTorrent is still available and still worth your time. If you're happy with it, keep using it — NanoTorrent exists for people who want the same experience on a memory-safe, C++-free stack.

This port is built predominantly with AI assistance under human review — see the AI declaration.

Visit PicoTorrent
PicoTorrentC++ · wxWidgets
libtorrent
NanoTorrentRust 2024 · Slint
librqbit
Straight with you

Where the edges still are

One real gap is left — two of the three were closed in 0.4.2. The rest of what used to be listed here is the operating system’s own behaviour, which no code in a torrent client would change, so it is labelled as such rather than dressed up as a bug.

Known gap Real and fixable. We intend to close it.

v2 seeding does not survive a restart One root cause: the engine’s v2 seams — identity override, piece verifier, hash provider — are add-time options, and session persistence does not carry them. A restored torrent has none of them and serves nothing until it is re-added from its .torrent. Two smaller symptoms sit behind it: leaf-layer hash requests are refused rather than computed, and a v2-only magnet’s layers are held by the resolver rather than installed. The blocker is verification rather than code — the wire format matches libtorrent byte for byte and the merkle arithmetic is checked both directions, but there is no live v2 swarm left to test against.

Platform behaviour The OS does this. No code here would change it.

Linux notifications need a daemon They go to the D-Bus org.freedesktop.Notifications service. No daemon means nothing to talk to, and a client cannot supply one — a headless box or a bare window manager gets a warning in the log and carries on.
macOS asks about your local network Local service discovery sends multicast and is on by default, so macOS raises its Local Network Privacy prompt on first launch. The bundle carries a reason string so the dialog says why, and declining switches LSD off and nothing else. The only lever would be shipping LSD off by default on macOS, trading LAN peer discovery for no prompt — a product choice, not a fix.
Windows will not let any app claim the magnet default Anti-hijacking, applied to every application equally. Registering the handler and opening Settings ▸ Default apps so you can confirm is the most any app is allowed to do.

Not a gap — an invitation The one thing we would genuinely like help with.

The translations are machine-assisted English is the only locale written by hand. The other 75 are complete rather than reviewed, so the failure mode is a wrong word rather than a missing one — in a language none of us reads, which is why no amount of re-checking from this end beats one report from somebody who does. If you spot one, open an issue naming the locale, the key or the English text, and what it should say. A lang/ folder next to the executable also overrides a locale without a rebuild, if you would rather just fix it locally.

Give it a spin

Windows, macOS or Linux — an installer or a package each, plus an AppImage that needs neither and a Microsoft Store listing that keeps itself up to date. Your PicoTorrent setup comes with you, and the Discord is there if you get stuck.