A powerful terminal utility to download, sync, and back up your iCloud Drive files — with resume support, differential updates, and parallel transfers.
Apple's iCloud Drive is seamless on Apple devices — until you need to download thousands of files, migrate between accounts, or create local backups. Native tools choke on large directories, stall mid-transfer, and offer no resume capability. iFetch fixes that.
Disabled iCloud Drive? Your files are trapped in the cloud with no easy way to pull them down in bulk.
Switching Apple IDs means losing your Drive structure. No built-in tool to export everything at once.
Large transfers time out, connections drop, and you're left wondering which files actually made it.
Cloud-only is risky. You need an offline, version-controlled archive of your critical documents.
Every feature is designed around one goal: get your data from iCloud to your machine, completely and efficiently.
Configurable worker threads (default 4) for blazing fast concurrent transfers. Saturate your bandwidth.
--max-workers=8
Only changed chunks are fetched. File-level delta sync saves bandwidth and time on re-runs.
--chunk-size=2097152
Checkpointed progress tracking. Connection dropped? Pick up exactly where you left off.
.temp + tracker files
Full support for two-factor and two-step authentication. Credentials stored in your system keyring.
icloud --username=you@me.com
Include/exclude glob patterns. Sync only PDFs, skip archives — personalised sync sets per profile.
--profile pdf_backup
Automatic on-disk archiving of previous file versions. Rollback any file to a prior state.
.versions/ directory
Drop a Python file, subclass BasePlugin, hook into auth, progress, and completion events.
plugins/ auto-discover
Access and download items shared with your account. Browse shared roots with a single flag.
--list-shared
Structured JSON summary of every session — successes, failures, bytes transferred, and changed chunks.
download_report.json
iFetch runs on Python 3.9+ and works on macOS, Linux, and WSL. Follow these steps to get started.
Isolate iFetch's dependencies in a clean virtual environment.
$ python3 -m venv ivenv $ source ivenv/bin/activate
Pull in the Python packages iFetch relies on.
$ pip install pyicloud tqdm requests keyring
Store your Apple ID credentials securely in your system keyring. You'll complete 2FA once.
$ icloud --username=you@icloud.com Enter iCloud password: •••••••• Two-factor authentication required. Enter verification code: 123456 ✓ Authentication successful
Point iFetch at an iCloud Drive path and a local destination. That's it.
$ python ifetch/cli.py Documents/Photos ~/Backups/Photos ====================================================================== iCloud Drive Downloader Remote Path: Documents/Photos Local Path: /Users/you/Backups/Photos Parallel Workers: 4 ====================================================================== Authenticating with iCloud... ✓ Downloading from 'Documents/Photos' to '~/Backups/Photos'
Everything is driven from the terminal. Here's the full reference.
Recursively download any iCloud Drive path to a local directory with parallel workers, retry logic, and differential updates.
# Basic download $ python ifetch/cli.py Documents/Photos ~/Downloads/icloud-photos # Advanced: 8 workers, 5 retries, 2MB chunks, JSON log $ python ifetch/cli.py Documents/Code ~/Work/Code \ --email=you@apple.com \ --max-workers=8 \ --max-retries=5 \ --chunk-size=2097152 \ --log-file=download.log
Preview what's in an iCloud Drive directory without downloading anything.
$ python ifetch/cli.py Documents --list Listing contents of 'Documents': ────────────────────────────────────── 📁 Photos 📁 Programming 📄 resume.pdf 📄 budget.xlsx
Define include/exclude glob patterns in a JSON profile to sync only what you need.
# ~/.ifetch_profiles.json { "pdf_backup": { "include": ["Documents/**/*.pdf"], "exclude": ["Documents/Private/*"] } } $ python ifetch/cli.py Documents ~/PDFs \ --profile pdf_backup \ --email you@apple.com
Drop a Python file in plugins/, subclass BasePlugin, and hook into authentication, download progress, and completion events.
# plugins/notify.py from ifetch.plugin import BasePlugin class Notify(BasePlugin): def after_download(self, remote_item, local_path, success, **kw): if success: print(f"✓ {remote_item.name} → {local_path}")
iFetch auto-discovers all plugins on startup. No configuration needed.