GPT Image Edit Image (Ace Data Cloud)
It Wants a URL, Not Your Picture
- status
- task_id
- media_urls_json
- first_media_url
- result_json
- trace_id
If you open this node expecting a slot to plug a Load Image into, you've just found the thing that trips up everybody: there is no image socket. image_urls is a string. The node ships your reference images to a cloud service, so it needs them addressable over HTTPS, not as a tensor on your GPU.
What it's for
Editing with a closed model. Qwen-Image-Edit and the open edit models have gotten genuinely good, and if you're on a decent card that's still the smarter default - no per-call cost, no upload, no filter you can't argue with. What pulls people here is the specific behaviour the GPT Image and Nano Banana lines are good at: instruction-following on natural-language edits, legible text inside the image, and "keep this person, change everything around them" work that survives several rounds of iteration.
The catch is that both of those are also the models most likely to refuse you. There's nothing to abliterate - the filter lives server-side.
How it goes out and comes back
The node validates against the published Dify tool contract for gpt_image_edit_image, POSTs to the edits endpoint, and submits asynchronously. So expect a task_id and a pending status rather than an image, and go fetch it with GPT Image Retrieve Task. Both image_urls and prompt are genuinely required - the pack refuses to send an edit with no reference image, with a blunt "Reference images are required for editing."
One nice detail in the code: if image_urls starts with data:, it's passed through untouched; otherwise the string is parsed as JSON, or as one URL per line. That means a small edit reference can in principle ride along as a base64 data URI, though a normal hosted URL is what the API is designed for.
The inputs that matter
image_urls is a public HTTPS URL, or a JSON array / newline-separated list of them - the contract allows up to sixteen references on one call. prompt is the instruction. model exposes the same fifteen choices as the generate node (dall-e-2, dall-e-3, gpt-image-1, gpt-image-1.5, gpt-image-2, the gpt-image-2.5-flare / -sunburst / :official variants, nano-banana through nano-banana-pro), and leaving it on (from JSON/default) lets the service default apply. Not every model in that list is an editing model in the source - the list is the service's catalog, not a promise per entry.
The one setting worth learning is input_fidelity, which takes high or low. High is what keeps the subject's actual face and details rather than a plausible resynthesis of them; low is cheaper and looser. If your edit keeps drifting away from the original, that field is your first stop, not your prompt.
Then the usual suspects: count maps to the API's n and multiplies the cost, size is auto or WIDTHxHEIGHT, background is transparent/opaque/auto, output_format is png/jpeg/webp with output_compression for the lossy formats, and quality takes auto/low/medium/high (standard and hd are also accepted, inherited from the older API shape). callback_url exists if you want a webhook - most people don't. parameters_json takes the same fields as a JSON object, and any non-empty widget overrides its JSON twin.
Outputs are identical to the generate node: status, task_id, media_urls_json, first_media_url, result_json, trace_id. first_media_url into GPT Image Load Image gets you an IMAGE you can upscale, inpaint, or save.
The workflow trick worth knowing
Because the retrieve nodes and this one both speak STRING, you can chain a generation into an edit without ever touching the filesystem. Run a generate, take its media_urls_json (or first_media_url), right-click the image_urls widget and convert it to an input, then wire the URL in. That's the intended pattern for iterative work: generate, load, edit, load again.
Install
Manager → search GPT Image → publisher acedatacloud, package GPT Image by Ace Data Cloud. If it isn't listed, the manual route is trivial:
cd ComfyUI/custom_nodes
git clone https://github.com/AceDataCloud/GPTImageComfyUI
python -m pip install -r GPTImageComfyUI/requirements.txt
Only requests and jsonschema. Then set ACEDATACLOUD_API_KEY (or ACEDATACLOUD_API_TOKEN) in the environment of the process running ComfyUI and restart - a key exported into some other shell is the classic reason a fresh install reports no credential at all.
Where people get burned
The reference-image problem is the real one. There is no uploader in this pack - media only flows out, and the loader only accepts URLs from Ace's own CDN. So a local file on your drive is not directly usable here; you need it hosted somewhere HTTPS-reachable, or a data URI. People reasonably assume otherwise because every other edit node in the ecosystem takes an IMAGE.
Second: these are paid submits that are never retried after a connection drop. If the request went through and the response didn't, resubmitting pays twice. Retrieve the task by its ID instead.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| parameters_json | STRING | {} | — |
| model | COMBO | (from JSON/default) | 16 options: (from JSON/default), dall-e-2, dall-e-3, gpt-image-1, gpt-image-1.5, gpt-image-2, +10 |
| image_urls | STRING | — | |
| prompt | STRING | — | |
| count | STRING | — | |
| background | STRING | — | |
| input_fidelity | STRING | — | |
| output_format | STRING | — | |
| output_compression | STRING | — | |
| quality | STRING | — | |
| size | STRING | — | |
| callback_url | STRING | — |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| status | STRING | — |
| task_id | STRING | — |
| media_urls_json | STRING | — |
| first_media_url | STRING | — |
| result_json | STRING | — |
| trace_id | STRING | — |