GCP Storage Upload
Upload ComfyUI renders straight to a Google Cloud bucket — no API gymnastics
- images
GCP Storage Upload is the last node in your workflow, and it knows it. You feed it an image tensor - usually straight out of VAE Decode - and it does two things: saves the PNG to your local ComfyUI/outputs folder exactly like the built-in Save Image node, then pushes that same file up to a bucket in Google Cloud Storage. It's a terminal node: no outputs, nothing wires out of it. It's the end of the line, on purpose.
Why would you want that? Because the moment you're generating on a headless box or an unattended batch pipeline, "the image exists somewhere on this disk" stops being a useful outcome. The real win is having the render land in a bucket that your team, your static site, or your downstream automation can read without SSH-ing into the box. If that's your situation, this is the lightest path I've seen to it - no API wrapper, no HTTP requests, just a service-account JSON file and one dependency.
How it works
Mechanically it's about fifty lines. You give it the path to a GCP service-account key file, and the node sets that as the GOOGLE_APPLICATION_CREDENTIALS environment variable, authenticates a storage.Client() with it, and does a blob.upload_from_filename() on your freshly saved PNG. The bucket object path it writes to is {bucket_folder_prefix}/{file_name}.png.
One thing to know going in: the README tells you to set up a config.json with your service-account path in it. Don't bother - the shipped code doesn't read any config file. The gcp_service_json field on the node itself is what actually matters. Classic case of a README rotting while the code moved on; trust the node, not the doc.
The inputs that matter
Five inputs, and honestly only two of them need your attention:
- images - the IMAGE tensor, typically from VAE Decode or any Load Image node.
- gcp_service_json - a path to your service-account JSON key file, not the key string itself. This is the one that trips people up.
- bucket_name - the name of the GCS bucket you're uploading into. It has to already exist.
- bucket_folder_prefix - optional folder inside the bucket. Leave it empty to drop files at the root.
- file_name - no extension needed;
.pnggets appended for you. Defaults tofile, which you almost certainly want to change.
Installing it
Clone it into your custom nodes directory and restart ComfyUI:
cd ComfyUI/custom_nodes
git clone https://github.com/Fantaxico/ComfyUI-GCP-Storage.git
The only real dependency is google-cloud-storage. The pack tries to auto-install it on first load using pip.main(), which was removed from pip in version 23 - so on a modern setup that shim just crashes and you'll get an import error. Beat it to the punch and install it yourself into ComfyUI's Python environment:
pip install google-cloud-storage
Where people get burned
- Permission errors (403). The service account needs at least
storage.objectCreatoron the bucket, and the bucket must exist. A 403 is almost never a node bug - it's auth scope. - FileNotFoundError on upload. If a file with the same
file_namealready sits in your outputs folder, ComfyUI's built-in save path appends a counter to the local file (file_00001_.png) while the upload still points atfile.png, which doesn't exist. Use fresh names per run. - Silent overwrites. No timestamp is added anywhere, so rerunning with the same name clobbers the same blob. Bake a unique value into
file_nameif you want history. - It's a terminal node.
is_output_nodeis true andRETURN_TYPESis empty - don't hunt for an output to wire into something else.
This node does exactly one thing and stays out of your way, which is the appeal. If you need progress bars, retries, and a dozen cloud providers, the heavier comfyui-save-file-extended pack covers S3, Drive, and GCS - but for "save it locally and shove a copy into my GCP bucket," this is the one I'd reach for. And since custom nodes run arbitrary code with full OS access (ComfyUI's biggest structural hazard), a pack this small is easy to skim yourself before installing - which I'd recommend out of habit, not suspicion.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| file_name | STRING | file | — |
| bucket_name | STRING | bucket | — |
| bucket_folder_prefix | STRING | — | |
| gcp_service_json | STRING | path | — |
Outputs (0)
No outputs