Export everything out of Immich — files plus albums, people, tags, descriptions — into a redundant, human-readable local folder tree.
Project description
immich-export
Pull everything out of Immich — the files and the metadata that only lives in its database (albums, people, tags, descriptions, favorites, geo) — into a redundant, human-readable local folder tree.
This is the media escape hatch that makes "Immich = source of truth" reversible: if Immich vanished tomorrow, the export is a plain tree you can browse, grep, or import anywhere else.
immich-export/
library/2024/03/IMG_1234.jpg # primary tree (self-contained mode)
library/2024/03/IMG_1234.jpg.xmp # sidecar: tags, people, albums, description, geo, favorite
albums/Japan-2019/IMG_1234.jpg # → symlink into library/
people/Anna/IMG_1234.jpg # → symlink into library/
manifest.jsonl # one line per asset: id, checksum, path, all metadata
manifest.csv # the same, human-readable
export-report.txt # counts, warnings, errors, timing
Install
pipx install immich-export
# or
brew install fileworks/tap/immich-export
(Not yet published — first release pending; until then: uv run immich-export from a checkout.)
Usage
export IMMICH_SERVER=https://immich.local:2283
export IMMICH_API_KEY=... # Immich → Account Settings → API Keys
# full portable export (copies originals)
immich-export --out ./immich-export
# incremental re-run: only new/changed assets are downloaded
immich-export --out ./immich-export
# sidecar mode: you already have the Storage-Template tree mounted —
# only write .xmp sidecars + album/people views next to it
immich-export --mode sidecar --library-root /volume1/photos --out /volume1/photos
# custom primary tree
immich-export --layout "{year}/{album}" --out ./export
Key flags (see immich-export --help for all):
| Flag | Default | Meaning |
|---|---|---|
--mode |
self-contained |
self-contained copies originals; sidecar only writes XMP + views next to an existing tree |
--layout |
{year}/{month} |
primary tree; tokens {year} {month} {day} {album} {type}; {album} falls back to Unsorted |
--album-view / --people-view |
on | build albums/ and people/ symlink views |
--sidecars |
xmp |
xmp or none |
--since |
— | only assets taken on/after this date |
--resume |
on | skip assets already exported with an unchanged checksum (from manifest.jsonl) |
--include-hidden |
off | also export hidden + locked-folder assets |
Guarantees
- Read-only against Immich. Never writes back.
- Best-effort. One bad asset logs an error and the run continues; the report lists every failure.
- Idempotent / resumable. The manifest records each asset's checksum; re-runs download only new or changed files, and refresh sidecars when only metadata (albums/tags/people) changed.
- Verifiable. Every download is checked against Immich's SHA-1;
manifest.jsonllets you diff export-vs-server (or vs. a restore) any time. - Streams. Assets are paged and downloaded with bounded concurrency — a 100k-asset library never sits in memory.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success (including an empty library) |
| 2 | bad configuration or authentication failure |
| 3 | server unreachable |
| 4 | output directory unwritable / out of space |
| 1 | unexpected error (re-run with --verbose for the traceback) |
Sidecar format
Standard XMP wherever a standard slot exists — dc:subject (tags),
Iptc4xmpExt:PersonInImage (people), dc:description, photoshop:DateCreated,
exif:GPSLatitude/Longitude, xmp:Rating (favorite → 5) — so digiKam,
Lightroom and exiftool can read them. Album membership and Immich ids live in a
custom immich: namespace in the same file.
Immich API compatibility
Built against the Immich v3 API (spec version 3.0.1). Instead of a
generated client, the exact API slice used is declared in
src/immich_export/api_contract.py and checked in CI against a vendored,
pruned copy of the official OpenAPI spec. To check a new Immich release:
uv run python scripts/refresh_api_spec.py --ref v3.1.0
uv run pytest tests/test_contract.py
A removed endpoint or field fails the tests before it breaks at runtime.
Development
uv sync --all-extras --dev
uv run ruff check . && uv run ruff format --check . # lint
uv run mypy # strict types
uv run pytest # tests (mock Immich API)
uv build # sdist + wheel
Conventional Commits drive releases (python-semantic-release): merge to
main → version bump + changelog + GitHub Release + PyPI publish (OIDC) +
Homebrew formula bump.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file immich_export-0.0.3.tar.gz.
File metadata
- Download URL: immich_export-0.0.3.tar.gz
- Upload date:
- Size: 65.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
caa6d7b0f8e20f46f867f81faf8cba30c47d9c9b0d8fe4a8cba5e08b412de824
|
|
| MD5 |
0bf0feb95f1941f9e6ccee946c96942c
|
|
| BLAKE2b-256 |
2e6ef3d3ff9b92ecefe8dab872b9e712f06debcb033680497f7185d30b1182db
|
Provenance
The following attestation bundles were made for immich_export-0.0.3.tar.gz:
Publisher:
release.yml on fileworks/immich-export
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
immich_export-0.0.3.tar.gz -
Subject digest:
caa6d7b0f8e20f46f867f81faf8cba30c47d9c9b0d8fe4a8cba5e08b412de824 - Sigstore transparency entry: 2159801580
- Sigstore integration time:
-
Permalink:
fileworks/immich-export@34bb701f727c42ac626f974a9d1665be58f79b59 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fileworks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34bb701f727c42ac626f974a9d1665be58f79b59 -
Trigger Event:
push
-
Statement type:
File details
Details for the file immich_export-0.0.3-py3-none-any.whl.
File metadata
- Download URL: immich_export-0.0.3-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31536753bdab01d7eb6f72b71e3feb14905ab7ebdb61e12bd3fad012c30a6f0e
|
|
| MD5 |
fdfbc66c633f45cb4a4aa5bc9044c993
|
|
| BLAKE2b-256 |
c67856e6c622af994647f993898ef502cd9e43ef9523092aab0e04c95e1928ae
|
Provenance
The following attestation bundles were made for immich_export-0.0.3-py3-none-any.whl:
Publisher:
release.yml on fileworks/immich-export
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
immich_export-0.0.3-py3-none-any.whl -
Subject digest:
31536753bdab01d7eb6f72b71e3feb14905ab7ebdb61e12bd3fad012c30a6f0e - Sigstore transparency entry: 2159801844
- Sigstore integration time:
-
Permalink:
fileworks/immich-export@34bb701f727c42ac626f974a9d1665be58f79b59 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fileworks
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34bb701f727c42ac626f974a9d1665be58f79b59 -
Trigger Event:
push
-
Statement type: