Files
2026-07-12 10:17:17 -04:00

5.3 KiB

name, description, tags
name description tags
immich-import Import photos into Immich from Google Takeout, local folders, and other sources using immich-go CLI
immich
google-takeout
photo-import
self-hosting
immich-go

Immich Photo Import

Import photos into a self-hosted Immich server. Covers Google Takeout imports (the most common case), plain folder uploads, and troubleshooting.

When to load this skill

  • User says "import photos to Immich", "Google Takeout", "immich-go", or "upload to Immich"
  • User is migrating from Google Photos to Immich
  • User has a folder of photos to bulk-upload to Immich

Prerequisites

  • Immich server URL (e.g. http://192.168.50.150:2283)
  • API key with sufficient permissions (needs at minimum user.read + upload rights)
  • immich-go binary installed (for large imports) or the Immich CLI inside the server container

Workflow

1. Verify immich-go is installed

/usr/local/bin/immich-go version

Install if needed (from simulot/immich-go releases).

2. Get a valid API key

Option A — Via Immich web UI:

  • Settings → API Keys → Create New Key → name it → copy the key

Option B — Via Immich API (if you know the password):

# Login and create key
TOKEN=$(curl -s -X POST http://<server>:2283/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"..."}' | python3 -c "import json,sys; print(json.load(sys.stdin).get('accessToken',''))")

curl -s -X POST http://<server>:2283/api/api-key \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"immich-go-import"}'

Option C — Find admin email from DB:

docker exec immich_postgres psql -U postgres -d immich -c \
  'SELECT id, email, name, "isAdmin" FROM "user";'

3. Google Takeout Import

3a. Download the Takeout zips

If using Chrome in a KasmVNC container to download and Chrome kills the downloads:

Fix Chrome Safe Browsing (kills large Takeout zips):

docker exec -u 0 chrome sh -c 'cat > /etc/opt/chrome/policies/managed/download_safety.json << '\''EOF'\''
{
    "DownloadRestrictions": 0,
    "SafeBrowsingEnabled": false,
    "SafeBrowsingProtectionForDownloadEnabled": false
}
EOF
'
# Kill Chrome so it restarts with the new policies
docker exec -u 0 chrome pkill -f "chrome" || true

3b. Extract the zips

# install unzip if missing
sudo apt install -y unzip

mkdir -p /path/to/extracted
for f in takeout-*.zip; do
  unzip -q -o "$f" -d extracted/
done

3c. Import to Immich

# From Google Takeout (preserves albums, metadata, people tags):
/usr/local/bin/immich-go \
  --server=http://<server>:2283 \
  --api-key=<your-key> \
  upload from-google-photos /path/to/extracted/

# From a plain folder (no Takeout metadata):
/usr/local/bin/immich-go \
  --server=http://<server>:2283 \
  --api-key=<your-key> \
  upload from-folder --recursive /path/to/folder/

Using the Immich CLI inside the server container instead:

docker exec immich_server /usr/src/app/server/bin/immich \
  --url http://localhost:3001 \
  --key <your-key> \
  upload --recursive /path/

4. Verify

After import, check Immich web UI for:

  • Albums created (if using from-google-photos)
  • Asset counts
  • Background jobs processing (thumbnails, face detection, etc.)

Pitfalls

  • Flag names: immich-go uses --api-key and --server (double-dash long form). Single-dash -key or -server gets parsed as short flags (e.g. -k + ey=...) and fails silently or shows help.

  • API key permissions: immich-go checks several endpoints during startup. A key needs all of these permissions or it will fail with 403 at each check:

    • user.read — connection validation (GET /api/users/me)
    • server.about — server info check (GET /api/server/about)
    • asset.statistics — pre-upload stats (GET /api/assets/statistics)
    • asset.write + asset.read — actual upload + duplicate detection
    • job.create — pausing background jobs during upload (optional — skip with --pause-immich-jobs=FALSE)

    Best practice: Create a fresh key and enable all permissions, or you'll hit a whack-a-mole of 403s one endpoint at a time.

  • Chrome Safe Browsing: Google Takeout zips can be 50GB+. Chrome flags them as "uncommon" and kills the download with FILE_SECURITY_CHECK_FAILED (reason 40, danger UNCOMMON). The .crdownload files will be orphaned — they will never complete. Fix: set managed policies to disable Safe Browsing for downloads, then restart Chrome.

  • unzip not installed: Check first. On Ubuntu/Debian: sudo apt install unzip.

  • DB table names: Immich PostgreSQL uses lowercase table names. The user table is "user", not "users". Column names use camelCase quoting (e.g. "isAdmin", "oauthId"). Key permissions vs --pause-immich-jobs flag: If the API key lacks job.create, immich-go fails trying to pause background jobs. Workaround: add --pause-immich-jobs=FALSE to skip the job-pausing step:

/usr/local/bin/immich-go \\
  --server=http://<server>:2283 \\
  --api-key=<your-key> \\
  --pause-immich-jobs=FALSE \\
  upload from-google-photos /path/to/extracted/

This lets uploads proceed without admin-level job permissions. Thumbnails/face detection will process in the background normally.