External Image (ComfyDeploy)
The External node that actually does network I/O
- default_value
- image
External Image (ComfyDeploy) is the interesting member of the ihmily/comfy-deploy "External" family, because it's the only one that does real work in the node itself. The text, int, and float versions are pass-throughs - this one fetches bytes. It's the node that lets an API caller hand your deployed workflow an image: input for img2img, a ControlNet reference, an IPAdapter image, an inpainting mask source.
The two-part system is the same as the rest of the pack - nodes in ComfyUI, plus a self-hosted admin backend (comfy-deploy-admin) that manages and publishes deployed workflows. In the editor you feed this node an image via its default_value and test normally. When a caller's request includes your param_name, the admin injects that value - a URL or a base64 data URL - and the node downloads and decodes it at runtime.
How it works
Unlike the other External nodes, load_image has real branches. Look at nodes/comfydeploy_external_image.py and the logic is:
- Value starts with
http→ fetched withhttpxusing a browser user-agent, 3 retries, a 60-second timeout, following redirects. This is the normal case for an API call. - Value is a base64 data URL (
data:image/png;base64,...) → decoded locally. No network round-trip, which is what you want if the caller's image lives inside their own app. - Anything else → falls back to
default_value.
The fetched image gets EXIF-transposed (so phone photos aren't sideways), converted to RGB, normalized to a 0–1 float tensor, and returned as an IMAGE batch of one. If the fetch fails outright, the node raises a RuntimeError - it will not silently proceed.
Inputs and outputs that matter
- param_name (required, default
"input_image") - the request key. Same story as the rest of the family: this is your API contract, keep it stable. - keep_alpha_channel (required, default off) - the one setting that affects output, not just naming. Leave it off for normal RGB image work; turn it on when you genuinely need transparency, like feeding an RGBA image into an inpainting or background-removal stage.
- default_value (optional, an actual IMAGE) - your local-testing image and the fallback when a call omits the parameter. You can pick it like any image input in the editor.
The output is image (IMAGE) - wire it into LoadImage-style inputs: img2img, ControlNet's reference port, IPAdapter, anything that takes an image.
Installing it
Ships with the pack, so one install gets you all five External nodes:
cd ComfyUI/custom_nodes/
git clone https://github.com/ihmily/comfy-deploy.git
cd comfy-deploy
pip install -r requirements.txt
Or via ComfyUI Manager (search "comfy-deploy", author ihmily). No model files. README gate: pack v1.0.1+ needs ComfyUI 0.3.67+. Then set up the admin backend and point the ComfyDeploy panel at it (endpoint + API key) before deployment works.
Where people get burned
The URL you supply must be reachable from the ComfyUI server, not from your browser. http://localhost:3000/myimage.png on your dev machine is unreachable from a server across the internet - this is the classic "works when I test, fails in production" image-API bug. Either host the image somewhere public (an object store, a signed URL) or pass a base64 data URL instead. And note the URL only gets fetched on the deployed path or when you type it into the widget - the default_value image you set in the editor is what flows through locally.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| param_name | STRING | input_image | — |
| keep_alpha_channel | BOOLEAN | false | — |
| default_valueopt | IMAGE | — | |
| display_nameopt | STRING | — | |
| descriptionopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |