Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.
Latest commit message
Commit time
January 27, 2023 18:15
March 9, 2023 17:50
July 30, 2018 17:20
February 9, 2023 22:09
February 17, 2023 17:29
August 1, 2018 19:24
March 10, 2023 07:34
December 2, 2020 22:30
February 24, 2023 15:41
March 10, 2023 07:34
August 1, 2018 20:27
March 10, 2023 07:34
February 24, 2023 15:41
January 18, 2023 16:26
February 9, 2023 22:09
February 9, 2023 22:09
March 10, 2023 07:34

iCloud Photos Downloader Quality Checks Multi Platform Docker Build MIT License

  • A command-line tool to download all your iCloud photos.
  • Works on Linux, Windows, and MacOS.
  • Run as executable, docker container, or from the source
  • Run one time or continuously watch for changes to keep a local backup of your photos and videos.

This tool is developed and maintained by volunteers (we are always looking for help...). We aim to release new versions once a week (Friday), if there is something worth delivering.


There are three ways to run icloudpd:

  1. Download executable for your platform from the Github Release and run it
  2. Use Docker to download and run the tool (requires Docker installed, e.g. Docker Desktop
  3. Run from the source (requires Python and pip installed)

Download with Docker

Docker automatically pulls images from the remote repository if necessary. To download explicitely, e.g. to force version update, use:

docker pull icloudpd/icloudpd:1.12.0

Running from the source

icloudpd is a Python package that can be installed using pip:

pip install icloudpd

If you need to install Python, see the Appendix section for instructions.

Experimental Mode

Some changes are added to the experimental mode before they graduate into the main package. Details


Usage: icloudpd <options>

  Download all iCloud photos to a local directory

  -d, --directory <directory>     Local directory that should be used for
  -u, --username <username>       Your iCloud username or email address
  -p, --password <password>       Your iCloud password (default: use PyiCloud
                                  keyring or prompt for password)
  --cookie-directory </cookie/directory>
                                  Directory to store cookies for
                                  authentication (default: ~/.pyicloud)
  --size [original|medium|thumb]  Image size to download (default: original)
  --live-photo-size [original|medium|thumb]
                                  Live Photo video size to download (default:
  --recent INTEGER_RANGE          Number of recent photos to download
                                  (default: download all photos)
  --until-found INTEGER_RANGE     Download most recently added photos until we
                                  find x number of previously downloaded
                                  consecutive photos (default: download all
  -a, --album <album>             Album to download (default: All Photos)
  -l, --list-albums               Lists the available albums
  --skip-videos                   Don't download any videos (default: Download
                                  all photos and videos)
  --skip-live-photos              Don't download any live photos (default:
                                  Download live photos)
  --force-size                    Only download the requested size (default:
                                  download original if size is not available)
  --auto-delete                   Scans the "Recently Deleted" folder and
                                  deletes any files found in there. (If you
                                  restore the photo in iCloud, it will be
                                  downloaded again.)
  --only-print-filenames          Only prints the filenames of all files that
                                  will be downloaded (not including files that
                                  are already downloaded.)(Does not download
                                  or delete any files.)
  --folder-structure <folder_structure>
                                  Folder structure (default: {:%Y/%m/%d}). If
                                  set to 'none' all photos will just be placed
                                  into the download directory
  --set-exif-datetime             Write the DateTimeOriginal exif tag from
                                  file creation date, if it doesn't exist.
  --smtp-username <smtp_username>
                                  Your SMTP username, for sending email
                                  notifications when two-step authentication
  --smtp-password <smtp_password>
                                  Your SMTP password, for sending email
                                  notifications when two-step authentication
  --smtp-host <smtp_host>         Your SMTP server host. Defaults to:
  --smtp-port <smtp_port>         Your SMTP server port. Default: 587 (Gmail)
  --smtp-no-tls                   Pass this flag to disable TLS for SMTP (TLS
                                  is required for Gmail)
  --notification-email <notification_email>
                                  Email address where you would like to
                                  receive email notifications. Default: SMTP
  --notification-email-from <notification_email_from>
                                  Email address from which you would like to
                                  receive email notifications. Default: SMTP
                                  username or notification-email
  --notification-script PATH      Runs an external script when two factor
                                  authentication expires. (path required:
  --log-level [debug|info|error]  Log level (default: debug)
  --no-progress-bar               Disables the one-line progress bar and
                                  prints log messages on separate lines
                                  (Progress bar is disabled by default if
                                  there is no tty attached)
  --threads-num INTEGER_RANGE     Number of cpu threads -- deprecated. To be
                                  removed in future version
  --delete-after-download         Delete the photo/video after download it.
                                  The deleted items will be appear in the
                                  "Recently Deleted". Therefore, should not
                                  combine with --auto-delete option.
  --domain [com|cn]               What iCloud root domain to use. Use 'cn' for
                                  mainland China (default: 'com')
  --watch-with-interval INTEGER RANGE
                                  Run downloading in a infinite cycle, waiting
                                  specified seconds between runs  [x>=1]                                  
  --version                       Show the version and exit.
  -h, --help                      Show this message and exit.


icloudpd --directory ./Photos \
--username \
--password pass1234 \
--recent 500 \


If your Apple account has two-factor authentication enabled, you will be prompted for a code when you run the script.

Two-factor authentication will expire after an interval set by Apple, at which point you will have to re-authenticate. This interval is currently two months.

Authentication cookies will be stored in a temp directory (/tmp/pyicloud on Linux, or /var/tmp/... on macOS.) This directory can be configured with the --cookie-directory option.

You can receive an email notification when two-factor authentication expires by passing the --smtp-username and --smtp-password options. Emails will be sent to --smtp-username by default, or you can send to a different email address with --notification-email.

If you want to send notification emails using your Gmail account, and you have enabled two-factor authentication, you will need to generate an App Password at

System Keyring

You can store your password in the system keyring using the icloud command-line tool:

$ icloud --username
ICloud Password for
Save password in keyring? (y/N)

If you have stored a password in the keyring, you will not be required to provide a password when running the script.

If you would like to delete a password stored in your system keyring, you can clear a stored password using the --delete-from-keyring command-line option:

icloud --username --delete-from-keyring

Error on first run

When you run the script for the first time, you might see an error message like this:

Bad Request (400)

This error often happens because your account hasn't used the iCloud API before, so Apple's servers need to prepare some information about your photos. This process can take around 5-10 minutes, so please wait a few minutes and try again.

If you are still seeing this message after 30 minutes, then please open an issue on GitHub and post the script output.

Watching iCloud for changes

Most used scenario is to run icloudpd to periodically download new photots from iCloud. This can be achieved with parameter or external cron task.

If you provide SMTP credentials, the script will send an email notification whenever two-step authentication expires.

With --watch-with-interval parameter

You can use --watch-with-interval parameter to keep icloudpd watching for iCloud changes. icloudpd will indefinately repeat downloading instructions with specified pause between them, except for authentication, which is performed only once.

With Cron task

Alternatively, you can run icloudpd using cron on platforms that support it:

  • copy the example cron script from source tree, e.g. cp

  • Update with your username, password, and other options

  • Edit your "crontab" with crontab -e, then add the following line:

0 */6 * * * /path/to/

Now the script will run every 6 hours to download any new photos and videos.

cron tries to authenticate on each run


This script is available in a Docker image: docker pull icloudpd/icloudpd:1.12.0

Usage (Downloads all photos to ./Photos):

docker run -it --rm --name icloudpd \
    -v $(pwd)/Photos:/data \
    -v $(pwd)/cookies:/cookies \
    -e TZ=America/Los_Angeles \
    icloudpd/icloudpd:latest \
    icloudpd --directory /data \
    --cookie-directory /cookies \
    --folder-structure {:%Y/%Y-%m-%d} \
    --username \
    --password pass1234 \
    --size original \
    --recent 500 \

On Windows:

  • use %cd% instead of $(pwd)
  • or full path, e.g. -v c:/photos/icloud:/data

Building image locally from the source tree:

docker build . -t icloudpd:dev
docker run -it --rm icloudpd:dev icloudpd --version


Install Python & pip

Note that icloudpd works with python 3.7+.



  • Install Homebrew (if not already installed):
which brew > /dev/null 2>&1 || /usr/bin/ruby -e "$(curl -fsSL"
  • Install Python (includes pip):
brew install python

Alternatively, you can download the latest Python 3.x installer for Mac.

Linux (Ubuntu)

sudo apt-get update
sudo apt-get install -y python

Install Docker Desktop

To install Docker with user interface on Windows or Mac, download and install Docker Desktop


Want to contribute to iCloud Photos Downloader? Awesome! Check out the contributing guidelines to get involved.