Skip to main content

A robust, typed Python wrapper for the rclone CLI.

Project description

Rclone for Python

🚀 A robust, typed Python wrapper for rclone.

Supported Python versions

It shells out to the rclone binary the safe way — every command is built as an argument list and run without a shell, so paths and remote specs are never re-interpreted. Common subcommands have explicit, typed methods that return structured results; anything else is one run() call away.

Highlights

  • 🔒 No shell, no injection. Arguments are passed as a list — never a shell string.
  • 🧱 Zero required dependencies. Pure standard library. tqdm is optional, only for progress bars.
  • 🧩 Typed API + structured results. lsjsonlist[dict], sizeSizeResult, transfers → RcloneResult.
  • 📊 Reliable progress. Driven by rclone's own JSON stats log (works for remote destinations too), not by guessing file sizes.
  • 💥 Real errors. Non-zero exits raise RcloneCommandError carrying the exit code, its meaning, and captured output.

Requirements

Installation

pip install rclone                # core, no third-party dependencies
pip install "rclone[progress]"    # adds tqdm for progress bars

Quick start

from rclone import Rclone

rc = Rclone()                     # finds rclone on PATH

rc.copy("foo.txt", "remote:/path/to/dst")
rc.ls("remote:/path/to/dir")      # ['foo.bin', 'bar.txt', 'foo/']
rc.size("remote:/path/to/dir")    # SizeResult(count=5, bytes=170397, sizeless=0)

The legacy import path still works: from rclone.rclone import Rclone.

Examples

Transfers with progress

# A tqdm progress bar (requires the `progress` extra):
rc.copy("bigfile.bin", "remote:/backup", progress=True)

# Or your own callback, called on every stats tick:
def on_progress(stats):
    print(f"{stats.percentage}%  {stats.bytes}/{stats.total_bytes}  {stats.speed:.0f} B/s")

result = rc.move("data/", "remote:/archive", progress=on_progress)
print(result.success, result.stats.bytes)

Listing and info

rc.ls("remote:/dir")              # ['bar.txt', 'foo/']  (names only)

rc.lsjson("remote:/dir")          # [{'Path': 'bar.txt', 'Name': 'bar.txt', 'Size': 0, 'IsDir': False}, ...]

# lsd (directories) and lsl (files) return structured Entry objects:
rc.lsd("remote:/dir")             # [Entry(name='sub', size=128, mod_time=datetime(...), is_dir=True, count=-1), ...]
rc.lsl("remote:/dir")             # [Entry(name='bar.txt', size=11, mod_time=datetime(...), is_dir=False), ...]

for entry in rc.lsd("remote:/dir"):
    print(entry.name, entry.size, entry.mod_time)

size = rc.size("remote:/dir")
size.count, size.bytes            # also: size.total_objects, size.total_size (legacy aliases)

rc.about("remote:")               # {'total': ..., 'used': ..., 'free': ...}
rc.md5sum("remote:/dir")          # {'bar.txt': 'd41d8cd9...'}
rc.listremotes()                  # ['gdrive:', 's3:']
rc.version()                      # 'v1.74.3'

Extra flags

Pass any rclone flags as positional arguments to any method:

rc.ls("remote:/dir", "-R", "--max-depth", "2")
rc.copy("src/", "remote:/dst", "--transfers", "8", "--exclude", "*.tmp")

Content helpers

text = rc.cat("remote:/notes.txt")
rc.rcat("remote:/notes.txt", "written from python")   # reads from stdin

The escape hatch

Anything without a dedicated method is reachable via run() (returns an RcloneResult) — arguments are still passed safely as a list:

result = rc.run("dedupe", "remote:/dir", "--dedupe-mode", "newest")
print(result.returncode, result.stdout)

Configuration

rc = Rclone(
    binary="/usr/local/bin/rclone",   # explicit path (else $RCLONE_BINARY, else PATH)
    config="~/my-rclone.conf",        # passed as --config
    flags=["--fast-list"],            # global flags applied to every command
    debug=True,                       # log each command on the "rclone" logger
    timeout=600,                      # seconds, for non-streaming commands
)

Error handling

from rclone import Rclone, RcloneCommandError

rc = Rclone()
try:
    rc.copy("missing:", "remote:/dst")
except RcloneCommandError as exc:
    print(exc.returncode)   # e.g. 3
    print(exc.stderr)       # rclone's error output

# Or opt out of raising and inspect the result instead:
result = rc.check("a/", "b/")          # check() does not raise on differences
if not result.success:
    print("directories differ")

Migrating to 2.0

  • lsd() and lsl() now return a list[Entry] (structured: name, size, mod_time, is_dir, count, raw) instead of a list[str] of raw rclone lines. Use [e.name for e in rc.lsd(path)] for just names, or ls() which already returns names.

Migrating from 0.4.x

  • Import is now from rclone import Rclone (the old from rclone.rclone import Rclone still works).
  • The unit= constructor argument is gone; the progress bar auto-scales units (B/KB/MB/GB).
  • Progress is opt-in per call via progress=True (bar) or progress=<callable> (callback) instead of being on by default.
  • Listing/size now return structured types (list, SizeResult) and errors raise RcloneCommandError.
  • delete() works normally — the old artificial block is gone (the unsafe dynamic dispatch that motivated it was removed).
  • execute("...") is still available; new code should prefer run(...).

License

MIT

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

rclone-2.0.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

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

rclone-2.0.0-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file rclone-2.0.0.tar.gz.

File metadata

  • Download URL: rclone-2.0.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.13.13 Darwin/25.5.0

File hashes

Hashes for rclone-2.0.0.tar.gz
Algorithm Hash digest
SHA256 145698f95759af6efe915e72a8927c6f734cf9b4a5f5252c3771891b8f0098f5
MD5 cd232701091a7ab5682b2734f036f2a7
BLAKE2b-256 c44fe6d5dd6d518c5155ee0d75cf4e284f9e90204953ac32047a7f505c29b72c

See more details on using hashes here.

File details

Details for the file rclone-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: rclone-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.13.13 Darwin/25.5.0

File hashes

Hashes for rclone-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 031606b643789a61743dc9eb4ad5c686f668453e04683c76bc4ecf3af7bd46e9
MD5 761eb29a6bf3d0f300ce66d161ab1aad
BLAKE2b-256 a32054cfd1fdd98b759e38ef5dd2ecb5dc3c6bc5ab5c0920ff3f58b0c81524e6

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