EU AI Label (Metadata Writer & Save)
This Node Writes the AI-Act Metadata Google Actually Reads — and It Saves the File Itself
- images
- File Path
The EU AI Act's Article 50 transparency obligations are live since August 2026, and they ask providers to mark AI-generated content in a "machine-readable format" - invisible to the eye, but something Google and other platforms can detect. This node is the machine-readable half. It writes the IPTC DigitalSourceType XMP field (the marker that Google and others actually look for) into your image, embeds the ComfyUI workflow the way SaveImage does, and then saves the file itself.
Read that last part twice, because it's the whole trap: ComfyUI image tensors cannot carry file metadata between nodes, and the stock SaveImage writes its own metadata. Chain a SaveImage after this node and your AI-labeling XMP is silently gone. This is the save. Don't put another one after it.
How it works
The node builds a proper XMP packet as RDF/XML and embeds it natively through Pillow - PNG as an iTXt XML:com.adobe.xmp chunk, JPEG as an APP1 segment, WebP as an XMP chunk. The author deliberately avoided python-xmp-toolkit (needs the exempi C library) and pyexiv2 (binary wheels, platform grief), so the only dependencies are Pillow and numpy. Zero network calls at runtime.
If Embed Workflow is on (it is, by default), it also stuffs the ComfyUI prompt and workflow into the file like SaveImage does - which means your prompts, seeds, and local file paths end up inside the image. That's a privacy note, not a scare: it's the same default behavior you already have with SaveImage, just relevant here because this file is meant to travel. Flip it off if you're shipping to strangers. It also respects ComfyUI's global --disable-metadata flag.
The inputs that matter
- Digital Source Type - the one that matters. Four choices:
trainedAlgorithmicMedia- fully AI-generatedcompositeWithTrainedAlgorithmicMedia- AI-edited / compositealgorithmicMedia- algorithmic, no AI trainingnone- don't set it Pick the honest one; "which do I pick" is genuinely a judgment call, not a node setting.
- Description / Creator Tool / Credit - map to
dc:description,xmp:CreatorTool,photoshop:Credit. Sane defaults already there. - Custom XMP Fields - one
key=valueper line. Known prefixes (dc:,xmp:,photoshop:,Iptc4xmpExt:) map to their real namespaces; anything else goes into a pack-specific namespace. - Format - PNG, JPEG, or WebP. PNG is the one that keeps the workflow fully drag-drop-restorable in ComfyUI; JPEG/WebP carry it in EXIF instead. Quality applies to JPEG and WebP.
The File Path output (STRING, one path per line) is worth using: wire it into the sibling Metadata Check node for an instant round-trip verification that the label actually landed.
Install
Search ComfyUI_EU_AI_Label in ComfyUI Manager and install, then restart. Manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/a-und-b/ComfyUI_EU_AI_Label.git
pip install -r ComfyUI_EU_AI_Label/requirements.txt
Only Pillow and numpy - no model downloads, no native libs. The nodes appear under EU AI Label.
Where people get burned
The SaveImage-chaining trap above is the big one; the README warns about it in a box. Second is format: if a host re-encodes your file (basically every social platform), the metadata is gone regardless of what you wrote - this node writes the label, it can't make a recompressor keep it. And if you're generating for Art. 50 compliance, remember this is the machine-readable half; pair it with the Visible node for the label a human can see.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| digital_source_type | COMBO | IPTC DigitalSourceType — the machine-readable AI marker read by Google and others | |
| description | STRING | Contains AI-generated content — labeled in accordance with Art. 50 EU AI Act. | — |
| creator_tool | STRING | ComfyUI | — |
| credit | STRING | — | |
| custom_xmp_fields | STRING | Optional: one key=value per line (e.g. dc:rights=© 2026 Example GmbH) | |
| embed_workflow | BOOLEAN | true | Embed the ComfyUI workflow/prompt in the file. Privacy note: prompts and local paths end up in the image. |
| format | COMBO | 3 options: PNG, JPEG, WebP | |
| jpeg_quality | INT | 921–100 | Quality for JPEG and WebP |
| filename_prefix | STRING | ComfyUI | — |
| filename_suffix | STRING | _ai-labeled | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| File Path | STRING | — |