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 usingimmich-go, guaranteeing data integrity and avoiding duplicates during the upload.
Tools to Use
| Tool | Purpose | Key Advantage |
|---|---|---|
icloudpd | Download photos and albums from Apple servers | Maintains metadata (EXIF/XMP), Live Photos, and hierarchical structure |
immich-go | Upload downloaded content to your Immich instance | Avoids 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 likeYear/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.xmpfiles 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:
- Log in to the Immich web interface.
- Click on the user icon (top right).
- Select Account Settings and then API Keys.
- 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.
masalladelcloud