torram-ng
Recover torrent data by reconstructing files from fully and partially downloaded sources.
Given a .torrent file and one or more directories containing incomplete copies of its
contents, torram-ng identifies which pieces are intact by checking them against the piece
hashes in the torrent, and rebuilds the most complete output it can from what it finds.
If you have two dead torrents of the same release — one 75% done, the other 85% — the pieces you are missing from one may be present in the other. Combined, they can add up to a complete file.
Status: early. This is a modernization of the unmaintained
vbuell/torram. This release makes the project installable, tested and continuously integrated; the recovery engine itself is still the original 0.9.0 code and has known correctness defects. Read Known limitations before trusting it with anything you care about.
Install
uv tool install git+https://github.com/kanya-approve/torram-ng
Or run it once without installing:
uvx --from git+https://github.com/kanya-approve/torram-ng torram-ng --help
Both torram-ng and torram are installed as commands. Python 3.8 or newer.
Usage
torram-ng [-h] [--symlink] [--minsize MINSIZE] [-v] [-o OUTPUT_DIR] [-a]
[-c] [-s] [--fileext FILE_EXT] [--version]
torrentFile root
| Argument | Meaning |
|---|---|
torrentFile |
the .torrent to analyze |
root |
directory to search recursively for candidate files |
-o, --output_dir |
where to write recovered files (required in practice, see limitations) |
--minsize |
smallest file size to consider, in bytes. Defaults to 1 MiB, which silently excludes smaller files — pass --minsize 0 |
-s, --autoskip |
skip prompting when there is only one option; -ss automates further |
-v, --verbose |
repeat for more detail (-vv, -vvv) |
-c, --use_color |
ANSI colour output |
--fileext |
suffix to append to output files, e.g. .!qB for incomplete qBittorrent files |
Example — scan two drives and rebuild into ./recovered:
torram-ng show.torrent /mnt/disk1 -o ./recovered --minsize 0 -ss
After recovery, run a force recheck in your torrent client so it notices the files changed.
How it works
A torrent describes its contents as one continuous byte stream, split into fixed-size pieces.
Each piece has a SHA-1 hash stored in the .torrent. torram-ng walks the search directory,
picks out files whose size matches a file in the torrent, and hashes their pieces to find which
ones are intact. Where several sources each hold different good pieces, it can combine them.
Known limitations
These are inherited from the original implementation and are tracked as issues. The most significant:
- Pieces spanning file boundaries never verify. In a multi-file torrent, a piece that straddles two files is read from only the first one, so it always fails. Even a perfect, complete source reports missing pieces. (#3)
- Files with no attributable piece default to being skipped. A file that fits entirely
inside a piece beginning in an earlier file gets no piece assigned to it, so it is reported
[0 of 0] (Bad)and the suggested action is Skip. Interactively you can override this by choosing a candidate number; under-s/-ssit is dropped without prompting. On a real torrent this is not rare — 7 of the 12 files in Big Buck Bunny are affected. (#3, #11) - The merge path writes pieces at incorrect offsets and never verifies the result, so combining sources can produce a corrupt file that reports success. (#1)
- Scanning several drives can lose candidates, because hardlink de-duplication keys on the inode number without the device. (#6)
--minsizedefaults to 1 MiB, so small-file torrents recover nothing unless you pass--minsize 0. (#14)--symlinkdoes nothing — it is parsed but never implemented. (#17)-a/--autodetect_output_dircannot work; it needs PyQt4, which has no Python 3 build. (#18)- Performance does not scale. The verification loop is roughly
candidates × pieces × files, so large or many-file torrents are impractically slow. (#21) - Only BitTorrent v1 is supported. v2 and hybrid torrents are untested.
A rewrite of the core around a global piece model is planned; it addresses most of the above structurally rather than one at a time.
The tool only ever reads from the directories you point it at, and writes solely to the output directory. It does not modify your sources.
Development
uv sync --all-groups
uv run pytest
uv run ruff check
uv run ruff format --check
Tests generate their own torrents and content deterministically, so nothing large is committed.
Two real torrents are included as parse-only fixtures — see tests/data/README.md.
Known bugs are covered by xfail(strict=True) tests referencing their issue number. They keep
CI green while documenting each defect as executable behaviour; when one is fixed its test
starts failing, which is the signal to remove the marker.
Credits
Originally written by Volodymyr Buell as torram (formerly torrent-upstart). See NOTICE.
License
Apache-2.0. Note that the upstream project was published without a license; see #29.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file torram_ng-2.0.0.tar.gz.
File metadata
- Download URL: torram_ng-2.0.0.tar.gz
- Upload date:
- Size: 12.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ccabe90f2f5e6159c9d876d7ee8ab614e2eeee7939d711c1092261439eae8cb
|
|
| MD5 |
b7a24ca09d3d55196268e94dd15444cb
|
|
| BLAKE2b-256 |
4e61c21faff94ba0e4c9e5983700c8ccb90f11c293236a82f7c0b189fb890592
|
Provenance
The following attestation bundles were made for torram_ng-2.0.0.tar.gz:
Publisher:
release.yml on kanya-approve/torram-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
torram_ng-2.0.0.tar.gz -
Subject digest:
6ccabe90f2f5e6159c9d876d7ee8ab614e2eeee7939d711c1092261439eae8cb - Sigstore transparency entry: 2729374506
- Sigstore integration time:
-
Permalink:
kanya-approve/torram-ng@e4ca8542365769f7f51e1d47f35d487432ec54e9 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/kanya-approve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e4ca8542365769f7f51e1d47f35d487432ec54e9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file torram_ng-2.0.0-py3-none-any.whl.
File metadata
- Download URL: torram_ng-2.0.0-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36bad77f4fb166253c6d64a502b794ed666e14e9331ad2860d2576c579cd0778
|
|
| MD5 |
82f7c257cc06dcfb651ce1f76fab09f7
|
|
| BLAKE2b-256 |
b575106e1eb77197ac8a94de5a415158f5fff571140c6f9cf1f8cc74dc9596d1
|
Provenance
The following attestation bundles were made for torram_ng-2.0.0-py3-none-any.whl:
Publisher:
release.yml on kanya-approve/torram-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
torram_ng-2.0.0-py3-none-any.whl -
Subject digest:
36bad77f4fb166253c6d64a502b794ed666e14e9331ad2860d2576c579cd0778 - Sigstore transparency entry: 2729374896
- Sigstore integration time:
-
Permalink:
kanya-approve/torram-ng@e4ca8542365769f7f51e1d47f35d487432ec54e9 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/kanya-approve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e4ca8542365769f7f51e1d47f35d487432ec54e9 -
Trigger Event:
release
-
Statement type: