After you deploy a ComfyUI project, you can generate images from the WebUI or by making API calls.
Background information
The native ComfyUI API is not optimized for serverless environments. To improve text-to-image API call efficiency, we provide the ComfyUI Serverless API.
The ComfyUI Serverless API consolidates image generation, image upload, status retrieval, and image retrieval—functions that are separate in the native ComfyUI—into a single operation. This enables parallel image generation across multiple instances and accelerates your tasks.
Enable API call mode
Export the workflow API as a JSON file
Before making API calls, build and debug your workflow in the ComfyUI WebUI. Verify that the workflow successfully generates images. After debugging, go to the ComfyUI interface and click . Your browser downloads a JSON file containing the workflow definition.
The JSON file describes how the current workflow operates.
{
"3": {
"inputs": {
"seed": 740511732689542,
"steps": 20,
"cfg": 8,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1,
"model": [
"4",
0
],
"positive": [
"6",
0
],
"negative": [
"7",
0
],
"latent_image": [
"5",
0
]
},
"class_type": "KSampler",
"_meta": {
"title": "K sampler"
}
},
"4": {
"inputs": {
"ckpt_name": "sd-v1-5-inpainting.ckpt"
},
"class_type": "CheckpointLoaderSimple",
"_meta": {
"title": "Load Checkpoint"
}
},
"5": {
"inputs": {
"width": 512,
"height": 512,
"batch_size": 1
},
"class_type": "EmptyLatentImage",
"_meta": {
"title": "Empty Latent Image"
}
},
"6": {
"inputs": {
"text": "beautiful scenery nature glass bottle landscape, , purple galaxy bottle,",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"7": {
"inputs": {
"text": "text, watermark",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"8": {
"inputs": {
"samples": [
"3",
0
],
"vae": [
"4",
2
]
},
"class_type": "VAEDecode",
"_meta": {
"title": "VAE Decoding"
}
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage",
"_meta": {
"title": "Save Image"
}
}
}
Publish the API
After preparing the workflow JSON file, configure an API access endpoint for your ComfyUI function. Switch to the API Call tab and click Publish API.
Modify GPU specifications and elastic policies
When configuring the ComfyUI API operation, set the function’s resource specifications based on your expected workload and performance requirements. Consider the following parameters:
GPU specifications: Select GPU-accelerated instances with different types and configurations to process API call requests. ComfyUI workflows vary significantly in computational complexity and resource consumption. Test your workflow to evaluate processing time and cost across GPU specifications, then select the optimal configuration.
Elastic policy:
Pay-as-you-go mode: This mode uses a pay-as-you-go billing method. You are not charged for compute resources when no requests are active. For sparse invocations, cold starts may occur, which delays the response to the first request.
Express mode: Caches ComfyUI in a provisioned snapshot, incurring a minimal snapshot storage fee. This approach avoids cold starts and significantly improves response speed for infrequent calls. If the number of required instances exceeds the number of provisioned snapshots, on-demand instances may still be launched. In such cases, some requests might experience a cold start.
After publishing the API, the platform automatically generates an API endpoint for external use. Use the API call documentation on the page and the JSON file you exported earlier to construct an API request for your AI image generation service.
Configure image reading and saving
After publishing the API, go to the tab to configure how images are read and saved.
Role permissions: Grant ComfyUI the required permissions. Select a role that has permission to read images from OSS or write images to OSS.
Save generated results to OSS: After you configure the required parameters, this option automatically saves generated images to OSS.
Bucket: The OSS bucket used to store images. If the bucket resides in a different region than ComfyUI, network latency may increase and additional traffic fees may apply. Use a bucket in the same region as ComfyUI.
Path: The path where the image is stored in the OSS bucket.
Link validity period: After the image is saved, a temporary link to access the resource is generated. If this parameter is not configured, the image is saved but no link is generated.
After enabling image saving to OSS in the console, ensure that `output_oss=true` is set in the request query. Otherwise, generated images will not be saved to the OSS bucket.
The following is an example of an API call that automatically saves images:
curl "{your_public_request_address}/api/serverless/run?output_oss=true" -X POST -H "Content-Type: application/json" -d '{your_text-to-image_workflow_JSON}'
API definition
The workflow JSON file exported from ComfyUI can be used directly for ComfyUI Serverless API calls. The API also supports the following features.
In a KSampler node, if `seed` is set to -1, it is automatically replaced with a random number.
The LoadImage node supports the following image sources:
File name: Reads an image from the input directory, such as example.png.
URL: Reads an image from a URL, such as https://example.com/example.png.
OSS: Reads an image from OSS (requires a role with OSS permissions), such as oss://bucket.oss-cn-hangzhou.aliyuncs.com/example.png.
base64: Reads an image from a base64 string, such as iVBORw0KGgoAAAANSUhE.... Note: Using base64 increases the request body size significantly. This may exceed the Function Compute limit for request body length, which is 32 MB for synchronous calls and 128 KB for asynchronous calls.
HTTP image generation
Method |
|
||
Path |
|
||
Request |
|||
Header |
Key |
Description |
|
|
|
||
Query |
Key |
Type |
Description |
|
|
Specifies whether to save the result to OSS. |
|
|
|
Specifies whether to output the result as a base64 string. |
|
|
|
Specifies whether to stream the progress. |
|
Body |
Same as the native ComfyUI API. The key is the node ID and the value is the node information. |
||
Response |
|||
Stream |
Same as the native ComfyUI API WebSocket messages. Each streamed output is a WebSocket message. After each image generation task is complete, a message with the type |
||
Non-Stream Body |
Key |
Type |
Description |
|
|
Fixed as |
|
|
|
The image generation result. |
|
|
|
The prompt_id for this image generation task. It is generated by ComfyUI and can be used to query the history. The data is stored in memory and is destroyed after the instance is recycled. |
|
|
|
A list of the generated images. |
|
|
|
The ID of the node that outputs the image. |
|
|
|
The ordinal number of the current image in the node's output. |
|
|
|
The output image. |
|
|
|
Information included in the native ComfyUI output. |
|
|
|
The file name. |
|
|
|
The type of the output image (the output folder). |
|
|
|
The output subfolder. |
|
|
|
The output directory. |
|
|
|
The output base64 information. |
|
|
|
The base64 string of the current image. Requires |
|
|
|
The output OSS information. |
|
|
|
The OSS region. |
|
|
|
The OSS bucket. |
|
|
|
The name of the output image in OSS. Requires |
|
|
|
The time-to-live (TTL) of the current image in OSS. Requires |
|
WebSocket image generation
This operation follows the same logic as HTTP mode. Input parameters are passed through websocket.send().
Protocol |
WebSocket |
||
Path |
|
||
Request |
|||
Query |
Key |
Type |
Description |
|
|
Specifies whether to save the result to OSS. |
|
|
|
Specifies whether to output the result as a base64 string. |
|
|
|
Specifies whether to stream the progress. |
|
Send Message |
Same as the native ComfyUI API. The key is the node ID and the value is the node information. |
||
Response |
|||
Receive Message |
Same as the native ComfyUI API WebSocket messages. Each streamed output is a WebSocket message. After each image generation task is complete, a message with the type |
||
Get status
Retrieves the status of an image generation task. Because FaaS is stateless, you must configure persistent storage to ensure status information is retained correctly.
Save to a file system: Mount NAS or OSS to the function instance. The file is saved to {mount_directory}/output/serverless_api.
Method |
|
||
Path |
|
||
Request |
|||
Query |
Key |
Type |
Description |
|
|
The task ID. You can obtain it from . |
|
Response |
|||
Body |
Key |
Type |
Description |
|
|
An array of content output in streaming and WebSocket modes. |
|
|
|
The event type. |
|
|
|
The content of the corresponding event. |
|
Invocation methods
Synchronous image generation
If you only need the final image and do not require progress updates, use a synchronous HTTP call.
import requests
import json
# Enter your public request address
endpoint = "https://xxx.xxx.fcapp.run"
def txt2img(prompt):
resp = requests.post(f"{endpoint}/api/serverless/run?output_oss=true", json=prompt)
return resp.json()
with open("./api.json", "r", encoding="utf-8") as f:
result = txt2img(json.loads(f.read()))
images = result["data"]["results"]
for image in images:
# The output will be serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
Streaming image generation
To monitor image generation progress in real time, use a synchronous HTTP call and read the streaming output.
import requests
import json
# Enter your public request address
endpoint = "https://xxx.xxx.fcapp.run"
def txt2img(prompt):
with requests.post(
f"{endpoint}/api/serverless/run?output_oss=true&stream=true",
json=prompt,
stream=True,
) as response:
for line in response.iter_lines():
# Only lines starting with data: are data lines
if line.startswith(b"data: "):
data = json.loads(line[6:])
# As the image generation progresses, the current node status is output
# Some possible lines are as follows
# {'type': 'status', 'data': {'status': {'exec_info': {'queue_remaining': 1}}, 'sid': '200c62b4-111f-4994-a4a4-20a28c944408'}}
# {'type': 'executing', 'data': {'node': '4'}}
# {'type': 'status', 'data': {'status': {'exec_info': {'queue_remaining': 1}}}}
# {'type': 'execution_start', 'data': {'prompt_id': '453484bb-1749-4fe3-9f2c-31664b8c3aec', 'timestamp': 1747821408300}}
# {'type': 'execution_cached', 'data': {'nodes': [], 'prompt_id': '453484bb-1749-4fe3-9f2c-31664b8c3aec', 'timestamp': 1747821408304}}
# {'type': 'executing', 'data': {'node': '4', 'display_node': '4', 'prompt_id': '453484bb-1749-4fe3-9f2c-31664b8c3aec'}}
# {'type': 'progress', 'data': {'value': 1, 'max': 20, 'prompt_id': '453484bb-1749-4fe3-9f2c-31664b8c3aec', 'node': '3'}}
# {'type': 'executing', 'data': {'node': None, 'prompt_id': '453484bb-1749-4fe3-9f2c-31664b8c3aec'}}
# 'type': 'serverless_api', 'data': ... }
print(data)
# The type of the final result is serverless_api
if data["type"] == "serverless_api":
return data
with open("./api.json", "r", encoding="utf-8") as f:
result = txt2img(json.loads(f.read()))
images = result["data"]["results"]
for image in images:
# The output will be serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
Asynchronous image generation
To avoid blocking the calling thread, use the built-in asynchronous invocation feature of Function Compute and poll for the result using the status API. This feature is provided by Function Compute. For more information, see Invoke a function.
from time import sleep
import requests
import json
import uuid
# Enter your public request address
endpoint = "https://xxx.xxx.fcapp.run"
def txt2img(prompt):
task_id = str(uuid.uuid4())
requests.post(
f"{endpoint}/api/serverless/run?output_oss=true",
json=prompt,
headers={"X-Fc-Invocation-Type": "Async", "X-Fc-Trace-Id": task_id},
)
while True:
resp = requests.get(
f"{endpoint}/api/serverless/status?task_id={task_id}",
)
statusList = resp.json()
# All intermediate states of the current image generation task are output as an array
print(statusList)
if len(statusList) > 0:
if statusList[-1]["type"] == "serverless_api":
return statusList[-1]
sleep(1)
with open("./api.json", "r", encoding="utf-8") as f:
result = txt2img(json.loads(f.read()))
images = result["data"]["results"]
for image in images:
# The output will be serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
WebSocket image generation
If you have already integrated the native WebSocket API and use WebSocket to track image generation progress, you can adopt the WebSocket image generation operation to integrate the ComfyUI Serverless API with minimal changes.
import json
import websocket # pip install websocket-client
# Enter your public request address
# Note: Use the ws or wss protocol
endpoint = "wss://xxx.xxx.fcapp.run"
def txt2img(prompt):
result = {}
def on_open(ws):
ws.send(json.dumps(prompt))
def on_message(ws, msg):
# As the image generation progresses, the current node status is output
data = json.loads(msg)
print(data)
if data["type"] == "serverless_api":
nonlocal result
result = data
ws.close()
ws = websocket.WebSocketApp(
f"{endpoint}/api/serverless/ws?output_oss=true",
on_open=on_open,
on_message=on_message,
)
ws.run_forever()
return result
with open("./api.json", "r", encoding="utf-8") as f:
result = txt2img(json.loads(f.read()))
images = result["data"]["results"]
for image in images:
# The output will be serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
View call logs and monitoring
On the page, you can view historical request details and corresponding operational logs. This helps you identify the time consumed by each image generation request and troubleshoot failures.
Instance list
On the page, you can view the list of currently running instances, review logs and monitoring metrics for each instance, and, if needed, log on to an instance to run Shell commands.