Save Image (Rich Metadata)
The SaveImage that CivitAI actually understands
- images
ComfyUI's stock SaveImage embeds the workflow graph but not the flat A1111-style parameters string that CivitAI's uploader actually parses. So you can post a perfect render and watch it land on the platform with no prompt, no model link, no steps - just pixels. Save Image (Rich Metadata) is the drop-in fix: same wiring, but every PNG you save also carries an A1111-compatible parameters chunk with resource hashes, so CivitAI auto-detects the checkpoint and LoRAs and links their resource pages. If you live in the upload loop, this is the save node you want.
What it writes, and why it matters
Each PNG gets three tEXt chunks. Two of them you already know from any ComfyUI save: prompt and workflow, the standard JSON that drag-and-drop restores. The third is parameters - the A1111/Forge dialect: positive prompt with inline <lora:name:weight> tags, a Negative prompt: line, then Steps:, Sampler:, CFG scale:, Seed:, Size:, Model hash:, Model:, Lora hashes:, Hashes:.
The hashes are the clever part. They're AutoV2 form - the first 12 hex of the file's SHA256 - computed for the checkpoint (searched in checkpoints → diffusion_models → unet) and every enabled LoRA. That's exactly what CivitAI's PNG inspector keys on to auto-link resources. The author even got the ordering right: the JSON Hashes: block goes last, because its commas would otherwise break A1111's key-value parsing. There's also a fourth chunk, ai_gallery_meta, a clean canonical JSON meant for the author's AI Gallery app - you can ignore it unless you use that tool.
The inputs that matter
There are no outputs; it's an output node. The fields you'll actually touch:
filename_prefix- note the default isAIGal, notComfyUI, so change it or your files land in anAIGal_00001_.pngpattern you didn't expect.images- an autogrow input. Plug in a second batch and the node grows a new slot (up to the 100-slot cap), saving each batch with_2,_3, … suffixes. Raw + refine + upscale in one workflow, one node, shared metadata.embed_workflowandembed_a1111- both default on. Turn offembed_a1111only if you need a minimal PNG.prompt_text/negative_text- see below; these are the ones that bite.
The prompt_text trap
The workflow graph only stores node inputs. If your prompt is generated at runtime - an LLM prompt expander, a wildcard processor, a random picker - the final text isn't in the graph, and no parser can recover it afterward. For those workflows, wire the actual string into prompt_text (and negative_text if you have one); it's written verbatim and overrides graph extraction. Otherwise the node does a genuinely thorough graph walk - tracing through CLIPTextEncode, string primitives, routers like rgthree's Any Switch, even reproducing KJNodes' Ideogram 4 Prompt Builder output - but no heuristics beat handing it the real string.
Install
Nothing to download beyond the repo; it needs only Pillow and NumPy, both shipped with ComfyUI, and a ComfyUI build with the v3 API (any recent release). ComfyUI Manager can find it by searching "Save Image Rich Metadata", or:
cd ComfyUI/custom_nodes
git clone https://github.com/quzopl/comfyui-save-image-rich-metadata.git
Restart, and it appears in the image category.
Gotchas
- First save after loading a new model is slow. Each file is SHA256'd once, then cached in a
.hash_cache.jsoninside the pack's folder (keyed by path + size + mtime). Subsequent saves are instant; nothing gets written next to your model files. - Metadata dies on re-encode, as always. The chunks are only in your original PNG - screenshots, JPEG conversion, and Reddit uploads strip them. Keep the master copy.
- It's still niche. This pack is brand new with no community track record yet. The mechanism checks out against the source, but don't expect a big ecosystem of tutorials around it.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| filename_prefix | STRING | AIGal | Filename prefix for the first image batch. Extra batches auto-suffix '_2', '_3', ... |
| images | COMFY_AUTOGROW_V3 | — | |
| embed_workflowopt | BOOLEAN | true | Also embed standard ComfyUI 'prompt'+'workflow' chunks. |
| embed_a1111opt | BOOLEAN | true | Also embed A1111-compatible 'parameters' chunk. |
| prompt_textopt | STRING | Optional. Connect the STRING that actually conditioned the image (e.g. the output of an LLM prompt expander, wildcard processor or switch). Overrides the prompt recovered from the workflow graph — use it whenever the prompt is generated at run time. | |
| negative_textopt | STRING | Optional. Explicit negative prompt STRING; overrides graph extraction. |
Outputs (0)
No outputs