A Bash script for bulk-importing photos into Immich from Google Photos takeout ZIPs and/or local folders, with rich push notifications via ntfy.sh.
- Multi-phase imports — each takeout ZIP and each folder runs as a separate phase
- Auto-discovers takeout ZIPs — drop ZIPs in the script directory (or configure
TAKEOUT_DIR), they're picked up automatically - Push notifications via ntfy.sh:
- Import started (with full phase list)
- Progress pings every 30 min (configurable) with live stats per phase
- Phase complete with stats (uploaded / dupes / errors / assets)
- Next phase announcement
- Final summary
- Pre-flight checks — config present, required vars set, Immich reachable, API key valid,
immich-goin PATH - Config summary on startup — shows server, masked API key, ntfy topic, interval, all folders with ✅/❌ existence checks
- Dry-run mode —
DRY_RUN=1passes--dry-runto immich-go, no uploads - Notification test mode —
TEST_NOTIFY=1sends a single test notification and exits
git clone https://github.com/Rediwed/immich-import.git && cd immich-import && cp immich-import.example.conf immich-import.conf && $EDITOR immich-import.conf# 1. Copy and edit the config
cp immich-import.example.conf immich-import.conf
$EDITOR immich-import.conf
# 2. (Optional) Drop Google Photos takeout ZIPs in the same directory
# 3. Run
bash immich-import.sh| Variable | Required | Default | Description |
|---|---|---|---|
IMMICH_SERVER |
✅ | — | Immich URL, e.g. http://localhost:2283 |
IMMICH_API_KEY |
✅ | — | Immich API key (Account Settings → API Keys) |
NTFY_TOPIC |
✅ | — | ntfy.sh topic name |
TAKEOUT_DIR |
— | script dir | Directory containing Google Photos takeout ZIPs |
IMPORT_FOLDERS |
— | () |
Bash array of local folders to import |
PROGRESS_INTERVAL |
— | 1800 |
Seconds between progress notifications |
Override any config value inline — useful for testing:
# Dry run with 20-second progress pings
PROGRESS_INTERVAL=20 DRY_RUN=1 bash immich-import.sh
# Test ntfy notifications only
TEST_NOTIFY=1 bash immich-import.shSettings are applied in this order (highest to lowest priority):
- Environment variable (set inline or exported in your shell)
immich-import.conf(your local config file)- Built-in default (fallback value defined in the script)
A value set via environment variable always wins, even if the same key is defined in the config file.
Push notifications are sent to your configured NTFY_TOPIC at key points during the import:
- Import started — lists all phases about to run
- Progress pings — sent every
PROGRESS_INTERVALseconds (default 30 min) while a phase is running, showing live per-phase stats - Phase complete — sent when each takeout ZIP or folder finishes, with a full stats breakdown
- Next phase announcement — sent before each new phase begins
- Final summary — sent when all phases are done
Progress ping (sent periodically during a phase):
⏳ Phase 2/5: Folder: Camera Roll — Immich read 43%, Assets found: 1204, Upload errors: 0, Uploaded 521
Final summary (sent when the entire import completes):
🎉 Import done in 47m — ↑3761 new, 16791 dupes, 0 errors
Phase 1/3 — Takeout: takeout-001.zip (12m): ↑1204 new, 8230 dupes, 0 errors / 9434 assets
Phase 2/3 — Folder: Camera Roll (23m): ↑2557 new, 8561 dupes, 0 errors / 11118 assets
...