S3 Image Upload (Inline Credentials)
Upload your ComfyUI output straight to S3 — keys go right in the node
- images
- s3_urls
- upload_status
- uploaded_count
S3 Image Upload is the node that gets your finished image off the local machine and into a bucket without a single environment variable. You type your access key, your secret, and your bucket name into the node's own fields, hit run, and the image is in S3 by the time the graph finishes. No ~/.aws file, no IAM role to hunt for, no CLI setup - if the keys work in the AWS console, they work here.
That "inline credentials" design is the whole point of this pack, and it's genuinely aimed at a specific pain: serverless and ephemeral ComfyUI deployments (Modal, RunPod serverless, a Docker container that gets recycled) where you can't reliably bake credentials into the environment. A pack that reads AWS_ACCESS_KEY_ID from env vars is a non-starter there; this one carries everything in the node.
How it works
The node takes your IMAGE tensor, converts it to RGB, and saves it as a WebP file (quality 100, lossless off) to a temp file. Then it builds a boto3 client with the credentials you provided - no default credential chain involved - and uploads. Filenames are dead simple: filename_prefix.webp, or prefix_1.webp, prefix_2.webp if you feed it a batch. The extension is always .webp, no matter what your prefix says. It returns the public URL for each upload.
It's smart about S3-compatible services in a way that saves you real pain. For plain AWS it constructs https://<bucket>.s3.amazonaws.com/<key>. For Supabase it switches to path-style addressing and builds an /object/public/<bucket>/<key> URL, because that's what Supabase's S3 gateway actually serves. Anything else - Cloudflare R2, MinIO, DigitalOcean Spaces - gets a path-style <endpoint>/<bucket>/<key> URL.
The inputs that matter
- images - the
IMAGEoutput from your VAE decode (or anything downstream of it). - bucket_name, access_key_id, secret_access_key, region - paste them in. Region defaults to
us-east-1; change it to your bucket's real region. - endpoint_url - leave empty for AWS. For Supabase use
https://<your-project>.supabase.co/storage/v1/s3, and for R2/MinIO/Spaces use their endpoint. - folder_path (default
uploads) - the "folder" prefix inside the bucket.
Outputs are s3_urls (a list), upload_status, and uploaded_count. The status string and count are your tripwire: on any failure you get uploaded_count of 0 and a status that says what went wrong, instead of a thrown error killing your whole run.
Install
ComfyUI Manager is the easy path - search for s3_serverless_inline_storage_utils and install. Or clone it yourself:
cd ComfyUI/custom_nodes
git clone https://github.com/udayjain26/s3_serverless_inline_storage_utils
Restart ComfyUI and you'll find the nodes under S3 Serverless Storage. No model downloads - this pack is pure code. Manager installs the pip deps (boto3, botocore, pillow, requests) automatically; if you cloned by hand and imports fail, run pip install boto3 botocore pillow requests yourself.
Troubleshooting
The failure messages come back through upload_status, so check that first. "Bucket does not exist" or "Access denied" mean exactly what they say - check the bucket name and that your IAM user has s3:PutObject on it. Signed-URL note: the URL this node builds is not itself signed, so for a private bucket the returned URL won't open in a browser - that's expected; it's for other services that can reach the bucket. Two timeouts are baked in at 60 seconds each, with adaptive retries, so transient network blips usually sort themselves out.
One security warning worth taking seriously: a ComfyUI workflow you save as a PNG carries the whole node graph embedded in the image. That means your access key and secret travel inside any PNG you share that contains this node. Clear the credential fields before you drag your workflow into a Discord post - the README says it, and it's the one habit you actually need.
If your uploads keep failing only on big batches, it's usually a bucket policy or a CORS thing on the storage side, not this node. Verify with a single image first.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Images to upload to S3 | |
| filename_prefix | STRING | comfy_image | Prefix for uploaded filenames |
| bucket_name | STRING | S3 bucket name | |
| access_key_id | STRING | AWS Access Key ID | |
| secret_access_key | STRING | AWS Secret Access Key | |
| region | STRING | us-east-1 | AWS region |
| endpoint_urlopt | STRING | Custom S3 endpoint URL (for S3-compatible services like Supabase) | |
| folder_pathopt | STRING | uploads | Folder path within bucket |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| s3_urls | STRING | — |
| upload_status | STRING | — |
| uploaded_count | INT | — |