Nodes/comfyui-superside-nodes/Superside GPT Image 2.5 Sunburst Edit
ComfyUI Node

Superside GPT Image 2.5 Sunburst Edit

The closed model, with a mask that actually holds

By Superside·Created 3 months ago·Updated 6 days ago· 1
Superside GPT Image 2.5 Sunburst Edit
  • image_1
  • image_2
  • image_3
  • image_4
  • image_5
  • image_6
  • mask_image
  • images
  • info
◄prompt—►
◄api_key►
◄sizematch input + resolution►
◄resolution2K►
◄width1920►
◄height1080►
◄mask_modeoff - edit whole image►
◄invert_maskfalse►
◄qualityhigh►
◄num_images1►
◄output_formatpng►
◄sync_modefalse►
◄backgroundauto►
◄output_compression0►

GPT Image 2.5 Sunburst Edit is a fal.ai wrapper: your prompt and images leave your machine, openai/gpt-image-2.5/sunburst/edit does the work, and the result drops back onto the canvas as a normal IMAGE. There is no local equivalent - you cannot download GPT Image, so this node is the only door to that model from inside a ComfyUI graph.

Why you'd reach for it over the other edit models in this pack: it takes a real mask. The community's read on closed models is that editing is where they win, but most of those endpoints regenerate the whole frame and unmasked regions come back close-but-not-identical - which is exactly why people still keep a masked pass in the pipeline at all. Here you get the thing local inpainting owns and edit models usually don't: untouched pixels outside the mask, from a model you couldn't otherwise run.

How it works

It subclasses the pack's GPT Image 2 Edit node, inheriting the same sizing and masking controls, and adds background and output_compression plus two extra quality tiers. Under the hood the pack builds a fal_client.SyncClient scoped to the single call - key from the api_key widget, never a global env mutation - uploads your IMAGE tensors as PNG, and converts the response back to a tensor. Multi-minute generations go through fal's queue with a bounded client-side timeout rather than one long-held HTTP connection.

Two fields do most of the work. size defaults to match input + resolution: your input's aspect ratio is preserved (a tall portrait stays tall) and scaled to resolution (1K/2K/4K). match input (original) keeps the input's own size, and there are ten fixed ratios plus custom pixels - the only mode where width/height are read, both multiples of 16. The ~8 MP output cap is documented for the GPT Image 2 family, so 4K works out to roughly 3840 px on the long edge at 16:9, less as the ratio gets squarer.

The other field is mask_mode, and getting it wrong is the usual confusion:

  • off - edit whole image - the default. It ignores mask_image entirely. That's deliberate for crop-and-stitch graphs where a separate node does the pasting, and it's why people wire a mask, see no effect, and assume the node is broken.
  • guide model (soft) - the mask is sent to the model so it focuses on the white area, but it may still re-render the rest.
  • lock outside mask (hard) - same, plus the result is composited back only inside the mask. This is standalone inpainting, and the mode this node is actually good at.

Mask convention is WHITE = edit, BLACK = keep; invert_mask flips it (only read when mask_mode isn't off).

Then quality: auto, low, medium, high (the default), xhigh, max. Billing here is per token and, per the node's own description, climbs steeply with quality (text $5/1M in, $10/1M out; image $8/1M in, $30/1M out). Treat xhigh and max as deliberate purchases, not "let's see what it looks like." background (auto/transparent/opaque) needs png or webp for transparency - jpeg falls back to opaque - and output_compression only applies to jpeg and webp; 0 leaves it to the API.

Outputs are images (IMAGE - into SaveImage, PreviewImage, or a stitch node) and info (STRING - a result URL).

Installing it

cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes.git
pip install -r requirements.txt

Install into the same Python environment ComfyUI runs on, then restart - new nodes and widget UI only load on restart. Everything shows up under the Superside category; it's on the registry too, so Manager finds it by pack name. To update: git pull origin main in the repo folder, then restart.

There is no config file and no key in the repo. Paste your key into the node's api_key widget - that's the normal flow, and it's also the access-control gate. The FAL_KEY environment fallback only fires when the widget is blank, and it exists for headless deployments that would otherwise embed a literal key in the workflow JSON. On a shared multi-tenant backend, keep passing the key explicitly per workflow. If both are blank the node fails immediately with a clear error.

Common issues and cost surprises

Cost is invisible until it isn't. Every fal-backed node in this pack paints its price in small green text under the node, with the full note in the tooltip. This endpoint is not priced by fal - it's token-billed, so the pack counts it but refuses to guess, listing it separately:

1 call(s) could not be priced:
  - openai/gpt-image-2.5/sunburst/edit

Add a Superside Fal Cost Report node, wire your last image into after_image so it runs last, and read the real numbers after a run. Once you've read a measured cost off fal's dashboard, you can record it in MANUAL_PRICES in modules/fal_pricing.py.

The wrong-type error on old workflows. If a workflow saved before the pack's show_text.js fix throws "an input value has the wrong type," it's the read-only text display having eaten a widget slot. Set the affected widget back to its default once and re-save. It won't recur.

The rest is the API-wrapper tax. Your images and prompt go to OpenAI via fal; refusals come from the model and there's no local patch for them. These runs take minutes, so don't stack six in a loop. And one caveat about the model: GPT Image 2.5 is barely discussed publicly - "Sunburst" reads as an internal codename - so try it on one image before rebuilding a pipeline around it.

CategorySuperside

Inputs (21)

NameTypeDefaultDescription
promptSTRING—
image_1IMAGE—
api_keySTRING—
image_2optIMAGE—
image_3optIMAGE—
image_4optIMAGE—
image_5optIMAGE—
image_6optIMAGE—
mask_imageoptIMAGE—
sizeoptCOMBOmatch input + resolutionOutput shape. 'match input + resolution' keeps your image's aspect (portrait stays portrait) and scales it to 'resolution' below - just pick 4K for the biggest. 'match input (original)' sends size=auto and lets the model choose - it does NOT guarantee your input's size and can come back far smaller, so use it only when you want the model to decide. Or pick a fixed aspect ratio / 'custom pixels'.
resolutionoptCOMBO2KHow large the output is when 'size' is an aspect ratio. GPT Image 2 caps total size to ~8 MP, so 4K gives ~3840 px on the long edge at 16:9 (true UHD), less for squarer ratios (~2880 at 1:1).
widthoptINT192016–4096Only used when size is 'custom pixels'. Must be a multiple of 16.
heightoptINT108016–4096Only used when size is 'custom pixels'. Must be a multiple of 16.
mask_modeoptCOMBOoff - edit whole imageHow to use mask_image: - 'off - edit whole image': ignore the mask, edit everything. Use this in crop-stitch pipelines where a separate stitch node does the masking (this is how it worked before). - 'guide model (soft)': send the mask to GPT so it focuses edits on the white area (the model may still re-render the rest). - 'lock outside mask (hard)': same, plus paste the result back only inside the mask so everything outside stays pixel-identical to the input. Best for standalone inpainting.
invert_maskoptBOOLEANfalseOnly used when mask_mode is not 'off'. Mask convention is WHITE = edit this area, BLACK = keep. Turn ON if your mask is inverted (the area you want to change is black).
qualityoptCOMBOhigh6 options: auto, low, medium, high, xhigh, max
num_imagesoptINT11–4—
output_formatoptCOMBOpng3 options: png, jpeg, webp
sync_modeoptBOOLEANfalse—
backgroundoptCOMBOautoBackground of the generated image. 'transparent' needs output_format png or webp; with jpeg the model falls back to opaque.
output_compressionoptINT00–100Compression level for jpeg and webp output, 0 to leave it to the API. Ignored for png.

Outputs (2)

NameTypeDescription
imagesIMAGE—
infoSTRING—