-
Notifications
You must be signed in to change notification settings - Fork 0
Frequently Asked Questions
Q: What is qBittorrent Automation?
A: qBittorrent Automation is a Python-based rules engine that automates torrent management tasks through the qBittorrent Web API. It allows you to define YAML-based rules that automatically categorize, tag, pause, resume, delete, and manage torrents based on conditions you specify.
Q: Why not use qBittorrent's built-in RSS automation?
A: qBittorrent's RSS automation only works for adding new torrents based on RSS feeds. This system provides:
- Management of existing torrents based on conditions
- Multiple trigger types (manual, scheduled, webhooks)
- Complex condition logic (AND/OR/NOT groups)
- Access to all torrent fields and metadata
- Idempotent actions that won't repeat unnecessarily
- Dry-run mode for safe testing
Q: Does this work with qBittorrent v4.x?
A: This system is designed for qBittorrent Web API v5.0+ which introduced breaking changes (e.g., pause→stop, resume→start). If you're using qBittorrent v4.x, you'll need to modify the API client to use the old endpoint names.
Q: Is this safe to run on my existing torrents?
A: Yes! The system has several safety features:
-
Dry-run mode (
--dry-run) shows what would happen without making changes - Idempotent actions skip if torrent already in desired state
- File-order execution allows predictable rule evaluation
- Comprehensive logging with trace mode for debugging
- stop_on_match prevents multiple rules from affecting the same torrent
Q: Can I run this on Windows?
A: Yes! The system is Python-based and works on Windows, Linux, and macOS. You'll need Python 3.8+ and the required dependencies (requests, pyyaml).
Q: Where should I put my config files?
A: By default, the system looks for:
-
config/config.yml- Connection and global settings -
config/rules.yml- Your automation rules
You can override these with --config and --rules flags.
Q: How do I use environment variables in config files?
A: Use ${VARIABLE_NAME} syntax:
qbittorrent:
username: ${QB_USERNAME}
password: ${QB_PASSWORD}The system expands these at runtime using os.environ.
Q: Can I have multiple rule files?
A: Currently, the system loads a single rules file. However, you can organize rules within the file using YAML comments and logical grouping:
# ===== Content Organization =====
- name: "Categorize movies"
# ...
# ===== Cleanup =====
- name: "Remove old torrents"
# ...Q: What happens if qBittorrent is unreachable?
A: The system will raise a ConnectionError and exit. For scheduled triggers, ensure you have proper error handling in your cron job or systemd timer.
Q: How do I enable trace logging?
A: Use the --trace flag:
python triggers/manual.py --traceThis logs all API calls, field accesses, and condition evaluations.
Q: How do I know what fields are available?
A: See the Available Fields section (§7) for complete tables. You can also:
- Enable
--tracemode to see all field accesses - Check qBittorrent Web API documentation
- Use
/api/v2/torrents/infoto see raw torrent data
Q: What's the difference between info.size and info.total_size?
A:
-
info.size- Total size of the torrent (all files) -
info.total_size- Same asinfo.size(alias in qBittorrent API)
Both return the same value in bytes.
Q: Why is my files.* condition not working?
A: files.* is a collection field - it returns a list. Operators check if ANY item in the list matches:
# This checks if ANY file name contains "sample"
- field: files.name
operator: contains
value: "sample"If you need to check ALL files, use a none condition with the inverse:
# This ensures NO file is larger than 1GB
conditions:
none:
- field: files.size
operator: ">"
value: 1073741824Q: How do I check if a torrent has NO tags?
A: Check if the tags string is empty:
conditions:
all:
- field: info.tags
operator: "=="
value: ""Q: Can I use regex in conditions?
A: Yes! Use the matches operator:
- field: info.name
operator: matches
value: '(?i).*[Ss]\d{2}[Ee]\d{2}.*' # TV show patternUse (?i) for case-insensitive matching.
Q: How do older_than and newer_than work?
A: These operators compare Unix timestamps against a relative time in seconds:
# Torrents added more than 7 days ago
- field: info.added_on
operator: older_than
value: 604800 # 7 days in seconds
# Torrents completed less than 24 hours ago
- field: info.completion_on
operator: newer_than
value: 86400 # 24 hours in secondsQ: What does info.state return?
A: The current state string, one of:
-
downloading- Actively downloading -
uploading- Actively seeding -
pausedDL- Paused while incomplete -
pausedUP- Paused after completion -
stalledDL- No download progress -
stalledUP- No upload activity -
checkingUP- Checking files after completion -
checkingDL- Checking files while incomplete -
error- Torrent has errors -
missingFiles- Files missing on disk -
forcedUP- Force seeding -
forcedDL- Force downloading
Q: How often do scheduled triggers run?
A: Scheduled triggers use cron expressions. You control the schedule:
# Every hour
schedule: "0 * * * *"
# Every day at 3 AM
schedule: "0 3 * * *"
# Every Monday at 9 AM
schedule: "0 9 * * 1"Then run triggers/scheduled.py in your cron or systemd timer.
Q: Can I test scheduled rules without waiting?
A: Yes! Use manual trigger with dry-run:
python triggers/manual.py --dry-runThis evaluates all enabled rules immediately.
Q: How do webhooks work?
A: Set up qBittorrent to call your webhook server when torrents are added or completed:
- Run the webhook listener:
python triggers/on_added.py --port 8081-
Configure qBittorrent to POST to
http://your-server:8081/webhookwhen torrents are added -
Rules with
trigger: on_addedwill be evaluated for the specific torrent
Q: Can I filter which torrents a trigger processes?
A: Yes! Use the filter section in trigger conditions:
conditions:
trigger: manual
filter:
category: "Movies" # Only process Movies category
state: "downloading" # Only downloading torrents
all:
- field: info.ratio
operator: "<"
value: 1.0Q: What's the difference between manual.py and scheduled.py?
A:
- manual.py - Run on-demand, processes all torrents matching rules (useful for testing or one-time bulk operations)
- scheduled.py - Same as manual but designed to be run by cron/systemd timer at regular intervals
Both use trigger: manual or trigger: scheduled in rules.
Q: Will stop action pause a torrent that's already paused?
A: No - actions are idempotent. The system checks the current state:
if torrent["state"] in ["pausedUP", "pausedDL"]:
logger.info(f"Torrent already stopped, skipping")
returnQ: What's the difference between start and force_start?
A:
- start - Resume normal downloading/seeding (respects queue limits)
- force_start - Force the torrent to start regardless of queue limits (useful for private trackers or low-seeded content)
Q: Does delete_torrent remove files from disk?
A: Only if you specify delete_files: true:
actions:
- type: delete_torrent
params:
delete_files: true # Remove from diskIf false or omitted, only removes from qBittorrent (files stay on disk).
Q: Can I set multiple tags at once?
A: Yes! Use set_tags:
actions:
- type: set_tags
params:
tags: "movies,hd,private"This replaces all existing tags. To add tags while keeping existing ones, use add_tag.
Q: How do I remove all tags?
A: Use set_tags with an empty string:
actions:
- type: set_tags
params:
tags: ""Q: What does limit: -1 mean for upload/download limits?
A: -1 means unlimited (removes any speed limit).
Q: Can I run multiple actions for the same torrent?
A: Yes! Actions execute in order:
actions:
- type: set_category
params:
category: "Movies"
- type: add_tag
params:
tag: "auto-categorized"
- type: stopAll three actions will execute if conditions match.
Q: How many API calls does the system make?
A: The system optimizes API calls through caching:
Per-Trigger API Calls:
- Initial torrent list fetch (1 call)
- Per-torrent metadata fetches (only if fields accessed):
-
trackers.*→/api/v2/torrents/trackers(1 call per torrent) -
files.*→/api/v2/torrents/files(1 call per torrent) -
properties.*→/api/v2/torrents/properties(1 call per torrent) -
peers.*→/api/v2/sync/torrentPeers(1 call per torrent) -
webseeds.*→/api/v2/torrents/webseeds(1 call per torrent)
-
Example: If you have 100 torrents and rules only check info.* fields, that's 1 API call total. If rules also check trackers.url, that's 1 + 100 = 101 calls.
Q: How can I reduce API calls?
A: Optimize your rules:
- Use filters to limit torrents processed:
conditions:
filter:
category: "Movies" # Only fetch Movies category-
Avoid expensive fields if possible:
-
info.*- Free (included in main list) -
trackers.*,files.*,properties.*- Expensive (1 call per torrent)
-
-
Use
stop_on_match: trueto prevent redundant rule evaluation:
- name: "First matching rule"
stop_on_match: trueQ: Can I run this on a system with 10,000+ torrents?
A: Yes, but optimize carefully:
- Use aggressive filtering:
filter:
state: "downloading" # Process only active torrents-
Avoid expensive fields in high-frequency rules
-
Run scheduled triggers less frequently (every 6-12 hours instead of hourly)
-
Consider breaking rules into multiple files run at different intervals
Q: How long does execution take?
A: Depends on:
- Number of torrents
- Number of rules
- Fields accessed
- Network latency to qBittorrent
Typical performance:
- 100 torrents, simple rules (info.* only): < 1 second
- 100 torrents, complex rules (all fields): 5-10 seconds
- 1000 torrents, simple rules: 2-5 seconds
- 1000 torrents, complex rules: 30-60 seconds
Use --trace to see timing breakdowns.
Q: I'm getting 401 Unauthorized errors
A: Check your credentials in config/config.yml:
qbittorrent:
username: "admin"
password: "your_password"Also verify qBittorrent Web UI authentication is enabled.
Q: Rules aren't matching torrents I expect
A: Enable --trace mode to see condition evaluation:
python triggers/manual.py --traceLook for lines like:
[TRACE] Evaluating condition: info.ratio >= 2.0
[TRACE] Result: False (actual value: 1.5)
Q: Getting KeyError when accessing fields
A: Not all fields exist for all torrents. The system handles missing fields gracefully:
# If field doesn't exist, comparison returns FalseCheck that you're using correct field names from the Available Fields table.
Q: schedule trigger isn't running
A: Scheduled triggers don't run automatically - you need to set up cron or systemd timer:
Cron example:
0 * * * * cd /path/to/qbittorrent-automation && python triggers/scheduled.pyQ: Webhook server won't start
A: Check port availability:
# Linux: Check if port 8081 is in use
sudo netstat -tulpn | grep 8081
# Free the port or use a different one
python triggers/on_added.py --port 8082Q: Changes aren't applying to torrents
A: Check:
-
Dry-run mode: Are you using
--dry-run? Remove it to apply changes. - Idempotency: Action may be skipped if torrent already in desired state (check logs)
-
Conditions: Rule may not be matching (use
--trace) - stop_on_match: Earlier rule may have matched first
Q: Can I run this in Docker?
A: Yes! Example Dockerfile:
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
RUN pip install requests pyyaml
# Copy application
COPY lib/ /app/lib/
COPY triggers/ /app/triggers/
COPY config/ /app/config/
# Run scheduled trigger every hour
CMD ["sh", "-c", "while true; do python triggers/scheduled.py; sleep 3600; done"]Q: How do I deploy with systemd?
A: Create a service file and timer:
/etc/systemd/system/qbittorrent-automation.service:
[Unit]
Description=qBittorrent Automation
After=network.target
[Service]
Type=oneshot
WorkingDirectory=/opt/qbittorrent-automation
ExecStart=/usr/bin/python3 triggers/scheduled.py
User=qbittorrent/etc/systemd/system/qbittorrent-automation.timer:
[Unit]
Description=Run qBittorrent Automation hourly
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.targetEnable and start:
sudo systemctl enable qbittorrent-automation.timer
sudo systemctl start qbittorrent-automation.timerQ: Can I run multiple instances?
A: Yes, but ensure they don't conflict:
- Use different rule files:
python triggers/manual.py --rules config/rules-cleanup.yml
python triggers/manual.py --rules config/rules-categorization.yml- Or use different trigger types (manual, scheduled, webhooks) simultaneously
Q: How do I integrate with Sonarr/Radarr?
A: Use the on_added webhook trigger:
- Run webhook server:
python triggers/on_added.py --port 8081-
Configure Sonarr/Radarr to send webhook to your server after adding torrents to qBittorrent
-
Create rules with
trigger: on_addedto auto-categorize/tag based on naming patterns
qbt-rules v0.3.0 | Python-based rules engine for qBittorrent automation
GitHub • PyPI • Issues • Discussions • Contributing • License
Requirements: Python 3.8+ • qBittorrent 5.0+
Made with ❤️ by the qbt-rules community | Licensed under MIT
v0.3.0 | GitHub
- ✅ Unified CLI (
qbt-rules) - ✅ Custom triggers
- ✅ Trigger-agnostic mode
- ✅ Size operators (
50GB)