Nodes/GPTImageComfyUI/GPT Image Edit Image (Ace Data Cloud)
ComfyUI Node

GPT Image Edit Image (Ace Data Cloud)

It Wants a URL, Not Your Picture

By AceDataCloud·Created 3 days ago·Updated 2 days ago· 0
GPT Image Edit Image (Ace Data Cloud)
    • status
    • task_id
    • media_urls_json
    • first_media_url
    • result_json
    • trace_id
    ◄parameters_json{}►
    ◄model(from JSON/default)►
    ◄image_urls►
    ◄prompt►
    ◄count►
    ◄background►
    ◄input_fidelity►
    ◄output_format►
    ◄output_compression►
    ◄quality►
    ◄size►
    ◄callback_url►

    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.

    CategoryAce Data Cloud/GPT Image

    Inputs (12)

    NameTypeDefaultDescription
    parameters_jsonSTRING{}—
    modelCOMBO(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_urlsSTRING—
    promptSTRING—
    countSTRING—
    backgroundSTRING—
    input_fidelitySTRING—
    output_formatSTRING—
    output_compressionSTRING—
    qualitySTRING—
    sizeSTRING—
    callback_urlSTRING—

    Outputs (6)

    NameTypeDescription
    statusSTRING—
    task_idSTRING—
    media_urls_jsonSTRING—
    first_media_urlSTRING—
    result_jsonSTRING—
    trace_idSTRING—