πΎ Save Image With Metadata
The save node that makes Civitai actually read your generations
- images
ComfyUI's built-in SaveImage writes two PNG text chunks: workflow (the full UI graph) and prompt (the execution graph). That's excellent for round-tripping - drag the PNG back onto the canvas and your graph rebuilds, which is how ComfyUI ships its own example workflows. What it does not write is the flat A1111-style parameters string, and that's the thing CivitAI parses to auto-detect your checkpoint, sampler, seed and LoRA hashes and link them on the upload. There's a whole community article titled "Stop using ComfyUI's default Save Image node (if you post to Civitai)" for exactly this reason.
πΎ Save Image With Metadata writes both: the ComfyUI graph (if you want it) and the A1111 parameters block CivitAI's parser reads. It's adapted from ChronoKnight's Chrono-Save-for-Civitai node, and the author credits that plainly.
How it knows your settings
This is the interesting part. The node doesn't ask you to wire anything in, because there is nothing to wire: images is the only input that needs connecting. Instead it captures the prompts and LoRAs from the executed runtime graph - walking upstream from the sampler that actually ran - with a fallback to parsing the saved workflow graph if the runtime route comes up empty. Same mechanism for the model, sampler, seed and steps it writes into the metadata.
The practical consequence: it reads what ran, not what you typed. That's more reliable than widget-scraping in most graphs, but it's also why a heavily bypassed or muted branch can leave it guessing. When it gets something wrong, that's what positive_override is for.
There's also a special case worth knowing: if a π Batch Wildcard Upscale Sampler is in the graph, this saver detects it and writes each image its own prompt, negative and seed (seed + index) automatically, no wiring required. That node samples internally with no KSampler or text-encode node in the graph, so the saver couldn't discover anything by conventional means.
Inputs
images- the batch. Multiple images are saved as separate numbered files.filename_prefix- a template, default%date:yyyy-MM-dd - hh.mm.ss%. It takes standardstrftimecodes plus the node's own%date:format%style and two extras:%seed(the resolved generation seed) and%model(the model basename).folder- a subfolder under ComfyUI's output directory, same templating, default%date:yyyy-MM-dd%so runs self-organise into dated folders.file_format-png,jpegorwebp.quality- 1-100 for jpeg and webp, ignored for PNG.embed_workflow- include the workflow in the file. On by default.strip_lora_prompt- strips<lora:...>and embedding tags from the prompt text in the metadata. The LoRA hashes are recorded separately either way, so this is purely about how the prompt reads.positive_override- optional. A single string applies to every image; a list applies one per image, looping if the list length doesn't match the image count. Wire thepromptlist output from the Batch Wildcard Sampler here for manual per-image control.
The format trap
Save as PNG if the workflow matters. PNG is the only common format carrying the tEXt/iTXt text chunks, so it's the only one that round-trips a full graph. JPEG and WebP re-encode by definition and have no PNG text chunks - the best you get is a flat parameter string re-homed in EXIF. So: PNG for the master you archive and drag back in, JPEG/WebP for the derivative you upload somewhere. Also remember that anything you do post publicly carries your prompt, seed and the exact model stack unless you scrub it first - the metadata is the workflow, and the default is disclosure.
Install
ComfyUI Manager β ComfyUI-mnemic-nodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes
Restart. piexif comes in with the pack requirements for the EXIF side of things. No model downloads.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | The images to save. A batch is saved as separate numbered files. | |
| filename_prefix | STRING | %date:yyyy-MM-dd - hh.mm.ss% | Filename prefix template. %Y: Year (e.g., 2025) %m: Month (01-12) %d: Day of month (01-31) %H: Hour (24-hour clock) (00-23) %M: Minute (00-59) %S: Second (00-59) %f: Microsecond (000000-999999) %x: Date representation %X: Time representation %c: Date and time representation %p: AM/PM %A: Weekday full name (e.g., Thursday) %a: Weekday abbreviated name (e.g., Thu) %B: Month full name (e.g., August) %b: Month abbreviated name (e.g., Aug) %j: Day of year (001-366) %W: Week number of year (Monday as first day) (00-53) %w: Day index of week (Monday is 0) (0-6) %U: Week number of year (Sunday as first day) (00-53) %u: Day index of week (Sunday is 0) (0-6) %%: A literal '%' character %date:yyyy-MM-dd - hh.mm.ss%: custom date token style %seed: resolved generation seed %model: resolved model basename |
| folder | STRING | %date:yyyy-MM-dd% | Subfolder under ComfyUI output directory. %Y: Year (e.g., 2025) %m: Month (01-12) %d: Day of month (01-31) %H: Hour (24-hour clock) (00-23) %M: Minute (00-59) %S: Second (00-59) %f: Microsecond (000000-999999) %x: Date representation %X: Time representation %c: Date and time representation %p: AM/PM %A: Weekday full name (e.g., Thursday) %a: Weekday abbreviated name (e.g., Thu) %B: Month full name (e.g., August) %b: Month abbreviated name (e.g., Aug) %j: Day of year (001-366) %W: Week number of year (Monday as first day) (00-53) %w: Day index of week (Monday is 0) (0-6) %U: Week number of year (Sunday as first day) (00-53) %u: Day index of week (Sunday is 0) (0-6) %%: A literal '%' character %date:yyyy-MM-dd - hh.mm.ss%: custom date token style %seed: resolved generation seed %model: resolved model basename |
| file_format | COMBO | File type to write. PNG is lossless; jpeg and webp use the quality setting. | |
| quality | INT | 1001β100 | Compression quality for jpeg and webp, 1-100. Ignored for PNG. |
| embed_workflow | BOOLEAN | true | Include workflow in the image. |
| strip_lora_prompt | BOOLEAN | false | Strip LoRAs from prompt. |
| positive_overrideopt | STRING | Override the auto-detected positive prompt. Accepts a single string (applied to every image) or a list of prompts (one per image, looping if the count differs from the number of images). |
Outputs (0)
No outputs