After you deploy a ComfyUI project, you can generate images from the WebUI page or using API calls.
Background information
The native ComfyUI API is not suitable for serverless scenarios. To address this, we provide the ComfyUI Serverless API to streamline text-to-image API calls.
The ComfyUI Serverless API merges the native ComfyUI operations for generating images, uploading images, retrieving status, and retrieving images into a single API operation. This lets you use multiple instances for concurrent image generation, which accelerates your tasks.
Enable API call mode
Export the workflow API as a JSON file
Before you make API calls, build and debug your workflow in the ComfyUI WebUI. Ensure that the workflow can generate images successfully. After debugging, in the ComfyUI interface, click the menu item. Your browser then downloads a JSON file that contains the workflow definition.
This 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": "KSampler"
}
},
"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 Decode"
}
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage",
"_meta": {
"title": "Save Image"
}
}
}
Publish the API
Once the workflow JSON file is ready, configure an API access endpoint for your ComfyUI function by switching to the API Call tab and clicking Publish API.
Modify GPU specifications and elastic policies
When you configure the ComfyUI API operation, set the resource specifications for the function based on the expected call load and performance requirements. Consider the following parameters:
GPU specifications: Select GPU-accelerated instances with different card types and configurations to process API call requests. The computing complexity and resource consumption of ComfyUI workflows vary significantly. We recommend that you test your workflow to evaluate the performance of different GPU specifications based on task processing time and cost. Then, select the optimal configuration.
Elastic policy:
Pay-as-you-go mode: This is a pay-as-you-go billing method. No computing fees are incurred when there are no requests. In sparse invocation scenarios, cold starts may occur, which can slow down the response to the first request.
Express mode: This mode caches ComfyUI in a provisioned snapshot, which incurs only minimal snapshot storage fees. This method effectively avoids cold starts and significantly improves the response speed for low-frequency calls. If the number of required instances exceeds the number of provisioned snapshots, on-demand instances may still be created. In this case, some requests may experience a cold start.
After you publish the API, the platform automatically generates an API address for external calls. You can refer to the API call documentation on the page and use the exported JSON file to construct an API request for your AI image generation service.
Configure image reading and saving
After you publish the API, go to the tab to configure how images are read and saved.
Role permissions: Select a role for ComfyUI that has permissions to read from and write to Object Storage Service (OSS).
Save generated results to OSS: Automatically saves generated images to OSS after you configure the required parameters.
Bucket: The OSS bucket used to store images. We recommend using a bucket in the same region as your ComfyUI deployment to avoid network latency and additional traffic fees.
Path: The path to the image in the OSS bucket.
Link validity period: Specifies a validity period to generate a temporary link for accessing the resource after the image is saved. If you do not specify a validity period, the image is saved, but no link is generated.
After you enable saving images to OSS in the console, make sure to set `output_oss=true` in the request query. This ensures that the generated images are saved to the OSS bucket.
The following is an example of a call that automatically saves an image:
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 ComfyUI Serverless API also adds the following capabilities:
For the KSampler node, if `seed` is -1, it is automatically replaced with a random number.
The LoadImage node supports loading images from the following sources:
Filename: 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, such as oss://bucket.oss-cn-hangzhou.aliyuncs.com/example.png. To perform this operation, you must configure a role with OSS permissions.
base64: Reads an image from a base64 string, such as iVBORw0KGgoAAAANSUhE.... Note that base64 encoding significantly increases the request body size. This may exceed the Function Compute limit on request body size (32 MB for synchronous calls and 128 KB for asynchronous invocations).
HTTP image generation
Method |
|
||
Path |
|
||
Request |
|||
Header |
Key |
Description |
|
|
|
||
Query |
Key |
Type |
Description |
|
|
Specifies whether to output the results to OSS. |
|
|
|
Specifies whether to output the results in base64 format. |
|
|
|
Specifies whether to stream the progress. |
|
Body |
Refer to the native ComfyUI API. The key is the node ID and the value is the node information. |
||
Response |
|||
Stream |
Refer to the native ComfyUI API WebSocket information. Each stream output is a WebSocket message. When image generation is complete, a message with the type |
||
Non-Stream Body |
Key |
Type |
Description |
|
|
Fixed as |
|
|
|
Image generation result. |
|
|
|
The prompt_id for this image generation task. This ID 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. |
|
|
|
Filename. |
|
|
|
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 image file in OSS. Requires |
|
|
|
The time-to-live (TTL) of the image in OSS. Requires |
|
WebSocket image generation
The logic of this operation is the same as that of the HTTP mode. Input parameters are passed using websocket.send().
Protocol |
WebSocket |
||
Path |
|
||
Request |
|||
Query |
Key |
Type |
Description |
|
|
Specifies whether to output the results to OSS. |
|
|
|
Specifies whether to output the results in base64 format. |
|
|
|
Specifies whether to stream the progress. |
|
Send Message |
Refer to the native ComfyUI API. The key is the node ID and the value is the node information. |
||
Response |
|||
Receive Message |
Refer to the native ComfyUI API WebSocket information. Each stream output is a WebSocket message. When image generation is complete, a message with the type |
||
Get status
This operation retrieves the status of an image generation task. Due to the stateless nature of Function as a Service (FaaS), you must configure storage to ensure that status information is correctly persisted.
To save the status 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 get this ID from . |
|
Response |
|||
Body |
Key |
Type |
Description |
|
|
An array of content output in streaming and WebSocket modes. |
|
|
|
Event type. |
|
|
|
The content of the corresponding event. |
|
Invocation methods
Synchronous image generation
If you only need the final image and not the generation progress, you can 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 is serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
Streaming image generation
To receive the image generation progress in real time, you can 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():
# 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
# The following are some possible output lines
# {'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 is serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
Asynchronous image generation
If you do not want the call to be blocked, use the asynchronous invocation feature of Function Compute. Then, poll the Get Status API operation to retrieve the result. The asynchronous invocation feature is provided by Function Compute. For more information, see InvokeFunction.
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 is 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 receive the image generation progress, you can use the WebSocket image generation operation. This lets you use 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 is serverless-api-output/b74f33c0-69ba-4e4b-b584-6700890b7f51.png
print(image["output"]["oss"]["object"])
View call logs and monitoring metrics
On the page, you can view historical request information and the corresponding operational logs. This helps you determine the processing time of an image generation request and troubleshoot errors when a request fails.
Instance list
On the page, you can view the list of currently running instances. You can also view the logs and monitoring metrics for each instance. If necessary, you can log on to an instance to perform Shell operations.
FAQ
What if I cannot find my workflow?
If you have generated an image, find it in the history queue in the menu on the left. Right-click the image and select Load Workflow to restore the workflow.