# 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({
"11": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_main_reference",
"images": [
"228",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"16": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_subject_full_FILENAME"
},
"_meta": {
"title": "Load Subject Image"
}
},
"18": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "{outfit}",
"replace": "",
"string": [
"23",
0
]
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"23": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Generate a high-fashion studio image of the subject from Image 1 and Image 2, wearing the exact outfit from Image 3.\n\nImage 1 and Image 2 define the subject’s identity and body proportions.\nImage 3 defines only the outfit and must match exactly.\n\nFull-body shot.\nSubject facing forward, standing naturally.\nNeutral expression.\n\nClean white studio background.\nHard flash lighting.\n55mm lens look.\nFuji Velvia film aesthetic.\n\nSlightly overexposed.\nStrong visible film grain.\nHighly saturated colors.\n\nDo not change the subject’s identity, clothing, or accessories."
},
"_meta": {
"title": "Prompt Template"
}
},
"26": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_outfit_FILENAME"
},
"_meta": {
"title": "Full Body Outift"
}
},
"226": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_subject_close_FILENAME"
},
"_meta": {
"title": "Load Subject Image"
}
},
"228": {
"class_type": "ByteDanceSeedreamNode",
"inputs": {
"fail_on_partial": True,
"height": 2048,
"image": [
"28:225",
0
],
"max_images": 1,
"model": "seedream 5.0 lite",
"prompt": [
"18",
0
],
"seed": 2000540261,
"sequential_image_generation": "disabled",
"size_preset": "2560x1440 (16:9)",
"watermark": False,
"width": 2048
},
"_meta": {
"title": "ByteDance Seedream 4.5 & 5.0"
}
},
"257": {
"class_type": "ByteDanceSeedreamNode",
"inputs": {
"fail_on_partial": True,
"height": 2048,
"image": [
"28:225",
0
],
"max_images": 1,
"model": "seedream 5.0 lite",
"prompt": [
"260",
0
],
"seed": 1405040888,
"sequential_image_generation": "disabled",
"size_preset": "2560x1440 (16:9)",
"watermark": False,
"width": 2048
},
"_meta": {
"title": "ByteDance Seedream 4.5 & 5.0"
}
},
"258": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_main_reference",
"images": [
"257",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"259": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "High-fashion studio close-up of the subject from Image 1 and Image 2, wearing the exact outfit from Image 3 (visible portion only).\n\nIdentity and facial structure must match Image 1 and 2 exactly.\n\nTight close-up (mid-chest to top of head).\nLow-angle, subject centered.\nLooking slightly past camera, bored expression, subtly raised eyebrows.\n\n\nWhite studio background.\nHard flash.\n55mm lens look.\nFuji Velvia aesthetic.\n\nSlight overexposure, strong film grain, highly saturated colors.\n\nNo changes to identity, clothing, or accessories."
},
"_meta": {
"title": "Prompt Template"
}
},
"260": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "{outfit}",
"replace": "",
"string": [
"259",
0
]
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"274": {
"class_type": "GeminiNanoBanana2",
"inputs": {
"aspect_ratio": "auto",
"model": "Nano Banana 2 (Gemini 3.1 Flash Image)",
"prompt": "",
"resolution": "1K",
"response_modalities": "IMAGE",
"seed": 858333317454308,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests.",
"thinking_level": "MINIMAL"
},
"_meta": {
"title": "Nano Banana 2"
}
},
"28:15": {
"class_type": "ResizeAndPadImage",
"inputs": {
"image": [
"226",
0
],
"interpolation": "area",
"padding_color": "white",
"target_height": [
"28:177",
1
],
"target_width": [
"28:177",
0
]
},
"_meta": {
"title": "Resize And Pad Image"
}
},
"28:177": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"16",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"28:224": {
"class_type": "ResizeAndPadImage",
"inputs": {
"image": [
"26",
0
],
"interpolation": "area",
"padding_color": "white",
"target_height": [
"28:177",
1
],
"target_width": [
"28:177",
0
]
},
"_meta": {
"title": "Resize And Pad Image"
}
},
"28:225": {
"class_type": "ImageBatch",
"inputs": {
"image1": [
"28:5",
0
],
"image2": [
"28:224",
0
]
},
"_meta": {
"title": "Batch Images (DEPRECATED)"
}
},
"28:5": {
"class_type": "ImageBatch",
"inputs": {
"image1": [
"16",
0
],
"image2": [
"28:15",
0
]
},
"_meta": {
"title": "Batch Images (DEPRECATED)"
}
}
})
workflow.set_input("26", "image", client.assets.from_url("https://comfy.org/catalog-media/d0625f61-d16c-4168-ab04-c76ac40a3e6e/466e0ed8-f584-4697-bf8a-10f30c547101"))
workflow.set_input("226", "image", client.assets.from_url("https://comfy.org/catalog-media/982f5e41-1b57-4e48-91da-144f0c7b7646/83a50b7d-3a15-42ea-a3e2-2c709a753672"))
workflow.set_input("16", "image", client.assets.from_url("https://comfy.org/catalog-media/357bf933-c68b-497c-8fe6-a052a9911158/53dc3695-c105-4eb3-ad0b-8af8f9dae3e2"))
# 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("11"):
output.to_file(output.name)
for output in job.get_outputs("258"):
output.to_file(output.name)