Save Image to Remote ⚡
The save node that never touches your own disk
- images
- saved_paths
Know this before you install anything: this node does not save a file. It encodes your image in memory and POSTs it to a receiver app running somewhere else. Nothing lands on the machine running ComfyUI - no output/, no temp file, no spool. If nothing is listening at that URL, the run fails and the image is simply gone.
That's either exactly what you want or completely useless.
When it's the right tool
Stock SaveImage writes to ComfyUI/output/ and refuses to go anywhere else; PreviewImage writes to temp/. So on a headless box, a rented GPU, or a container with a disposable filesystem, "it's saved" means "it's saved there" - and now you go fetch it. This node flips that: the render lands on your workstation or NAS and the render box stays clean. It's the write half of the same pipe the rest of this pack reads from. Don't go looking for docs, though - the README's node list covers the older folder-saving variants; the remote pair lives in the node description and the source.
How it actually works
It's an HTTP POST to <receiver_url>/api/v1/upload, one per image in the batch, as multipart/form-data: a file part plus form fields describing the generation - prefix, model and workflow names, prompts, seed, dimensions, sampler, subfolder, job ids. The receiver writes it and answers with JSON (ok, saved_to, filename, size_bytes). Anything other than a 200 with ok: true raises immediately, quoting the URL and the receiver's own error code. No retries, no spool, no local fallback.
Encoding is Pillow. With format: png, the API prompt and every extra_pnginfo key - the UI's workflow - go into the PNG's text chunks exactly like the stock save, deliberately unscrubbed, so the file drags back onto the canvas and rebuilds the graph. Same caveat as any headless run: drive ComfyUI through the API and there's no UI to serialize, so only the prompt chunk exists.
And there's no authentication in this path at all. No key, no token, no header.
The inputs you'll actually set
images- the wire from your decode or VAE node. Everything else is bookkeeping.receiver_url- defaults tohttp://127.0.0.1:8790, the SSH-tunnel case where the receiver sits at the far end. Otherwise paste the public URL the receiver app shows. It needshttp(s)://host, and give it the origin only - a path is kept, so you'd POST toyourpath/api/v1/upload.filename_prefix- a raw prefix, not the stock template language. Empty gives youimage_00000.png;set_000gives youset_00000000.png. That five-digit index is batch position, from zero.subfolder- where the receiver routes it. The receiver decides.format- stay onpngif you want the workflow inside the file. JPEG and WebP have no PNG text chunks, so the graph isn't in the bytes, though the metadata still crosses the wire as form fields.timeout- 120 seconds per image, not per run.verify_tlsstays on unless the receiver has a self-signed cert.
The rest - the sampler settings, positive_prompt, negative_prompt, model_name, workflow_name, seed, width, height, job_id, generation_id, extra_metadata - is metadata only; empty values are dropped rather than sent as blanks. Leave width/height at 0 and the node fills in the tensor's real dimensions.
The single output is saved_paths - a STRING of the receiver's paths, one per line for a batch. The UI also shows a row per image with size and transfer time.
Install
Manager → search ComfyUI-Get-Random-File → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/ChrisColeTech/ComfyUI-Get-Random-File
Restart. Dependencies are requests (already in any ComfyUI install) and imageio-ffmpeg, used by the video nodes. The console prints [CCTech Suite]: Activated N file nodes on load.
The receiver is the real install question, and it isn't in this repo. Run the author's app, or write the other end yourself: accept the file part and the form fields at /api/v1/upload, reply 200 with {"ok": true, "saved_to": ..., "filename": ..., "size_bytes": ...}.
Common issues
"receiver unreachable." Usually nothing is listening. 127.0.0.1:8790 only works when the receiver is on the same machine - that's what the tunnel is for.
"...refused the save [http.404]." Your URL picked up a path. Scheme, host, port, nothing else.
A fatal save means a lost image. Nothing is spooled, so a failed POST throws the encoded bytes away. Re-queue - the sampler and decode are still cached, so usually only the upload repeats. Randomize your seed and you get a new image instead of a retry.
Don't expose it casually. No auth in the path at all, and the reasoning behind "PSA: Please secure your ComfyUI instance" applies to a receiver behind a public tunnel - an unauthenticated file-write endpoint is exactly what it sounds like.
One subtlety: IS_CHANGED returns not-a-number - the always-rerun trick - so re-queueing genuinely retries the upload.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| receiver_url | STRING | http://127.0.0.1:8790 | — |
| subfolder | STRING | — | |
| filename_prefix | STRING | — | |
| model_name | STRING | — | |
| workflow_name | STRING | — | |
| positive_prompt | STRING | — | |
| negative_prompt | STRING | — | |
| seed | INT | 00–9223372036854776000 | — |
| formatopt | COMBO | 3 options: png, jpeg, webp | |
| jpeg_qualityopt | INT | 921–100 | — |
| webp_qualityopt | INT | 921–100 | — |
| timeoutopt | INT | 1205–3600 | — |
| verify_tlsopt | BOOLEAN | true | — |
| job_idopt | STRING | — | |
| generation_idopt | STRING | — | |
| widthopt | INT | 0 | — |
| heightopt | INT | 0 | — |
| stepsopt | INT | 0 | — |
| cfgopt | FLOAT | 0.00 | — |
| sampleropt | STRING | — | |
| scheduleropt | STRING | — | |
| extra_metadataopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| saved_paths | STRING | — |