Face Swap
The best instant AI face swap technology for photos.
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({
"76": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_base_image_FILENAME"
},
"_meta": {
"title": "Load Target Image"
}
},
"81": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_head_image_FILENAME"
},
"_meta": {
"title": "Load Source Image"
}
},
"190": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": {
"__value__": [
"",
""
]
},
"image_a": [
"204",
0
],
"image_b": [
"199:120",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"204": {
"class_type": "SaveImageAdvanced",
"inputs": {
"filename_prefix": "face_swap",
"format": "png",
"format.bit_depth": "8-bit",
"format.input_color_space": "sRGB",
"images": [
"199:131",
0
]
},
"_meta": {
"title": "Save Image (Advanced)"
}
},
"205": {
"class_type": "SaveImageAdvanced",
"inputs": {
"filename_prefix": "face_swap_stitched",
"format": "png",
"format.bit_depth": "8-bit",
"format.input_color_space": "sRGB",
"images": [
"199:177",
0
]
},
"_meta": {
"title": "Save Image (Advanced)"
}
},
"199:109": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"199:123",
0
],
"latent_image": [
"199:113",
0
],
"noise": [
"199:110",
0
],
"sampler": [
"199:125",
0
],
"sigmas": [
"199:122",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"199:110": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 788122026421577
},
"_meta": {
"title": "RandomNoise"
}
},
"199:111": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "flux2-vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"199:112": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"199:120",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"199:113": {
"class_type": "EmptyFlux2LatentImage",
"inputs": {
"batch_size": 1,
"height": [
"199:112",
1
],
"width": [
"199:112",
0
]
},
"_meta": {
"title": "Empty Flux 2 Latent"
}
},
"199:114:179": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"199:116:180",
0
],
"latent": [
"199:114:78",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"199:114:77": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"199:116:182",
0
],
"latent": [
"199:114:78",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"199:114:78": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"199:121",
0
],
"vae": [
"199:111",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"199:115": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_3_8b_fp8mixed.safetensors",
"device": "default",
"type": "flux2"
},
"_meta": {
"title": "Load CLIP"
}
},
"199:116:180": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"199:119",
0
],
"latent": [
"199:116:181",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"199:116:181": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"199:120",
0
],
"vae": [
"199:111",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"199:116:182": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"199:117",
0
],
"latent": [
"199:116:181",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"199:117": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"199:115",
0
],
"text": [
"199:198",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"199:118": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "flux-2-klein-9b.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"199:119": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"199:115",
0
],
"text": "bad quality, noise, blurry, worst quality, low resolution, blur, distortion, unnatural blending, cartoon, illustration, painting"
},
"_meta": {
"title": "CLIP Text Encode ( Negative Prompt)"
}
},
"199:120": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"76",
0
],
"resize_type": "scale total pixels",
"resize_type.megapixels": 1,
"scale_method": "lanczos"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"199:121": {
"class_type": "ResizeImageMaskNode",
"inputs": {
"input": [
"81",
0
],
"resize_type": "scale total pixels",
"resize_type.megapixels": 1,
"scale_method": "lanczos"
},
"_meta": {
"title": "Resize Image/Mask"
}
},
"199:122": {
"class_type": "Flux2Scheduler",
"inputs": {
"height": [
"199:112",
1
],
"steps": 4,
"width": [
"199:112",
0
]
},
"_meta": {
"title": "Flux2Scheduler"
}
},
"199:123": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"199:133",
0
],
"negative": [
"199:114:179",
0
],
"positive": [
"199:114:77",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"199:125": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "lcm"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"199:131": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"199:109",
0
],
"vae": [
"199:111",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"199:133": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "Alissonerdx__BFS-Best-Face-Swap__bfs_head_v1_flux-klein_9b_step3750_rank64.safetensors",
"model": [
"199:118",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
},
"199:171": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": "",
"string_a": [
"199:197",
0
],
"string_b": [
"199:184",
0
]
},
"_meta": {
"title": "Concatenate Prompt"
}
},
"199:176": {
"class_type": "ImageConcanate",
"inputs": {
"direction": "down",
"image1": [
"199:120",
0
],
"image2": [
"199:121",
0
],
"match_image_size": True
},
"_meta": {
"title": "ImageConcanate"
}
},
"199:177": {
"class_type": "ImageConcanate",
"inputs": {
"direction": "right",
"image1": [
"199:176",
0
],
"image2": [
"199:131",
0
],
"match_image_size": True
},
"_meta": {
"title": "ImageConcanate"
}
},
"199:184": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"199:185",
0
],
"image": [
"199:120",
0
],
"max_length": 256,
"mtp": "auto",
"prompt": "Describe the facial expression. Do not mention facial details such as freckles or unique marks. Do not output <think> tags.\n\nAn example output is as follows:\n<example>\nKey features include:\n- A wide, open-mouthed grin with their tongue sticking out playfully.\n- One eye is winking (the right eye), adding to the mischievous or fun vibe.\n- Their lips are parted in an exaggerated smile that complements the tongue-out gesture.\n- The overall look conveys confidence, joy, and a sense of youthful rebellion — perfectly matching the vibrant, colorful aesthetic they’re presenting.\n</<example>",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 1,
"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 Text"
}
},
"199:185": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3.5_9b_bf16.safetensors",
"device": "default",
"type": "qwen_image"
},
"_meta": {
"title": "Load CLIP"
}
},
"199:195": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"199:197",
0
],
"on_true": [
"199:171",
0
],
"switch": True
},
"_meta": {
"title": "If/Else Switch"
}
},
"199:197": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "head_swap: start with Picture 1 as the base image, keeping its lighting, environment, and background. remove the head from Picture 1 completely and replace it with the head from Picture 2, strictly preserving the hair, eye color, nose structure of Picture 2. copy the direction of the eye, head rotation, micro expressions from Picture 1, high quality, sharp details, 4k\n"
},
"_meta": {
"title": "Prompt Base"
}
},
"199:198": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"199:195",
0
]
},
"_meta": {
"title": "Preview as Text"
}
}
})
workflow.set_input("76", "image", client.assets.from_url("https://comfy.org/catalog-media/8fe73d3d-d1b4-441f-868f-de7c39283e4b/e7eb0cc0-e6b4-435e-be2f-9b834c6d4fb9"))
workflow.set_input("81", "image", client.assets.from_url("https://comfy.org/catalog-media/24509314-ef4a-4dee-af38-c8602e8f38dc/6b898242-c7e9-4f34-9ac3-b0e9abd51ff2"))
# 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("204"):
output.to_file(output.name)
for output in job.get_outputs("205"):
output.to_file(output.name)Try an example
About this workflow
This ComfyUI workflow performs fast, high-quality face swaps on photos using a minimal, easy-to-tune graph. Two LoadImage nodes bring in your source face (the identity you want to transfer) and the target photo. A custom face-swap processor (node ID: 217f3726-59bc-4170-9ab1-c622bb578338) detects and aligns faces in the target, transfers the source identity onto the target while preserving expression, pose, and lighting, and outputs a composited image. An ImageCompare node lets you visually verify results against the original for quick A/B checks, and SaveImageAdvanced handles clean, repeatable exports.
Technically, the face-swap node encapsulates the core pipeline—face detection, alignment/warping, identity transfer, and blending—so you don’t need to manage separate detection or masking nodes. This makes the workflow compact and robust: you load images, optionally tweak the swap node’s settings (such as which detected face to replace or blend strength, depending on the implementation), preview with ImageCompare, and then save your output with consistent naming and format via SaveImageAdvanced.
It’s particularly useful when you need reliable swaps from solid input photos without building a large, complex graph.
Questions & answers
Use sharp, well-lit images with a clear, unobstructed face. Front-facing or slight three-quarter angles work best. Heavy occlusions (hands, hair, masks), extreme profiles, or motion blur can degrade results.
Open the face-swap node (217f3726-59bc-4170-9ab1-c622bb578338). If it provides a face selection control, choose the index/face you want to replace. If not, crop the target image around the intended face and rerun.
Large lighting or color differences between source and target can show in the blend. Try a source photo matched in lighting and tone, or preprocess with basic color/contrast adjustments. Subtle tweaks to the swap node’s blend/feather (if available) can also help.
No. The workflow generates a new, swapped image. SaveImageAdvanced lets you export non-destructively with your chosen format, quality, and filename pattern.