Save Image to S3
The end-of-workflow save node that writes to the bucket
- images
- s3_image_paths
SaveImageS3 is this pack's answer to ComfyUI's core SaveImage: you drop it at the end of an image workflow and the PNG ends up in your S3 bucket instead of your local output folder. If the deliverable lives in the cloud, this is the save node you want.
It's the counterpart to LoadImageS3 - that node pulls images out of the bucket and into the graph, this one pushes finished generations back up. Together they turn your bucket into the input/output directory for a ComfyUI install that doesn't need to keep much of anything on disk.
How it works
The behavior intentionally tracks core SaveImage, right down to the filename scheme. Two inputs you'll actually set:
- images - the IMAGE tensor (or batch) from your sampler, VAE decode, or upscaler.
- filename_prefix - the base name (default
Image). Like the core node, it supports%width%and%height%placeholders that get filled in from the actual image dimensions.
On run it does the standard save-image routine, with a cloud twist. It writes each PNG to a temporary file, embeds the workflow's prompt and extra_pnginfo metadata (respecting ComfyUI's --disable-metadata flag, same as core), uploads the file to S3_OUTPUT_DIR in the bucket using the counter-style name Image_00001_.png, then deletes the temporary file. It returns s3_image_paths - a list of the object keys it just wrote.
The counter is computed by listing what's already in the S3 output folder rather than the local disk. That's a deliberate design choice and a nice one: if several machines share a bucket, they share the numbering instead of overwriting each other's files (well, mostly - it's still a check-then-upload, so two runs at the exact same moment can race, but you won't collide in normal use).
One important difference from core SaveImage
There is no local copy after the run. The temp file is deleted the moment the upload finishes, so the bucket is the only place the PNG lives. That's the feature, but it's also the gotcha - if you want local plus cloud, chain a regular SaveImage in before or alongside this node and you'll get both.
Also note it only writes PNG - no JPEG option, so if you're shooting for small files, this isn't the node for that.
Installing and configuring the pack
ComfyS3 installs like any custom node - Manager search for "ComfyS3" (author TemryL), or:
cd ComfyUI/custom_nodes
git clone https://github.com/TemryL/ComfyS3
cd ComfyS3
pip install -r requirements.txt # boto3==1.34.32, python-dotenv==1.0.1
Restart, then create .env in custom_nodes/ComfyS3/:
S3_REGION=us-east-1
S3_ACCESS_KEY=your_access_key
S3_SECRET_KEY=your_secret_key
S3_BUCKET_NAME=your-bucket
S3_INPUT_DIR=input
S3_OUTPUT_DIR=output
S3_ENDPOINT_URL and S3_ADDRESSING_STYLE are optional for S3-compatible storage (MinIO, R2, Backblaze) instead of AWS proper.
Common issues
The S3 client is constructed when the node loads, so a missing or wrong .env gives you ComfyS3 - ERROR - Missing required S3 environment variables. in the console before you've even run anything - fix the config, then restart. Uploads are synchronous boto3, so a long batch of images is a queue of sequential uploads; a big batch on a slow uplink means sitting through it. And those plaintext AWS keys in .env are worth treating like the credentials they are - custom nodes run with full OS access, so keep your ComfyUI off the public internet while they're sitting there.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| filename_prefix | STRING | Image | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| s3_image_paths | STRING | — |