Nodes/comfyui-too-xmp-metadata/Write XMP Metadata (Lossless)
ComfyUI Node

Write XMP Metadata (Lossless)

Tag your image library without touching a pixel

By tetsuoo-online·Created about a year ago·Updated 3 months ago· 9
Write XMP Metadata (Lossless)
    • output_path
    input_image_path
    metadata1girl, black hair
    output_dir
    console_debugfalse

    If you generate a lot and also hoard, this is the node. WriteXMPMetadataLossless takes an image that already exists on disk, sticks your tags into it, and saves the result somewhere new - without decoding, recompressing, or re-encoding a single pixel. The output is pixel-identical to the original, in the same format, with the same creation and modification timestamps. It's a few kilobytes of extra text riding inside the file, nothing more. The "lossless" in the name is real, not marketing.

    The mechanism is a copy, not a rewrite. The node duplicates your file (shutil.copy2, which already preserves timestamps), then hands the copy to ExifTool with one -XMP-dc:Subject+=tag argument per tag and -overwrite_original so the metadata is written in place. Afterwards it restores the timestamps with os.utime, because ExifTool has a habit of bumping them. Format is preserved for the same reason: nothing is ever decoded - the image data never passes through PIL at all.

    The inputs that matter:

    • input_image_path - the full path to the image on disk. This node cannot take a tensor; if you're tagging a fresh render, wire a Save Image node first and point this at the saved file.
    • metadata - comma-separated tags (landscape, sunset, ocean) or a JSON object. The default 1girl, black hair is a leftover from the author's booru habits - change it.
    • output_dir (optional) - where the tagged copy goes. Leave it blank and the file lands in a tagged subfolder next to the original, keeping its filename.
    • console_debug (optional) - makes the node narrate the ExifTool command it runs.

    Output is output_path, a STRING with the location of the tagged file. It's an output node, so the graph finalizes when it runs.

    The JSON form is worth knowing, because it lets you attach more than tags:

    {
      "tags": ["landscape", "sunset"],
      "author": "you",
      "description": "Beach at golden hour"
    }
    

    The tags list becomes searchable Subject keywords; everything else becomes custom fields in an XMP-comfyui namespace. Any tag viewer that reads XMP - XnView, for example - can search all of it.

    Where people get burned:

    • It won't touch a file already inside a tagged folder unless you give it an explicit output_dir. That's the loop guard working as intended - it stops you from retagging copies forever. Point it at a fresh directory and it'll proceed.
    • Rerunning appends. Since v1.1.0 existing metadata is kept and new tags are added, so you can build a library up over time without clobbering earlier notes.
    • "Erreur: ..." in the node's output is French, not a foreign bug - the author is francophone. The two usual causes are ExifTool not being installed and a path that doesn't exist.
    • ExifTool is the actual dependency. The pip requirements are just pillow and numpy, which ComfyUI ships with; the real requirement is the ExifTool binary. Windows is covered by the exiftool.exe bundled in the repo, but on Linux or macOS you install it yourself (apt install libimage-exiftool-perl, or brew install exiftool on a Mac).

    Install is standard: ComfyUI Manager, search "comfyui-too-xmp-metadata", or git clone https://github.com/tetsuoo-online/comfyui-too-xmp-metadata into ComfyUI/custom_nodes and restart.

    If you want tags on everything already sitting in your library - screenshots, old renders, downloaded references - this is the one you reach for. It's the whole "tags live in the files so I can't lose the database" philosophy the pack is built around, and it's the safest node in the pack precisely because it never re-encodes anything.

    Categorytoo/xmp-metadata

    Inputs (4)

    NameTypeDefaultDescription
    input_image_pathSTRING
    metadataSTRING1girl, black hair
    output_diroptSTRING
    console_debugoptBOOLEANfalse

    Outputs (1)

    NameTypeDescription
    output_pathSTRING