Fast, resilient, multi-source download manager and accelerator for Windows, macOS, and Linux.
https://hydra.javad.dev
- Overview
- Key Features
- Installation
- Uninstall
- Usage
- Benchmark
- Embedding HYDRA —
libhydra - Contributing
- License
Hydra Download Manager (HDM) is an open-source, high-performance network file retriever and download accelerator designed for speed, resilience, and adaptability. It dynamically partitions downloads across multiple connections and independent mirror sources, continuously rebalancing work to maximize throughput without stalling on slow peers. It ships as both a wget/curl-compatible CLI and a cross-platform desktop download manager with browser integration.
|
|
|
CLI:
brew install ja7ad/tap/hydramacOS Desktop App (GUI):
brew install --cask ja7ad/tap/hydraUbuntu / Debian-based (Launchpad PPA):
sudo add-apt-repository ppa:sonycore/hydra
sudo apt update
sudo apt install hydraPPA Repository: launchpad.net/~sonycore/+archive/ubuntu/hydra
Fedora / RHEL-based (Fedora COPR):
sudo dnf copr enable sonycore/hydra
sudo dnf install hydraCOPR Repository: copr.fedorainfracloud.org/coprs/sonycore/hydra
Arch Linux (AUR):
Build from source:
paru -S hydra-download-manager
# or: yay -S hydra-download-managerPrecompiled binary:
paru -S hydra-download-manager-bin
# or: yay -S hydra-download-manager-binAUR Packages: hydra-download-manager | hydra-download-manager-bin
One file, no installation, no root. Download it from the latest release, make it executable, and run it:
chmod +x Hydra-*-x86_64.AppImage
./Hydra-*-x86_64.AppImageaarch64 images are published alongside the x86_64 ones. Every release is
built on the oldest supported Ubuntu and verified to run on 22.04 through the
current release, so one image covers the whole line and the distributions
downstream of it.
The image carries the GUI, the hydra CLI, the hydra-host native-messaging
bridge and the update finisher. On its first start it writes a menu entry, a
copy of the browser extensions and the native-messaging manifests into
~/.local/share/hydra — all of them pointing at the image file, so moving or
renaming it is repaired on the next launch. Nothing is written outside your
home directory and nothing needs root.
| Command | What it does |
|---|---|
./Hydra-*.AppImage |
run the GUI |
./Hydra-*.AppImage --hydra-exec hydra … |
run the CLI inside the image |
./Hydra-*.AppImage --hydra-install |
write the menu entry and browser manifests now |
./Hydra-*.AppImage --hydra-uninstall |
remove them again (downloads and settings are kept) |
./Hydra-*.AppImage --hydra-extensions |
print the directory to load the unpacked extensions from |
Set HYDRA_APPIMAGE_NO_INTEGRATION=1 for a run that writes nothing outside
your download directory. For a fully self-contained copy — settings included —
create a directory named after the image with a .home suffix next to it
(Hydra-0.3.14-x86_64.AppImage.home); the AppImage runtime then uses it as
$HOME, which is what makes the image portable across machines on a USB stick.
Updates. This is the one Linux build Hydra can update itself: the deb and
the rpm install into /usr, which only their package manager may rewrite, so
the in-app updater offers you the new package instead of touching those files.
An AppImage is a single file you own wherever you put it, so Update Now
replaces that file and relaunches — including when it sits somewhere only root
can write, where it asks for your password first. The image also advertises
zsync update information, so AppImageUpdate and appimaged can update it
too.
Because it does not bundle GTK, the graphics stack or ALSA — those come from your desktop, where they are already correct — a portal-capable desktop is still what the file dialogs need. Nothing else is required.
macOS / Linux — installs the GUI bundle (GUI + CLI + browser extensions) by default:
curl -fsSL https://raw.githubusercontent.com/ja7ad/hydra/main/install.sh | bashCLI only:
curl -fsSL https://raw.githubusercontent.com/ja7ad/hydra/main/install.sh | bash -s -- --cliWindows (PowerShell) — installs the GUI bundle by default:
irm https://raw.githubusercontent.com/ja7ad/hydra/main/install.ps1 | iexCLI only:
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ja7ad/hydra/main/install.ps1))) -CliThe scripts detect your OS and architecture (amd64/arm64), fetch the matching archive from the latest GitHub release, and install it — on Linux and macOS to /usr/local (falling back to ~/.local; override with --prefix DIR), on Windows to %LOCALAPPDATA%\Programs\Hydra. The CLI lands under both hydra and the short hya; an existing hya on the same prefix is never overwritten. GUI installs also register the browser native-messaging host. Pin a release with --version vX.Y.Z / -Version vX.Y.Z, or download the archives yourself from the releases page.
A GUI install is a real desktop app, not a loose binary:
- Windows — a start-menu shortcut (
-Desktopadds a desktop one) and an Apps & features entry, so Hydra is listed and uninstallable from Settings like any other app. - macOS —
Hydra Download Manager.appis installed into/Applications(override with--app-dir DIR, e.g.~/Applications), with its icon and name in Launchpad, Spotlight, the Dock and the app switcher.hydra,hya,hydra-guiandhydra-hostin<prefix>/binare symlinks into the app, so the CLI stays onPATHand one update refreshes both. - Linux — the logo lands in the hicolor icon theme and a
hydra.desktopentry in your applications directory (plus the prefix's, for a system-wide install), so the app shows up in the launcher, the dock and the switcher with its own icon.
Either way the GUI can update itself in place afterwards (Options → General → Check for updates), including an install that lives in a root-owned directory — it asks for authorisation before replacing those files.
Beta channel — --beta (-Beta on Windows) installs the newest -rc pre-release when it is ahead of the latest stable release; otherwise it installs the stable release:
curl -fsSL https://raw.githubusercontent.com/ja7ad/hydra/main/install.sh | bash -s -- --beta& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ja7ad/hydra/main/install.ps1))) -BetaThe GUI's in-app updater follows the same rule: enable Options → General → Download Beta channel and update checks will also offer release candidates while one is ahead of stable.
macOS notes: since the app isn't notarized yet, Gatekeeper may block it — see the macOS Permissions Guide for granting the required permissions. If you installed via the .dmg and macOS refuses to open the app ("damaged" or "unidentified developer"), clear the quarantine attribute:
xattr -cr /Applications/Hydra\ Download\ Manager.appEnsure you have Rust (1.80+) installed:
git clone https://github.com/ja7ad/hydra.git
cd hydra
cargo build --releaseThe compiled binary will be located at target/release/hydra. To build the GUI and native-messaging host as well, run make build.
Hydra integrates directly with web browsers to automatically capture downloads, provide right-click context menu options, and intercept media streams.
Install the extension directly from the official store for your browser:
- Chrome Web Store (for Google Chrome, Microsoft Edge, Brave, Vivaldi, Opera, Arc, and Chromium-based browsers):
Chrome Web Store: Hydra Download Manager Integration - Firefox Add-ons (AMO) (for Mozilla Firefox):
Firefox Add-ons: HDM Integration - Safari: Ships inside the macOS desktop application bundle (enable under Safari → Settings → Extensions).
Tip: In the desktop GUI, you can also view status and open extension store listings directly from Options → Extensions or the Extensions toolbar button.
Extension source code and resources are maintained under the extensions/ directory:
extensions/chrome/— Chromium MV3 extension source code (shared core).extensions/firefox/— Firefox MV3 event-page add-on source.extensions/safari/— Safari Web Extension resources.
Every installer also ships pre-built extension packages with the app in both packed (.zip / .xpi) and unpacked shapes:
| Install | Extensions directory |
|---|---|
| Windows (setup.exe) | %LOCALAPPDATA%\Programs\Hydra\extensions |
| macOS (.app / DMG) | Hydra Download Manager.app/Contents/Resources/extensions |
| macOS (.pkg) | /Library/Application Support/Hydra/extensions |
| Linux (.deb / .rpm) | /usr/share/hydra-download-manager/extensions |
| Linux (AppImage) | ~/.local/share/hydra/extensions |
Archive / install.sh |
<prefix>/share/hydra/extensions |
- Chrome, Edge, Opera, Brave, Vivaldi, Arc, Chromium — open
chrome://extensions(edge://extensions,opera://extensions, …), turn on Developer mode, choose Load unpacked, and pick theextensions/chrome/(or bundledchrome/) directory. The manifestkeypins the id tojpnonmbbkjdpeebdhkjoliklfhkdcomjacross all Chromium browsers, matching the native-messaging host allow-list. The packed.zipis the Web Store upload format, and the signed.crxis for enterprise policy deployment (ExtensionSettings/ExtensionInstallForcelistagainst an update manifest you host). - Firefox — open
about:debugging#/runtime/this-firefox→ Load Temporary Add-on… and pickextensions/firefox/manifest.jsonor the packed.xpi. Developer Edition, Nightly, and ESR can install it permanently after settingxpinstall.signatures.requiredtofalseinabout:config.
To build and assemble extensions from a repository checkout:
make extensions # -> target/extensions
make extensions ARGS="--crx-key path/to/key.pem" # also sign a .crxA .crx is packed whenever a signing key is available (--crx-key, $HYDRA_CRX_KEY, or
target/hydra-chrome-crx.pem); --crx generates one if there is none. Sign with the key behind
the pinned manifest key — any other key changes the extension id, and the script says so.
ARGS=--sign additionally fetches an addons.mozilla.org-signed .xpi (needs web-ext and AMO
API keys).
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/ja7ad/hydra/main/uninstall.sh | bashTo also delete config, state, and logs:
curl -fsSL https://raw.githubusercontent.com/ja7ad/hydra/main/uninstall.sh | bash -s -- --purgeWindows (PowerShell):
irm https://raw.githubusercontent.com/ja7ad/hydra/main/uninstall.ps1 | iexTo also delete config and state:
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/ja7ad/hydra/main/uninstall.ps1))) -PurgeHomebrew:
# Uninstall CLI
brew uninstall hydra
# Uninstall macOS Desktop App (and zap settings)
brew uninstall --cask --zap hydraThe scripts remove binaries, extensions, manifests, desktop shortcuts, and startup entries. On macOS, they also remove the bundled app and package receipts. Config and state are kept by default (~/.config/hydra on Linux/macOS, %APPDATA%\hydra on Windows); use --purge / -Purge to delete them.
# Retrieve a file with automatic concurrency discovery
hydra https://example.com/archive.tar.gz
# Specify output destination
hydra https://example.com/archive.tar.gz -o output.tar.gz
hyaworks everywherehydradoes. Every install channel — the install scripts, Homebrew, the.deb/.rpm/AUR packages, the macOS.pkgand the Windows installer — puts the CLI on yourPATHunder both names. It is three letters to type, and it is also the name to reach for on a machine that already has THC-Hydra, the login auditor, which ishydratoo. Shell completions are installed for both;hydra install-completions --bin-name hyaadds them by hand.
# Explicit connection count (e.g., 8 connections)
hydra -x 8 https://example.com/largefile.iso
# Fetch across multiple mirror origins serving identical files
hydra https://mirror1.example.org/file.iso https://mirror2.example.org/file.isoA Metalink document supplies the three things a bare URL cannot: every mirror
that holds the object, its exact size, and what it must hash to. HYDRA
reads both dialects — Metalink 3.0 (.metalink, what mirrormanager and most
distribution redirectors emit) and Metalink 4 / RFC 5854 (.meta4) — and needs
no flag to do it:
# A document on disk, whatever it is called: the content is read.
hydra ./Fedora-Workstation.metalink
# A redirector that serves one. Detected from its Content-Type on the probe
# that was going to happen anyway.
hydra "https://mirrors.fedoraproject.org/metalink?repo=fedora-40&arch=x86_64"
# Or name it outright, when a URL reveals nothing about itself.
hydra --metalink https://example.org/big.iso.meta4What that buys, over the same object fetched from one URL:
- Mirrors that can actually be assembled together. Splicing ranges across
hosts is normally gated on every source agreeing about a strong validator —
and independent mirror operators cannot share an
ETag, so that gate keeps exactly one source out of a nineteen-mirror list. A document states the size and a content digest from outside the mirrors, so agreement is established against the document instead. Stronger, and satisfiable. - A reserve bench. Politeness authorises a handful of connections; the rest of the list is held back. When a mirror dies or goes silent mid-transfer, its connections are re-pointed at a reserve in place — the socket count stays what politeness allowed, and no range is stranded.
- Localised repair. Where the document publishes
<pieces>, each chunk is verified as the file lands and a bad one costs a single chunk refetched from a different mirror, not a whole re-download.
Read one without fetching anything, including what HYDRA would do with it:
hydra metalink ./Fedora-Workstation.metalink
hydra metalink --json https://example.org/big.iso.meta4Narrow the choice:
# Prefer mirrors near you; the rest stay as reserves.
hydra --metalink-location de,nl,fr ./mirrors.meta4
# One entry from a document that describes several.
hydra --metalink-file netinst.iso ./mirrors.meta4
# Only entries for one platform, and only one protocol.
hydra --metalink-os linux --metalink-preferred-protocol https \
--metalink-enable-unique-protocol ./mirrors.meta4HTTP(S) mirrors are used first and ftp:// mirrors wait behind them as
fallbacks, whatever the publisher's ranking says — ranges can be spliced and
chunks repaired over HTTP, while FTP streams from a single connection
(--metalink-preferred-protocol ftp restores the old order). Mirrors on schemes
this build cannot fetch (rsync:// and friends) are reported
and skipped rather than attempted; <metaurl> indirections such as BitTorrent
are recorded and not followed; and a <file name> that tries to escape the
output directory is refused outright. A <signature> is reported and not
verified — verify it yourself before trusting the digests it covers.
Servers that implement Metalink over HTTP (RFC 6249) need no document at
all: Link: <...>; rel=duplicate headers on an ordinary download become
reserves, discovered on the probe that already happened.
The desktop app reads the same documents: paste a .meta4/.metalink path or
URL into Add URL and it shows what the list offers — files, sizes, how many
mirrors are usable, whether per-chunk verification is available — before adding
one download per entry. libhydra exposes it too, through
hydra_metalink_parse/_open/_fetch and hydra_job_create_from_metalink.
HYDRA can seamlessly emulate wget or curl flags:
# wget dialect
hydra --compat=wget -c -O myfile.zip https://example.com/file.zip
# curl dialect
hydra --compat=curl -C - -o myfile.zip https://example.com/file.zipThe dialect is also taken from the name the binary is invoked as, so existing
scripts can run unchanged. hydra compat-link installs those entry points:
# Show where the wget/curl links would go, and whether they would be reached
hydra compat-link --dry-run
# Create them next to the hydra binary
hydra compat-link
# Keep the real curl/wget names free
hydra compat-link --name hydra-wget --name hydra-curlA link only takes effect from a directory that is on $PATH before the one
holding the real curl/wget — otherwise the shell keeps resolving the name to
the original tool. compat-link checks that and tells you which binary wins, so
a link that cannot be reached does not look like a silent failure. Existing files
are never replaced without --force.
# Launch interactive terminal UI
hydra interactive
# Add multiple downloads into the queue
hydra interactive https://example.com/file1.iso https://example.com/file2.zip# Check remote advertised checksums without downloading the object
hydra checksum https://example.com/release.tar.gz
# Download with target hash verification
hydra --checksum sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 https://example.com/file.tar.gzMeasured on a Hetzner VPS (Ubuntu 24.04, 2 vCPU), one client process at a time with a
cooldown between runs, every download verified against a reference SHA-256. hydra
rows marked default are a bare hydra <url> with no flags. Everything here is
reproducible with the scripts in scripts/benchmark/.
The origin is nginx serving 1 GB from RAM inside a network namespace on the same host,
with 50 ms of tc netem delay each way: a 100 ms round trip, unlimited bandwidth, and
no other traffic. Four plain curl ranges finish within 10 ms of each other, so the path
is fair and the only variable is the client. Mean of three runs.
| Application | Config | Avg speed | Time to complete | Peak memory | CPU time |
|---|---|---|---|---|---|
| hydra | -x 8 |
414 MB/s | 2.6 s | 6.9 MiB | 1.48 s |
| aria2c | -x 8 |
298 MB/s | 3.6 s | 25.3 MiB | 2.52 s |
| hydra | default |
298 MB/s | 3.6 s | 6.9 MiB | 1.79 s |
| hydra | -x 4 |
294 MB/s | 3.7 s | 6.9 MiB | 1.89 s |
| aria2c | -x 4 |
285 MB/s | 3.8 s | 21.1 MiB | 2.54 s |
| hydra | -x 2 |
184 MB/s | 5.9 s | 6.8 MiB | 2.35 s |
| aria2c | -x 2 |
180 MB/s | 6.0 s | 19.2 MiB | 3.15 s |
| hydra | adaptive |
141 MB/s | 7.6 s | 7.0 MiB | 2.46 s |
| wget | 1 conn |
106 MB/s | 10.1 s | 4.8 MiB | 2.39 s |
| hydra | -x 1 |
105 MB/s | 10.3 s | 6.6 MiB | 2.45 s |
| curl | 1 conn |
104 MB/s | 10.3 s | 10.9 MiB | 3.21 s |
| aria2c | -x 1 |
104 MB/s | 10.4 s | 17.9 MiB | 4.14 s |
At every matched concurrency HYDRA is ahead of aria2c, issues exactly one request per
connection with no repairs, and does it at a third of the memory and two thirds of the
CPU. A bare hydra <url> matches aria2c -x 4 on speed while curl, wget and aria2c
at their own defaults sit at a third of it. wget is the one client that uses less
memory, 4.8 MiB against 6.9.
A bare hydra <url> against aria2c -x 4 and curl, two runs each on the same VPS.
The Hetzner origin caps concurrency per client and refuses the surplus with 429; the
other three reward it.
| Origin | Client | Time | Avg speed | Peak memory | CPU time |
|---|---|---|---|---|---|
| ash-speed.hetzner.com, 1 GB | hydra | 15.3 s | 70.3 MB/s | 8.0 MiB | 3.8 s |
| aria2c -x 4 | 15.7 s | 68.3 MB/s | 20.4 MiB | 5.0 s | |
| curl | 28.2 s | 38.1 MB/s | 13.1 MiB | 4.5 s | |
| speedtest.bitel.io, 1000 MB | hydra | 2.4 s | 432 MB/s | 7.8 MiB | 2.3 s |
| aria2c -x 4 | 5.0 s | 208 MB/s | 21.5 MiB | 5.0 s | |
| curl | 6.4 s | 164 MB/s | 20.2 MiB | 4.5 s | |
| speedtest.bitel.io, 512 MB | hydra | 1.3 s | 413 MB/s | 7.9 MiB | 1.1 s |
| aria2c -x 4 | 2.9 s | 188 MB/s | 21.5 MiB | 2.8 s | |
| curl | 2.9 s | 187 MB/s | 22.9 MiB | 2.5 s | |
| mmatechnical.com, 500 MB | hydra | 1.0 s | 546 MB/s | 7.8 MiB | 0.9 s |
| aria2c -x 4 | 1.9 s | 282 MB/s | 21.9 MiB | 1.6 s | |
| curl | 2.7 s | 196 MB/s | 23.1 MiB | 2.3 s |
The second runs agree with the first to within a few percent on every row except mmatechnical, where the CDN warmed between them (hydra 392 MB/s, aria2c 420 MB/s on the second run).
hydra is the application. libhydra is the engine, and it is a product
in its own right: a stable C ABI over hya-core and hya-net, with its own
version, its own release archives, its own compatibility promise, and a
permissive MIT-or-Apache licence rather than the CLI's GPL. A desktop
application, an Android app, an iOS app, or a program in Go, Swift, Kotlin,
Dart, C# or Python can run the same download engine without taking the CLI or
the GUI with it.
make ffi # libhydra.a, libhydra.so/.dylib, and include/hydra.h
make ffi-compat # the ABI 1 stability gate
make ffi-test # the ABI suite, a C conformance program, and every
# published header against the current library#include "hydra.h"
hydra_engine_config_t cfg;
HYDRA_ENGINE_CONFIG_INIT(&cfg);
cfg.state_path = "hydra-state.json"; /* jobs survive a process restart */
hydra_engine_t *engine = hydra_engine_create(&cfg);
const char *urls[] = { "https://example.com/big.iso" };
hydra_job_config_t job;
HYDRA_JOB_CONFIG_INIT(&job);
job.urls = urls; job.url_count = 1; job.output_path = "big.iso";
hydra_job_id_t id;
hydra_job_create(engine, &job, &id);
hydra_job_start(engine, id);Job identity is a durable uint64_t rather than a pointer, so it survives an
app restart, a UI rebuild or a killed Android service; the event queue is the
asynchronous interface, so it becomes a Go channel, a Kotlin Flow, a Swift
AsyncStream or a Dart Stream; and file bytes never cross the boundary, so
resident memory stays independent of object size.
The ABI is frozen and mechanically enforced. Within ABI 1 no field moves, no enumerator is renumbered and no symbol disappears; CI checks the whole layout against a committed manifest and compiles every header this project has ever published against the library built from the current branch. docs/ffi/ABI.md is the specification — design principles, the stability policy, and what the guarantees actually cover.
Every release publishes a prebuilt archive — static library, shared library,
header, pkg-config metadata and these guides — for Linux (glibc and musl),
macOS, Windows, Android and iOS. Any other target builds from source with
scripts/build-ffi.sh --target <triple>, the same script CI runs.
| The ABI specification | Design principles, the ABI 1 stability policy, ownership, events, enforcement |
| Getting started | The contract, the archive layout, sixty seconds of C |
| Linux | glibc vs musl, pkg-config, CMake, containers, systemd |
| macOS | universal binaries, Xcode, App Sandbox, notarisation |
| Windows | MSVC, the static CRT, hydra.lib vs hydra.dll |
| Android | jniLibs, JNI, CMake, Flow, background execution |
| iOS | Hydra.xcframework, SwiftPM, AsyncStream, app lifecycle |
| Any other platform | building for a triple outside the release matrix |
| Language bindings | Go, Python, C#, Dart, C++, Zig, and writing your own |
See also docs/ffi/ABI.md for the specification,
include/hydra.h for the published declarations, and
examples/ffi-c/download.c for a complete C
client with mirrors, pause and resume.
Contributions are welcome! Please read the Contributing Guide for the project layout, build instructions, pre-submit checks (fmt, clippy, tests), commit conventions, and how licensing applies to each crate. In short:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-featuresBug reports and feature requests go to the issue tracker; security vulnerabilities should be reported privately via GitHub security advisories.
- The
hydraCLI binary is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). - The
hydra-core,hya-netandhya-ffilibraries are dual-licensed under MIT or Apache-2.0 (LICENSE-MIT / LICENSE-APACHE).
For more details, see LICENSING.md and THIRD-PARTY-NOTICES.md.


