How to Import Your iCloud Photos and Albums to Immich

By Jose FYS

Lab Objective: In this guide, you will learn how to mass-extract your entire iCloud photo library (including albums and original metadata) using icloudpd. Subsequently, we will import it natively into a local Immich server using immich-go, guaranteeing data integrity and avoiding duplicates during the upload.

Tools to Use

ToolPurposeKey Advantage
icloudpdDownload photos and albums from Apple serversMaintains metadata (EXIF/XMP), Live Photos, and hierarchical structure
immich-goUpload downloaded content to your Immich instanceAvoids duplicates and imports albums automatically by reading folders

Environment Preparation

To start downloading your photos from iCloud, the first step is to prepare a clean Python environment and install the necessary tool.

# Start virtual environment
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install icloudpd

Authentication and Session

If this is your first time using the tool or if your session has expired, you will need to perform the authentication process (2FA).

# 2FA / login
icloudpd --username $USER --cookie-directory "D:\TU-PC\immich-mig\auth" --auth-only

Migration Strategy

The process we will follow is divided into two phases: first, we will download all photos with their metadata organized by date, and then we will perform a specific download by albums to maintain that structure when importing into Immich. Once everything is downloaded, we will use immich-go to upload it to our instance.

1. Full Library Download

This command downloads all original files while maintaining a folder structure by date and preserving metadata.

# Full download with metadata
icloudpd `
  --username $USER `
  --cookie-directory "D:\TU-PC\immich-mig\auth" `
  --directory "D:\TU-PC\immich-mig\photos" `
  --folder-structure "{:%Y/%Y-%m-%d}" `
  --size original `
  --set-exif-datetime `
  --xmp-sidecar

What does this command do?

  • --folder-structure {:%Y}/{:%Y-%m-%d}: Creates a hierarchy like Year/Year-Month-Day.
  • --size original: Ensures we download the highest quality available.
  • --set-exif-datetime: Corrects or fills in the EXIF date if necessary.
  • --xmp-sidecar: Generates .xmp files with additional metadata.

2. Organization by Albums

To recreate your iCloud albums in Immich, we first need to list which albums exist and save them to a text file.

$USER="[email protected]"
$COOKIE="D:\TU-PC\immich-mig\auth"

# List albums and save to a file
icloudpd --username $USER --cookie-directory $COOKIE --list-albums >> D:\TU-PC\immich-mig\albums.txt

3. Album Download Script

With the generated list of albums, we will use the following PowerShell script to download the content of each album into its own folder. This will make it easier for Immich to identify them as independent albums upon import.

$USER      = "[email protected]"
$COOKIE    = "D:\TU-PC\immich-mig\auth"
$OUTROOT   = "D:\TU-PC\immich-mig\albums"
$ALBUMLIST = "D:\TU-PC\immich-mig\albums.txt"

# Function to sanitize invalid folder names
function Sanitize-Name([string]$name) {
  $invalid = [regex]::Escape(([string] [IO.Path]::GetInvalidFileNameChars()))
  return ($name -replace "[$invalid]", "_").Trim()
}

# Create root directory if it doesn't exist
New-Item -ItemType Directory -Force -Path $OUTROOT | Out-Null

# Process each album from the list
Get-Content $ALBUMLIST | ForEach-Object {
  $album = $_.Trim()
  if (-not $album) { return }

  $folder = Join-Path $OUTROOT (Sanitize-Name $album)
  New-Item -ItemType Directory -Force -Path $folder | Out-Null

  Write-Host "Downloading album: $album"
  icloudpd `
    --username $USER `
    --cookie-directory $COOKIE `
    --album $album `
    --directory $folder `
    --folder-structure none `
    --size original `
    --set-exif-datetime `
    --xmp-sidecar
}

Finalizing the Migration: Importing to Immich

Once we have all our photos and albums downloaded locally, the last step is to upload them to our Immich instance. We will use immich-go for this.

1. Generate API Key in Immich

Before launching the upload commands, we need to identify ourselves to the server:

  1. Log in to the Immich web interface.
  2. Click on the user icon (top right).
  3. Select Account Settings and then API Keys.
  4. Generate a new API KEY with all permissions and save it securely.

2. Configure the Upload Environment

To make executing the commands easier, we will define the addresses and the key as variables in PowerShell.

[!TIP] It is highly recommended to use the internal or direct URL of Immich (without going through a Reverse Proxy like Nginx) to avoid timeout issues or file size limits during mass migration.

$SERVER = "YOUR_IMMICH_URL" # Example: http://192.168.1.50:2283
$KEY    = "YOUR_API_KEY"

3. Run the Import

First, we will import the entire library (the full timeline) and then the specific albums.

Import the Timeline

# Using immich-go to upload from folder
immich-go upload from-folder --server=$SERVER --api-key=$KEY "D:\TU-PC\immich-mig\photos"

Import the Albums

This command will use the name of each subfolder to automatically create the corresponding album in Immich.

# Uploading and creating albums from folders
immich-go upload from-folder --folder-as-album=FOLDER --server=$SERVER --api-key=$KEY "D:\TU-PC\immich-mig\albums"

Troubleshooting and Technical Considerations

iCloud Web Interface Limitations Extracting massive backups directly from Apple’s website often leads to timeouts and fails to preserve the album structure correctly. Using icloudpd allows us to leverage the internal API to guarantee stable and resumable downloads.

2FA Token Expiration The generated session (cookie) has a limited lifespan. If the script stops throwing an authentication error mid-process, simply re-run the --auth-only command and relaunch the download. The process is idempotent and will resume right where it left off.

Duplicate File Management Importing the full timeline first and then the album directories does not generate duplicates. Immich calculates the checksum for each image; if it detects a duplicate during album processing, it simply creates a symbolic link to the corresponding album without consuming additional storage.


With these steps, we will have migrated all our iCloud content to our local Immich server, no longer depending on third-party services and regaining full control over our memories.

And as I always like to say: If this post has helped you, share it with other administrators who can benefit. And follow me for more real experiences from the homelab trenches.