Skip to content

Common Tasks in rTorrent

Michael Brenner edited this page Oct 22, 2019 · 43 revisions

Common Tasks in rTorrent for Dummies

This page is for showing examples on how to use the many options in rTorrent. Only real examples you can apply immediately, no theory at all.

(Source: old trac RTorrentCommonTasks WIKI page.)


Getting the full path of data of a torrent

From 0.9.2, d.base_path attribute can be empty sometimes (e.g. when a download is stopped). The following method always returns the full path of data of a download.

# gets the full path of data of a torrent (it's a workaround for the possibly empty 'd.base_path' attribute)
method.insert = d.data_path, simple, "if=(d.is_multi_file), (cat,(,/), (cat,(,/,("

Saving torrent state and resume data between sessions

# Point to a directory where rTorrent will save the torrent files. You
# may also use relative paths if you want different session
# directories depending on where you execute rtorrent.
session.path.set = ~/Download/session

Watch a directory for torrents

See Watch directories WIKI page for more information.

Create symbolic links to indicate the download state

# Create symlinks in the watch directory with a suffix indicating the download state.
method.set_key =,link1,"d.create_link=tied,,.started"
method.set_key =,link1,"d.delete_link=tied,,.started"
method.set_key =,"d.create_link=tied,,.finished"
method.set_key =,"d.delete_link=tied,,.finished"

# Create symlinks in the same directory as the download.
method.set_key =,link2,"d.create_link=base_path,,.started"
method.set_key =,link2,"d.delete_link=base_path,,.started"
method.set_key =,link2,"d.create_link=base_path,,.finished"
method.set_key =,link2,"d.delete_link=base_path,,.finished"

# Create a symlink in another directory without a suffix.
# You need to quote the command in this case.
method.set_key =,link3,"d.create_link=base_filename,/files,"

Move completed torrents to a fixed location

When the torrent finishes, it executes mkdir ~/Download/<label>; mv <base_path> ~/Download/ and then sets the destination directory to ~/Download/ (using the included d.data_path method).

method.insert = d.get_finished_dir, simple, "cat=~/Download/,$d.custom1="
method.insert = d.data_path, simple, "if=(d.is_multi_file), (cat,(,/), (cat,(,/,("
method.insert = d.move_to_complete, simple, "$argument.1=; execute=mkdir,-p,$argument.1=; execute=mv,-u,$argument.0=,$argument.1=; d.save_full_session="
method.set_key =,move_complete,"d.move_to_complete=$d.data_path=,$d.get_finished_dir="

If you need to move torrent data across disks/partitions on completion then you may find this version (mkdir ~/Download/<label>; cp -rp <base_path> ~/Download/; rm -rf <base_path>) helpful to avoid hash check failures

method.insert = d.get_finished_dir, simple, "cat=~/Download/,$d.custom1="
method.insert = d.get_data_full_path, simple, "branch=((d.is_multi_file)),((cat,(,((cat,(,/,("
method.insert = d.move_to_complete, simple, "execute=mkdir,-p,$argument.1=; execute=cp,-rp,$argument.0=,$argument.1=; d.stop=;$argument.1=; d.start=;d.save_full_session=; execute=rm, -r, $argument.0="
method.set_key =,move_complete,"d.move_to_complete=$d.get_data_full_path=,$d.get_finished_dir="

Move completed torrents to a dynamic location

The script allows you to perform very versatile completion moving, based on logic defined in a bash script, like in this example:

month=$(date +'%Y-%m')

test -n "$target" || case $(tr A-Z' ' a-z_ <<<"$label") in
    tv)                     target="tv" ;;
    movie*)                 target="movies/$month" ;;

See Versatile Move on Completion for all the details, including how to install this.

Move completed torrents to different directory depending on watch directory

Each watch directory adds torrents with the final destination stored in the custom1 string of the download. You can check this string with ^x then print=$d.custom1= in the client (using the above defined d.data_path method).

schedule2 = watch_directory_1,10,10,"load.start=~/Download/watch_stuff1/*.torrent,d.custom1.set=~/Download/stuff1/"
schedule2 = watch_directory_2,10,10,"load.start=~/Download/watch_stuff2/*.torrent,d.custom1.set=~/Download/stuff2/"

method.insert = d.data_path, simple, "if=(d.is_multi_file), (cat,(,/), (cat,(,/,("
method.insert = d.move_to_complete, simple, "$argument.1=; execute=mkdir,-p,$argument.1=; execute=mv,-u,$argument.0=,$argument.1=; d.save_full_session="
method.set_key =,move_complete,"d.move_to_complete=$d.data_path=,$d.custom1="

Delayed Completion Handling

Delayed Completion Handling (click for details) shows how to add a new trigger that works like the normal finished event, but only fires after a customizable delay.

One use-case for such a thing is to move a download from fast storage (RAM disk, SSD) to slow storage (HDD) for permanent seeding, after the initial rush in a swarm is over.

Move .torrent file after loading it manually

Do NOT use this if in combination with a watch folder! (At least in this way.)

When loading a torrent manually (i.e. load.start), moves the original XXX.torrent file to a directory (for example you may want to move the file to the trash bin, since rtorrent made a copy of it in the session directory).

method.set_key =,move_tor,"execute=mv,-u,$d.loaded_file=,/path/to/trash_bin"

Send email for completed downloads

Assuming you have a working mail system and this '' script is executable.

echo "$(date) : $1 - Download completed." | mail -s "[rtorrent] - Download completed : $1"
# First and only argument to '' is completed file's name ('')
method.set_key =,notify_me,"execute=~/,$"

Stop torrents after reaching a specified upload ratio

See Ratio Handling WIKI page for more information.

Delete data files when removing incomplete downloads

If you often add older torrents and find that they never complete due to lack of seeds, these commands will automatically delete the data files when removing an incomplete download (either manually or with remove_untied by removing the tied file) (using the above defined d.data_path method). Note that all files will be removed on incomplete or partially complete downloads, even those files from it which are in fact completely downloaded.

WARNING: Do NOT use this setup if you ever change a download's base_path to something like /home/bob/ or similar, or you could lose a lot of files!

# Enable removal for all downloads added from this watch directory.
schedule2 = watch_directory,10,10,"load.start=~/Download/watch_stuff/*.torrent,d.custom2.set=1"

# Clear 'custom2' when download completes.
method.set_key =,set_done_var,d.custom2.set=

# gets the full path of data of a torrent (it's a workaround for the possibly empty 'd.base_path' attribute)
method.insert = d.data_path, simple, "if=(d.is_multi_file), (cat,(,/), (cat,(,/,("
# Erase data files when a download is removed that still has 'custom2' set.
method.set_key =,rm_files,"branch=d.custom2=,\"execute={rm,-rf,--,$d.data_path=}\""

To make an incomplete download exempt from the automated deletion on removal, select the download then press Ctrl-X and enter d.custom2.set=.

Scheduling download rate

Every day "throttle_1" gets triggered at 01:00 and sets the download rate to unlimited, while "throttle_2" sets it to 2500kb at 05:00. Using this the client may be made to perform a somewhat crude form of bandwidth scheduling.

schedule2 = throttle_1,01:00:00,24:00:00,throttle.global_down.max_rate.set_kb=0
schedule2 = throttle_2,05:00:00,24:00:00,throttle.global_down.max_rate.set_kb=2500

Using custom throttles

You can define different throttle rates for (groups of) downloads or IP ranges. These throttles borrow bandwidth from the global throttle and thus are limited by it too.


The "slowupload" throttle limits the upload to 100 kb/s. The "slowdownload" throttle limits download to 5000 kb/s. The "sloweverything" throttle limits both.

You can assign throttles to a stopped download with ^T. The NULL throttle is a special unlimited throttle that bypasses the global throttle.

Using a different configuration file

$ rtorrent -n -o import=~/foo.rc

The -n switch tells rtorrent not to load the default resource file, while the import option loads ~/foo.rc.

Using custom views

Show items either currently uploading or downloading in active view. Update every 30 seconds.

schedule2 = filter_active,30,30,"view.filter = active,\"or={d.up.rate=,d.down.rate=}\""

Show items currently downloading in active view. Update every 30 seconds.

schedule2 = filter_active,30,30,"view.filter = active,d.down.rate="

Show items currently uploading in active view. Update every 30 seconds.

schedule2 = filter_active,30,30,"view.filter = active,d.up.rate="

Switch to a custom view with

ui.current_view.set = viewname

Setting bind address

Using the -b <ip> flag or bind = <ip> option, you may change the IP address the listening socket and outgoing connections is bound to.

The following can be used to set an interface with IPv4 address (e.g. eth0) to bind to. (Requires ip command that is part of iproute2 package.)

# Set an interface with IPv4 address to bind to: [eth0|tun0]
method.insert = cfg.interface.bind, string|const|private, (cat,"eth0")
# Get IPv4 address of a given interface
method.insert = get_interface_ipv4_address, simple|private, \
    "execute.capture=bash,-c,\"$cat=\\\"echo -n \$(ip -o -4 addr show \\\",$argument.0=,\\\" | grep -Po 'inet \\\\\\\\\\K[\\\\\\\\\\d.]+')\\\"\""
# The IP address the listening socket and outgoing connections is bound to. (bind)
schedule2 = set_bind_address, 0, 0, \
    "branch=((cfg.interface.bind)), \

Setting the local IP

Using the -i <ip> flag or ip = <ip> option, you may change your IP address that is reported to the tracker.

If you have a dynamic IP address then the following can be used to update the IP address every 30 minutes without the need of having dynamic DNS service. (Requires dig command that is part of dnsutils package.)

# Get public IP address without the need of having dynamic DNS service, also works from behind NAT, through tunnel
method.insert = get_public_ip_address, simple|private, "execute.capture=bash,-c,\"eval echo -n \$(dig -4 TXT +short\""
# The IP address reported to the tracker. (ip) This handles dynamic IP's as well.
schedule2 = ip_tick, 0, 1800, "network.local_address.set=(get_public_ip_address)"

The client may spend as much as 60 seconds trying to contact a UDP tracker, so if you are behind a firewall that blocks the reply packets you should tell the client to skip the UDP tracker. Set use_udp_trackers = no in your configuration file or in the command line option.

Start or stop all torrents

On the "main" view ^x + d.multicall2=,d.start=.

Replace d.start= with d.stop= to stop all torrents .

In case you need to stop all torrents but can't start rTorrent to run the above command, you can edit the sessions files with the following command, inside the session dir, which you of course have set up.

sed -i 's/5:statei1e/5:statei0e/' *.torrent.rtorrent

Stop downloading of a torrent but still uploading it

Set the priority of all unfinished files (or all the files) of a torrent to off, either manually (you still have to run the last command) or by running these commands in rtorrent with ^x after selecting a torrent:


Favoring one group of torrents over the rest of them

See Favoring group of torrents WIKI page for more information.


See Auto-Scraping WIKI page for more information.

Adding fast resume data to torrent files

When you are the first seeder for a torrent or you already have the data from somewhere else, rTorrent will normally have to hash-check all files even if you just created the torrent file from them and thus know that they are correct. To eliminate this step, the following Perl script by Josef Drexler can add rTorrent's fast resume data to the torrent file:


$ [base-directory] plain.torrent [with_fast_resume.torrent]

Then you can distribute the original torrent file and load the modified file into rTorrent and start seeding without needing a hash check. The base directory specifies where the files in the torrent are located, equivalent to the "directory" option in rtorrent.rc. If not specified, the files are assumed to be in the current directory.

Note that this script requires the Convert::Bencode_XS module from CPAN, if this module is not available on your system you will need to install it first:

$ perl -MCPAN -e 'install Convert::Bencode_XS'

If you're having trouble installing it on newer perl versions then take a look at the first comment of this issue.

Supporting public torrents (magnet links, UDP trackers, DHT)

All you need to have these settings in the config to be able to handle public torrents - including magnet links, UDP trackers and DHT:

  • change the 2 port settings to your liking
    • TCP/UDP port for tracker communication: DHT requires open/forwarded port(s) to work with this/these port(s)!
    • UDP port for DHT (DHT does not require open/forwarded port to work with this port)
  • don't forget to open / port forward the required ports / protocols in your firewall
  • magnet links doesn't work due to a bug if only encrypted connection is set! (e.g. protocol.encryption.set = require,require_RC4)
  • session directory must be defined for DHT to work !
  • it's strongly advised to use local DNS cache
# Port range to use for listening. (port_range)
network.port_range.set = 62820-62820

# Enable/disable peer exchange for torrents that aren't marked private. Disabled by default. (peer_exchange)
protocol.pex.set = 1

# Set whether the client should try to connect to UDP trackers (It can cause various problems if it's enabled, if you experience any with this option enabled then disable it.)
trackers.use_udp.set = 1

# Enable DHT support for trackerless torrents or when all trackers are down. 
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
# "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
# The default is "off".
# For DHT to work, a session directory must be defined.
dht.mode.set = auto

# UDP port to use for DHT
dht.port.set = 62882

# Adding public DHT servers for easy bootstrapping
schedule2 = dht_node_1, 5, 0, ""
schedule2 = dht_node_2, 5, 0, ""
schedule2 = dht_node_3, 5, 0, ""
schedule2 = dht_node_4, 5, 0, ""

Starting rTorrent on System Startup


Assuming a Debian-based distribution, create /etc/init.d/rtorrent with one of the rtorrentInit files (rtorrentInitTmux.bash , , rtorrentInitScreen.bash), editing the Configuration to suit your needs.

Make sure it has appropriate permissions and update your init system (as sudo/su/root):

# chown root:root /etc/init.d/rtorrent
# chmod 755 /etc/init.d/rtorrent
# update-rc.d rtorrent defaults


Assuming a Gentoo distribution, and having the daemon USE flag enabled ; select the user you want rtorrent to be runned as modifying /etc/conf.d/rtorrentd, and update your init system (as sudo/su/root):

# rc-update add rtorrentd default

Ubuntu 16.04 (with systemd)

Older systems will use the service command with screen to utilise a startup file, typically located in (or symlinked to) /etc/init.d/ however the new systemctl command requires a different format.

Make sure you have tmux installed (tmux instead of screen):

$ sudo apt-get update; sudo apt-get install tmux

Create the following file (with sudo/root permission at this location:) /etc/systemd/system/rtorrent.service

Description=rtorrent (in tmux)

ExecStart=/usr/bin/tmux -2 new-session -d -s rtorrent rtorrent
ExecStop=/usr/bin/tmux kill-session -t rtorrent


After that, you will need to then enable and start the service:

$ sudo systemctl enable rtorrent.service
$ sudo systemctl start rtorrent.service

You could also directly attach rtorrent to a tty using this service file instead:

Description=rtorrent daemon

ExecStart=/usr/bin/socat PTY,link=%t/rtorrent/tty EXEC:/usr/bin/rtorrent,pty,nofork


You can attach screen to this pty using:

screen /run/rtorrent/tty

Use CTRL + a d to detach.

Clone this wiki locally