Your metadata belongs in your files

Your self-hosted Immich server knows where, when and what. The original files usually don't. Immich Exif reads that metadata and writes it back into the photo itself, so it travels with the file.

immich-exif

$ immich-exif -y 60566630-…

=> 60566630 | IMG_20180523_200432.jpg

embedding 12 missing tags into the file:

+ GPSLatitude (none) 48.8566

+ GPSLongitude (none) 2.3522

+ ImageDescription (none) Dinner in Paris

~ DateTimeOriginal 2018:05:23 …23 18:04:32+02:00

+ Rating (none) ★★★★★

+ Make (none) Canon

embedded · re-uploaded · verified

EXIFTOOL-BACKED · DRY-RUN SAFE · CHECKSUM-VERIFIED DELETES · DUAL-API · PIPELINE 94% TESTED

Everything Immich knows, in the file

Immich keeps all that metadata in its database. Immich Exif diffs it against what's actually in each file and embeds only what's missing.

GPS & Places

Latitude and longitude with hemisphere refs, written to both EXIF and XMP so maps and other tools agree on where a shot was taken.

Dates & Timezones

DateTimeOriginal with the right offset: the exact moment your camera should have recorded, timezone included.

Descriptions

Captions written across EXIF, XMP and IPTC at once, so every app that reads metadata shows the same text.

Ratings

Your stars, as Rating, RatingPercent and XMP-xmp:Rating. The photos you picked stay picked, anywhere they land.

Camera & Lens

Make, model and lens model put back on shots that lost them in an import or an edit round-trip.

Video

The same pipeline writes metadata into mp4, mov and m4v. Other containers are skipped, never mangled.

A file, not a database

Metadata locked in a server is metadata you lose the day you export, migrate, or hand a photo to someone else. Immich Exif bakes it into the file with exiftool, so the photo is self-describing, no server required.

  • Reads the tags already in the file, writes only what's missing
  • Skips assets whose metadata already matches, so a re-run does nothing
  • Downloads to a temp dir, never overwrites a file outside it

# per asset
fetch metadata from Immich
diff Immich ⇄ the file's tags
embed only the missing tags (exiftool)
replace re-upload, copy links, delete old
skip anything already in sync

✓ safe to run again and again

Built to never lose a photo

It re-uploads and deletes real assets, so the destructive path is the careful path.

Upload before delete

The corrected file is uploaded and its album, favorite and visibility links copied before the old asset is ever removed. An interruption leaves a duplicate, never a hole.

Verify the bytes

Checksum verification is on by default: the uploaded asset is re-fetched and its checksum compared to what you sent before anything is removed. Downloads are checked the same way, so a corrupt or truncated transfer never reaches the upload step.

Permanent only when verified

A verified original is permanently deleted, because the new copy is provably byte-identical. Pass -no-verify-upload to skip the check and the original goes to Immich's trash instead, where you can still recover it.

Dry-run anything

-dry-run shows every change as a diff and writes nothing. A local SQLite cache skips assets already in sync, so re-running over a library is cheap and safe.

Running in three steps

Install, point it at your server, and preview before you commit.

immich-exif · getting started

$ git clone https://github.com/Majorfi/immich-exif

$ cd immich-exif/src && go build -o immich-exif .

$ export IMMICH_URL=https://photos.example.com

$ export IMMICH_API_KEY=••••••••••••

$ ./immich-exif -dry-run <asset-id> # preview one, write nothing

$ ./immich-exif -y -all # embed across the whole library

  1. 1

    Install it

    Grab a release binary, or clone the repo and go build in src/. It shells out to exiftool, so make sure that's on your PATH.

  2. 2

    Point it at your server

    Set IMMICH_URL and an API key from Account Settings → API Keys. The key lives in your .env, sent only to your own server.

  3. 3

    Run it

    Start with immich-exif -dry-run <asset-id> to preview a single photo, then -y -all when the diff looks right.

Every flag and tag is covered in the full documentation.

Fair questions

Is it free?

Yes. Immich Exif is open source: build it from source or grab a release binary. No paywall.

Does it touch my originals?

It embeds the missing tags into the file and re-uploads the corrected copy to Immich. Assets that already carry the right metadata are detected by a content snapshot and skipped, so it's safe to run repeatedly.

Can it lose my photos?

It's built hard against that. The new asset is uploaded before the old one is deleted, so an interruption leaves a duplicate, never a hole. By default the upload is checksum-verified byte-for-byte (and downloads are verified too) before the original is removed; only a provably identical copy lets the original be permanently deleted. If you pass -no-verify-upload to skip that check, the original is moved to Immich's trash instead, so it stays recoverable. And -dry-run lets you see every change first.

What do I need?

exiftool on your PATH, a running Immich server, and an API key. Go if you build from source, or just a prebuilt binary otherwise.

Does it work with the latest Immich?

Yes. The -immich-api flag auto-detects whether your server speaks the legacy or the 3.x API and adjusts the requests (album lookups, upload fields) accordingly.

Is this an official Immich tool?

No. It's an independent open-source companion that talks to Immich's public REST API. Immich is a trademark of its respective owners.

Free & open source

Your metadata, everywhere your photos go

Embed it once and the GPS, dates and captions ride along in the file. No database required to read them back.