Immich Upload (Image/File)
Your generations, straight into your own Google Photos
- images
- asset_ids_json
If you self-host Immich - the open-source Google Photos alternative - you already know the pain this node solves. Your ComfyUI output folder grows by the day, timestamp filenames pile up, and finding that one generation from three weeks ago means spelunking. Meanwhile your real photo library lives in Immich, with search, face recognition, and albums. This node is the bridge: it takes the images still in your graph (or the MP4 you just rendered to disk) and uploads them straight to Immich, optionally into an album you pick or one it creates for you.
It's a Save/Network node, the "save" step of your workflow aimed at a server instead of a folder. And here's the thing - barely anyone in the ComfyUI community talks about it. In r/comfyui and r/StableDiffusion, Immich shows up a handful of times, mostly people discovering it works surprisingly well as a gallery for AI output folders (point Immich's "external library" at your output dir and it scans everything). This node flips that model: instead of Immich finding your files, ComfyUI hands them over, metadata and all. If you're an Immich user, this is the save step you didn't know you were missing. If you're not, nothing here will change your life - this is a node with exactly one audience, and it's fine with that.
How it works
Plain REST calls, no extra server, no password sharing. You give it the Immich API base URL and an API key (Immich → your user menu → API Keys), and the node talks to the /assets endpoint with an x-api-key header. The default http://127.0.0.1:2283/api assumes Immich runs on the same machine as ComfyUI; if it's on another box, point it at that host's IP or hostname - the node even normalizes a bare host:port to the /api path for you.
It dedupes the way the Immich CLI does: every upload carries a deviceAssetId built from filename plus file modification time, so re-running a workflow won't duplicate the same asset. Images from your graph get written to a temp file (that's what save_image_format and save_quality control) and uploaded; file paths get streamed straight through. Finally, if you gave it an album name, it searches your albums and creates one if it's missing, then adds the fresh asset IDs to it.
The inputs that matter
Only two are required: base_url and api_key. Everything else is optional.
images- your IMAGE tensor. Wire it straight out of whatever KSampler/VaeDecode chain you're running.save_image_format/save_quality- png, jpeg, or webp; quality 1–100, default 95. Quality only applies to jpeg/webp - PNG is lossless, so that slider is dead weight there.file_paths- newline-separated absolute paths for things like the MP4 a video workflow wrote to disk. One per line. The file must exist on the machine running ComfyUI, or the node throws.album_id/album_name- ID wins if both are set; name is matched case-insensitively and created if absent.
Output is a single asset_ids_json string (JSON of the uploaded asset IDs plus the album ID). Drop it into a text-display node if you want to confirm what landed.
Installing it
Standard fare, no model downloads, no heavy dependencies - just requests (and pillow, which ComfyUI usually ships with):
cd ComfyUI/custom_nodes
git clone https://github.com/PatrickBorkowicz/ComfyUI-ImmichUploader
# then restart ComfyUI
Or search "Immich Uploader" in ComfyUI Manager and click install. On Windows with the embedded Python, the README has you pip-install requests into that environment explicitly:
<path-to>\ComfyUI\python_embeded\python.exe -m pip install requests
Where people get burned
The two real traps: forgetting the API key (the node hard-fails with a clear error if it's blank - it won't fall back to a password) and pointing base_url at the wrong host so your ComfyUI box can't reach the Immich server. Check those before you blame the node. Also note it's case-insensitive on album name, and if you leave album_name blank, nothing gets album'd - you just get loose assets in your library, which is fine if that's what you want.
This is an admirably boring node, in the good way. It uploads, it dedupes, it albums, and it gets out of your way. Exactly what you want from the save step.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| base_url | STRING | http://127.0.0.1:2283/api | — |
| api_key | STRING | — | |
| imagesopt | IMAGE | — | |
| save_image_formatopt | COMBO | png | 3 options: png, jpeg, webp |
| save_qualityopt | INT | 951–100 | — |
| file_pathsopt | STRING | — | |
| album_idopt | STRING | — | |
| album_nameopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| asset_ids_json | STRING | — |