Skip to main content

Detect files on disk not tracked by any qBittorrent torrent

Project description

qbittorrent-orphaned banner

PyPI version License: GPL-3.0 Python 3.8+ requests


qbittorrent-orphaned is a lightweight utility that identifies orphaned files -- files that exist on disk but are not tracked by any torrent in your qBittorrent instance. It connects to the qBittorrent Web API v2, walks the directories you configure, cross-references every file against every torrent, and reports what does not belong.

What Are Orphaned Files?

When you remove a torrent from qBittorrent but keep the data on disk, or when external tools (transcoders, renaming scripts, etc.) create files that were never part of a torrent, those files become orphans. They consume storage without being seeded or managed. This tool finds them so you can decide what to keep and what to reclaim.

Features

  • Single-file, pure Python -- no build step, no complex dependencies, just requests.
  • Web API v2 -- authenticates and queries qBittorrent over HTTP; works locally or across a network.
  • Case-insensitive matching -- handles mixed-case filenames on Windows and Linux alike.
  • Category-aware grouping -- results are organized by qBittorrent category, with uncategorized torrents collected under __UNCATEGORIZED__.
  • Human-readable sizes -- every orphan is printed alongside its size in KiB, MiB, GiB, etc.
  • Configurable metadata ignore list -- common metadata files (.nfo, .jpg, .png, .srt, .sub, .idx, .txt, .bin, .svg) are skipped by default. You can extend this list.
  • Exclude patterns -- filter out known non-torrent files (e.g., transcoded 720p copies) by substring match.
  • macOS-safe -- automatically skips ._ resource fork files.

Quick Start

Install from PyPI

pip install qbittorrent-orphaned

Standalone

QBIT_HOST=http://localhost:8080 \
QBIT_USER=admin \
QBIT_PASS=yourpassword \
CATEGORY_FOLDERS="Films=/mnt/media/films;Shows=/mnt/media/shows" \
qbittorrent-orphaned

You can also run the script directly without installing:

pip install requests

QBIT_HOST=http://localhost:8080 \
QBIT_USER=admin \
QBIT_PASS=yourpassword \
CATEGORY_FOLDERS="Films=/mnt/media/films;Shows=/mnt/media/shows" \
python orphan_detector.py

Docker

There is no pre-built image yet, but you can run it easily with a one-liner:

docker run --rm \
  -e QBIT_HOST=http://qbittorrent:8080 \
  -e QBIT_USER=admin \
  -e QBIT_PASS=yourpassword \
  -e CATEGORY_FOLDERS="Films=/media/films;Shows=/media/shows" \
  -v /mnt/media:/media:ro \
  --network=host \
  python:3-alpine sh -c "pip install --quiet requests && python /app/orphan_detector.py"

Mount the script into the container if you prefer a cleaner approach:

docker run --rm \
  -v "$(pwd)/orphan_detector.py:/app/orphan_detector.py:ro" \
  -v /mnt/media:/media:ro \
  -e QBIT_HOST=http://qbittorrent:8080 \
  -e QBIT_USER=admin \
  -e QBIT_PASS=yourpassword \
  -e CATEGORY_FOLDERS="Films=/media/films;Shows=/media/shows" \
  python:3-alpine sh -c "pip install --quiet requests && python /app/orphan_detector.py"

Tip: If qBittorrent runs in its own container, make sure both containers share a Docker network (or use --network=host) so the hostname resolves.

Configuration

All configuration is done through environment variables.

Variable Default Description
QBIT_HOST http://qbittorrent:8080 qBittorrent Web UI URL
QBIT_USER admin Username for Web UI authentication
QBIT_PASS password Password for Web UI authentication
CATEGORY_FOLDERS Films=W:\Films;Shows=X:\Series Semicolon-separated Category=Path pairs. Categories must match those configured in qBittorrent.
EXCLUDE_PATTERNS (empty) Comma-separated substrings. Any file whose relative path contains one of these patterns (case-insensitive) is skipped.
IGNORE_SUFFIXES (empty) Comma-separated file extensions to ignore in addition to the built-in list. Leading dots are optional (e.g., ass,ssa or .ass,.ssa).

Category Folders Format

CATEGORY_NAME=ABSOLUTE_PATH;CATEGORY_NAME2=ABSOLUTE_PATH2

Each category name must match exactly what is configured in qBittorrent. Torrents with no category are grouped under the key __UNCATEGORIZED__.

Example Output

===== Films =====
/mnt/media/films/Some.Movie.2023/Some.Movie.2023.mkv    (4,215 MiB)
/mnt/media/films/Old.Film.1999/Old.Film.1999.avi        (702 MiB)

===== Shows =====
/mnt/media/shows/Series.Name.S01/Episode.05.mkv          (1,102 MiB)

When no orphans are found the output is simply:

No orphaned files found.

How It Works

  1. Authenticate -- the script logs in to qBittorrent via /api/v2/auth/login and obtains a session cookie.
  2. Fetch torrents -- it retrieves the full torrent list from /api/v2/torrents/info, then for each torrent calls /api/v2/torrents/files to get every file path the torrent manages.
  3. Index by category -- all torrent file paths are normalized (forward slashes, lowercase) and grouped into a lookup set per category.
  4. Walk the filesystem -- for each configured category folder, the script recursively enumerates files, skipping ignored suffixes, macOS resource forks, and exclude-pattern matches.
  5. Cross-reference -- every disk file is checked against the corresponding category set. Files not present in any torrent are reported as orphans with their absolute path and human-readable size.

License

GPL-3.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qbittorrent_orphaned-1.0.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qbittorrent_orphaned-1.0.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file qbittorrent_orphaned-1.0.0.tar.gz.

File metadata

  • Download URL: qbittorrent_orphaned-1.0.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for qbittorrent_orphaned-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5d66ca7e10347d0425bcef1cca426d37507f0cc6f98b21af4f3d8f3be008f9a4
MD5 4c3a25f814228ced749464195692c279
BLAKE2b-256 1c73dea0b21d5ea80fa4125e70b9832183d65318049a4384400f80b910d0944b

See more details on using hashes here.

File details

Details for the file qbittorrent_orphaned-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for qbittorrent_orphaned-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 03f03d2c1a2bae915f64abcf1c60354415a438baef2d4805927c6d36217c5bb8
MD5 7929dbbe0a51d631734a0ba76073199a
BLAKE2b-256 aa9e588cde538091282efe492af7ebb589e683701e85d66cdaebceb6c902d81d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page