# 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_image_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"156": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "photo_restoration",
"images": [
"158:154",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"157": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": {
"__value__": [
"",
""
]
},
"image_a": [
"156",
0
],
"image_b": [
"76",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"185": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Restore this old photograph. Remove all scratches, dust, creases, tears, and stains. Repair faded and damaged areas. Enhance sharpness and fine detail while preserving the original faces, expressions, clothing, and background exactly as they are. Do not change the identity of any person, the composition, or add or remove any objects. High-quality photo restoration."
},
"_meta": {
"title": "Restore Prompt"
}
},
"186": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Restore this old photograph of four travelers standing on a rocky shoreline. Remove every crease, fold line, tear, water stain, mildew spot, scratch and speck of dust, and rebuild the missing torn corner so the rocks, grass and sky continue naturally. Repair the faded areas and recover detail in the knitted sweaters, oilcloth coats, boots and the faces. Keep every person's identity, expression, pose and position exactly as they are, and keep the shoreline, the sea spray and the composition unchanged. Colorize it with realistic, period-appropriate colors: weathered skin tones, undyed cream and charcoal wool, dark olive oilcloth, wet slate rocks, grey-green sea grass and a pale overcast sky over grey-blue water. The result should look like a well-preserved color photograph from the era, not a modern image."
},
"_meta": {
"title": "Restore + Colorize Prompt"
}
},
"187": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"185",
0
],
"on_true": [
"186",
0
],
"switch": True
},
"_meta": {
"title": "Enhanced Color Restoration"
}
},
"188": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"187",
0
]
},
"_meta": {
"title": "Final Prompt Preview"
}
},
"158:133": {
"class_type": "ModelSamplingAuraFlow",
"inputs": {
"model": [
"158:145",
0
],
"sampling": "flow",
"shift": 3.1
},
"_meta": {
"title": "ModelSamplingAuraFlow"
}
},
"158:134": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "qwen_image_vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"158:135": {
"class_type": "FluxKontextMultiReferenceLatentMethod",
"inputs": {
"conditioning": [
"158:137",
0
],
"reference_latents_method": "index_timestep_zero"
},
"_meta": {
"title": "Edit Model Reference Method"
}
},
"158:136": {
"class_type": "FluxKontextMultiReferenceLatentMethod",
"inputs": {
"conditioning": [
"158:139",
0
],
"reference_latents_method": "index_timestep_zero"
},
"_meta": {
"title": "Edit Model Reference Method"
}
},
"158:137": {
"class_type": "TextEncodeQwenImageEditPlus",
"inputs": {
"clip": [
"158:146",
0
],
"image1": [
"158:155",
0
],
"prompt": "",
"vae": [
"158:134",
0
]
},
"_meta": {
"title": "Text Encode Qwen Image Edit Plus"
}
},
"158:139": {
"class_type": "TextEncodeQwenImageEditPlus",
"inputs": {
"clip": [
"158:146",
0
],
"image1": [
"158:155",
0
],
"prompt": [
"188",
0
],
"vae": [
"158:134",
0
]
},
"_meta": {
"title": "TextEncodeQwenImageEditPlus (Positive)"
}
},
"158:140": {
"class_type": "CFGNorm",
"inputs": {
"model": [
"158:133",
0
],
"pre_cfg": False,
"strength": 1
},
"_meta": {
"title": "CFGNorm"
}
},
"158:141": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
"model": [
"158:140",
0
],
"strength_model": 1
},
"_meta": {
"title": "Load LoRA"
}
},
"158:142": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 4
},
"_meta": {
"title": "CFG"
}
},
"158:143": {
"class_type": "PrimitiveFloat",
"inputs": {
"value": 1
},
"_meta": {
"title": "CFG"
}
},
"158:144": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"158:155",
0
],
"vae": [
"158:134",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"158:145": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "qwen_image_edit_2511_fp8mixed.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"158:146": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_2.5_vl_7b_fp8_scaled.safetensors",
"device": "default",
"type": "qwen_image"
},
"_meta": {
"title": "Load CLIP"
}
},
"158:147": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"158:140",
0
],
"on_true": [
"158:141",
0
],
"switch": [
"158:150",
0
]
},
"_meta": {
"title": "Switch (Model)"
}
},
"158:148": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 4
},
"_meta": {
"title": "Steps"
}
},
"158:149": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 40
},
"_meta": {
"title": "Steps"
}
},
"158:150": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": True
},
"_meta": {
"title": "Enable 4steps LoRA?"
}
},
"158:151": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"158:142",
0
],
"on_true": [
"158:143",
0
],
"switch": [
"158:150",
0
]
},
"_meta": {
"title": "Switch (CFG)"
}
},
"158:152": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"158:149",
0
],
"on_true": [
"158:148",
0
],
"switch": [
"158:150",
0
]
},
"_meta": {
"title": "Switch (Steps)"
}
},
"158:153": {
"class_type": "KSampler",
"inputs": {
"cfg": [
"158:151",
0
],
"denoise": 1,
"latent_image": [
"158:144",
0
],
"model": [
"158:147",
0
],
"negative": [
"158:135",
0
],
"positive": [
"158:136",
0
],
"sampler_name": "euler",
"scheduler": "simple",
"seed": 179526350171703,
"steps": [
"158:152",
0
]
},
"_meta": {
"title": "KSampler"
}
},
"158:154": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"158:153",
0
],
"vae": [
"158:134",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"158:155": {
"class_type": "FluxKontextImageScale",
"inputs": {
"image": [
"76",
0
]
},
"_meta": {
"title": "FluxKontextImageScale"
}
}
})
workflow.set_input("76", "image", client.assets.from_url("https://comfy.org/catalog-media/36b7be97-9ae9-45b4-a1b5-755305cdca6a/35f22ae6-ca98-43bb-86cf-a4734fc1b43a"))
# 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("156"):
output.to_file(output.name)