Clothes Changer
With this app, you can change any outfit, in any photo! Instantly switch styles, explore new looks, or even create marketing-worthy shots for your store, with zero hassle. All you need to do is upload your character and a reference outfit, it's that simple.
Inside the workflow
A read-only preview of the source template. Open it in Cloud to explore the nodes and make changes.
Loading the graph
Open full-size workflow preview- Output
- Image
- Author
- Rob
Call this model from your code
The request below uses the same prepared graph and settings as the Playground. Each submission can start a paid run; do not automatically retry a submission whose outcome is unknown.
What you need
- Runs on
- Comfy Cloud
- Key
- COMFY_API_KEY
- Your files
- Uploaded by the code from their urls
Needs a paid Cloud plan and credits.
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"266": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_person_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"267": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_outfit_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"294": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Qwen_Edit_2511",
"images": [
"293:289",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"293:269": {
"class_type": "ModelSamplingAuraFlow",
"inputs": {
"model": [
"293:322",
0
],
"sampling": "flow",
"shift": 3.1
},
"_meta": {
"title": "ModelSamplingAuraFlow"
}
},
"293:270": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "qwen_image_vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"293:274": {
"class_type": "TextEncodeQwenImageEditPlus",
"inputs": {
"clip": [
"293:281",
0
],
"image1": [
"293:290",
0
],
"image2": [
"293:292",
0
],
"prompt": [
"293:337",
0
],
"vae": [
"293:270",
0
]
},
"_meta": {
"title": "TextEncodeQwenImageEditPlus (Positive)"
}
},
"293:275": {
"class_type": "CFGNorm",
"inputs": {
"model": [
"293:269",
0
],
"pre_cfg": False,
"strength": 1
},
"_meta": {
"title": "CFGNorm"
}
},
"293:276": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
"model": [
"293:275",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
},
"293:277": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 4
},
"_meta": {
"title": "CFG"
}
},
"293:278": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 1
},
"_meta": {
"title": "CFG"
}
},
"293:279": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"293:290",
0
],
"vae": [
"293:270",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"293:280": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "qwen_image_edit_2511_bf16.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"293:281": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_2.5_vl_7b_fp8_scaled.safetensors",
"device": "default",
"type": "qwen_image"
},
"_meta": {
"title": "Load CLIP"
}
},
"293:282": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"293:275",
0
],
"on_true": [
"293:276",
0
],
"switch": [
"293:285",
0
]
},
"_meta": {
"title": "Switch (Model)"
}
},
"293:283": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 6
},
"_meta": {
"title": "Steps"
}
},
"293:284": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 30
},
"_meta": {
"title": "Steps"
}
},
"293:285": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": True
},
"_meta": {
"title": "Enable 4steps LoRA?"
}
},
"293:286": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"293:277",
0
],
"on_true": [
"293:278",
0
],
"switch": [
"293:285",
0
]
},
"_meta": {
"title": "Switch (CFG)"
}
},
"293:287": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"293:284",
0
],
"on_true": [
"293:283",
0
],
"switch": [
"293:285",
0
]
},
"_meta": {
"title": "Switch (Steps)"
}
},
"293:288": {
"class_type": "KSampler",
"inputs": {
"cfg": [
"293:286",
0
],
"denoise": 1,
"latent_image": [
"293:279",
0
],
"model": [
"293:282",
0
],
"negative": [
"293:291",
0
],
"positive": [
"293:274",
0
],
"sampler_name": "euler",
"scheduler": "simple",
"seed": 525225493084341,
"steps": [
"293:287",
0
]
},
"_meta": {
"title": "KSampler"
}
},
"293:289": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"293:288",
0
],
"vae": [
"293:270",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"293:290": {
"class_type": "FluxKontextImageScale",
"inputs": {
"image": [
"266",
0
]
},
"_meta": {
"title": "FluxKontextImageScale"
}
},
"293:291": {
"class_type": "TextEncodeQwenImageEditPlus",
"inputs": {
"clip": [
"293:281",
0
],
"image1": [
"293:290",
0
],
"image2": [
"293:292",
0
],
"prompt": "",
"vae": [
"293:270",
0
]
},
"_meta": {
"title": "Text Encode Qwen Image Edit Plus"
}
},
"293:292": {
"class_type": "FluxKontextImageScale",
"inputs": {
"image": [
"267",
0
]
},
"_meta": {
"title": "FluxKontextImageScale"
}
},
"293:322": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "Qwen-Image-Edit-2509-clothes_try_on_clothing_transfer_edit.safetensors",
"model": [
"293:280",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
},
"293:330": {
"class_type": "TextGenerateLTX2Prompt",
"inputs": {
"clip": [
"293:332",
0
],
"image": [
"267",
0
],
"max_length": 256,
"mtp": "auto",
"prompt": "You are a garment tagger for a virtual try-on pipeline. The user message contains one image of an outfit (flat lay or product grid).\n\nOutput a single lowercase phrase enumerating every wearable item in the image, and nothing else — no preamble, no labels, no quotes, no trailing period, no line breaks.\n\nRules:\n- Describe each item as: [color/wash] [material or texture, if visually distinctive] [fit/cut, if notable] [garment type], e.g. \"washed brown oversized hoodie\", \"tan suede crossbody bag\".\n- Order: main top, bottoms, then accessories (headwear, belt, bag), footwear last.\n- Separate items with commas, with \"and\" before the last item.\n- For bags, append how they are worn if inferable, e.g. \"worn across the chest\".\n- Include only items visible in the image; never invent items, brands, or logos.\n- Mention a brand or printed text only if clearly legible on the garment.\n- If the image contains no clothing, output exactly: no garments detected",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 123456789,
"sampling_mode.temperature": 0.7,
"sampling_mode.top_k": 64,
"sampling_mode.top_p": 0.95,
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Prompt"
}
},
"293:331": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"293:330",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"293:332": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3.5_4b_bf16.safetensors",
"device": "default",
"type": "stable_diffusion"
},
"_meta": {
"title": "CLIP Loader"
}
},
"293:335": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": " ",
"string_a": "Put the clothes on the left onto the person on the right.\nDress the subject from the first image in the outfit from the second image:",
"string_b": [
"293:331",
0
]
},
"_meta": {
"title": "Concatenate Text"
}
},
"293:336": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": " ",
"string_a": [
"293:335",
0
],
"string_b": "Keep his face, hair, body proportions, pose, and the background exactly the same. The garments must match the clothing exactly in color, fabric texture, and details. Photorealistic fashion photo."
},
"_meta": {
"title": "Concatenate Text"
}
},
"293:337": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"293:336",
0
]
},
"_meta": {
"title": "Preview as Text"
}
}
})
workflow.set_input("267", "image", client.assets.from_url("https://comfy.org/catalog-media/6f8721d3-d594-43c6-9c0f-5dcfa3a9f2a7/bfbc898f-6812-45d2-95fb-5c9696404fb7"))
workflow.set_input("266", "image", client.assets.from_url("https://comfy.org/catalog-media/02c308b6-ea0c-4040-b14a-0819feb9a6a3/5507a16d-9ddd-48cb-8ea9-25e7c3f5082b"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("294"):
output.to_file(output.name)Try an example
About this workflow
Clothes Changer is a virtual try-on workflow that swaps the clothing in a character photo with a reference outfit image. It connects two LoadImage nodes (one for your character, one for the outfit) into a custom Clothes Changer node (a41effc1-fe4c-4b79-a70d-9b7388ef6a23), then saves the result with a SaveImage node. The workflow is compact and direct: LoadImage → Clothes Changer (a41effc1-...) → SaveImage, so you can go from inputs to an output render in a single pass.
Technically, the Clothes Changer node takes the person/character image and the outfit reference, aligns the garment to the subject’s pose, and composites it while preserving facial features, hair, and body structure. Common steps inside this kind of node include detecting clothing regions, pose-aware alignment/warping, and clean blending to avoid artifacts around edges. Because everything runs inside ComfyUI, you can iterate quickly by swapping inputs, adjusting the node’s settings (if exposed in your build), and re-queuing to refine fit, coverage, and output size.
Questions & answers
Use clear, well-lit images between 768–1536 px on the shortest side. Keep both character and outfit images at comparable sizes to help alignment and reduce artifacts.
The Clothes Changer node is designed to preserve identity (face, hair, and body structure) and only replace clothing. Minor blending around edges may occur; better framing and higher-resolution inputs help.
Yes, but results are usually cleaner when the garment is well-separated from the background. Flat-lay images or on-model shots with clear contrast work best. Front-facing garments generally align more reliably.
The SaveImage node writes files to the ComfyUI/output folder. Set the filename prefix in the SaveImage node to keep versions organized.