Head Swap · Image Editing
When the hair has to come with the face
- image_url
- reference_image_url
- images
- task id
Face swap vs head swap: pick right and save ten minutes
Face Swap transfers features. Head Swap replaces the entire head - hairstyle, hair colour, head shape, silhouette - while keeping the body, outfit, pose and background of the target image. Same price, $0.013 per image, completely different result, and mixing them up is the single most common mistake with this pair.
The rule of thumb: if the target photo has hair that doesn't belong to the new identity, a face swap gives you a stranger wearing someone else's haircut. That's Head Swap's job. It's the more aggressive edit, and on the right photo it's dramatically more convincing.
How it works
Two image sockets, one output. The node uploads your target and reference, calls spicyapi/head-swap-v1/edit, and returns the composite as a ComfyUI IMAGE with a task id beside it. No prompt - the reference photo is the instruction, which cuts both ways: nothing to tune, and nothing to fix a bad reference with.
Locally, the equivalent job would be an identity pipeline plus manual compositing around the hairline; this is one call. It's the same ArcFace-family identity machinery that IP-Adapter FaceID, InstantID, PuLID and ReActor all share, wrapped so you never see it.
Inputs and outputs
image_url (IMAGE) - the target. The head of the person in this image gets replaced. Body, pose, clothes and background survive.
reference_image_url (IMAGE) - the reference head. The whole head, hair included, is transferred onto the target. Because it's the whole head, this socket is less forgiving than a face reference: a reference shot with a flat, frontal face and clean hair reads best, and a reference with a strong 3/4 turn or hair blown about by wind gives the model more to guess.
seed - fixed by default, with the standard control after generate widget. Same seed and settings, same result; randomize for variation - at which point the run is billed again.
Outputs: images (IMAGE) and task id (STRING). That's the whole node - three fields, two outputs, one cent and change.
Install
Manager → search SpicyAPI, or:
cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapi
Restart, and that's genuinely it: no pip install, no checkpoint, no GPU. The pack declares zero dependencies and runs everything on SpicyAPI's servers, so a laptop works. It needs Python 3.10+ and a ComfyUI with the V3 node API. Key goes in Settings > SpicyAPI (or SPICY_API_KEY for a headless box), then restart once so the node list comes from your account, and set Max cost per run while you're there.
When it goes wrong
- Collar and neckline seams. The most common artifact: the head lands, the neck junction looks invented. Tight collars and high necks hide it; deep necklines don't.
- Reference and target lighting mismatch. There's no skin-tone matching on this node - that's Face Swap Plus's addition - so a blue-hour reference on a tungsten-lit target reads wrong. Match the light or accept the edit.
- Strong poses. Chin down, head turned far, or hair covering the face in the target: the model has to invent, and invented hair looks invented.
- Two people in the target. No mapping field here. Crop to one person, or use Face Swap v1 with
face_mapping. No SpicyAPI key is set- Settings, not the node. Your key never lands in a workflow file or in an image's metadata, so sharing a graph is safe.- Consent and likeness. Swapping a real person's head onto someone else is the sharpest version of an already-sharp ethics question, and the endpoint won't stop you. Don't be the reason this gets nerfed.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image_url | IMAGE | Target image. The head of the person in this image is the one that gets replaced. | |
| reference_image_url | IMAGE | Reference head image. The whole head, including hair and head shape, is transferred onto the target. | |
| seed | INT | 00–2147483647 | Same seed and settings, same result. Set 'control after generate' to randomize to get a new result on every run; every run is billed. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| task id | STRING | The SpicyAPI task id, for the console logs or support. |