← All guides AI Release
RU Subscribe to @ai_release1

How to Run a Local Image Generation Server: ComfyUI, Stable Diffusion, and API Access

Updated: 27.10.2026 · AI Release · @ai_release1
How to Run a Local Image Generation Server: ComfyUI, Stable Diffusion, and API Access

TL;DR

Requirements and setup

Illustration: Requirements and setup
Illustration: Requirements and setup

Pre-flight checklist:

> Note: this guide deliberately quotes no benchmark numbers, VRAM figures, or version pins — those change constantly. Where a value is environment-specific, it is marked *check the documentation*.

If this is your first local model run, the general setup patterns — virtual environments, model folders, run scripts — are described in How to run AI models locally on your PC: a beginner's guide, and the licensing side of choosing a checkpoint is covered in Open-weight AI models: how to run them for free in 2026.

Step 1. Install ComfyUI and a Stable Diffusion checkpoint

What to do: clone the repository, create an isolated Python environment, install PyTorch and the remaining dependencies, then place your checkpoint file where ComfyUI looks for it.

git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
python3 -m venv venv
source venv/bin/activate          # Windows PowerShell: .\venv\Scripts\Activate.ps1

Install PyTorch using the command from the official PyTorch "Get Started" selector for your OS and accelerator (CUDA / ROCm / CPU). The exact flags change per release — *check the documentation*; do not copy a flag set from an old tutorial. Then:

pip install -r requirements.txt
mkdir -p models/checkpoints
cp /path/to/<your-model>.safetensors models/checkpoints/

Why: ComfyUI is a node-graph tool — it composes the generation pipeline visually — while the checkpoint is the actual Stable Diffusion model that produces pixels. A virtual environment keeps ComfyUI's packages from colliding with your system Python, and models/checkpoints is the directory the "Load Checkpoint" node scans.

How to check:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
ls -la models/checkpoints

Expected output: a line such as 2.x.x True (the exact version string will differ — that is fine), and a directory listing containing your <your-model>.safetensors. If torch.cuda.is_available() prints False on a machine with an NVIDIA GPU, you installed a CPU-only build — rerun the PyTorch install with the CUDA command from the selector.

Step 2. Start the server and expose it as an HTTP API

Illustration: Step 2. Start the server and expose it as an HTTP API
Illustration: Step 2. Start the server and expose it as an HTTP API

What to do: launch ComfyUI as a local web server bound to localhost, build one minimal workflow in the browser, export it in API format, and call it with curl.

python main.py --listen 127.0.0.1 --port 8188

Open http://127.0.0.1:8188 in a browser. Build the smallest working graph:

1. Load Checkpoint — select <your-model>.safetensors.

2. CLIP Text Encode — positive prompt, connected to the checkpoint's CLIP output; a second one for the negative prompt.

3. Empty Latent Image — set width/height (start small, e.g. 512×512, so you can iterate).

4. KSampler — connect model, positive, negative, latent.

5. VAE Decode — connect the sampler's LATENT output and the checkpoint's VAE.

6. Save Image — connect the decoded IMAGE.

Press Queue once to confirm the graph renders an image in the UI. Then use Save (API Format) in the menu to write workflow_api.json — this is the machine-readable version of the same graph.

Why: the browser UI and the HTTP API are two front ends for one engine. The API accepts exactly the JSON you just exported, so anything you can build by hand you can also trigger from your own application.

curl -s -X POST http://127.0.0.1:8188/prompt \
  -H "Content-Type: application/json" \
  --data-binary @workflow_api.json

Expected response: a JSON object containing a prompt_id (for example {"prompt_id": "8f0c...", "number": 1, "node_errors": {}}). The field names are stable, but the full schema is version-specific — *check the documentation*.

How to check: take the returned prompt_id and poll the history endpoint:

curl -s http://127.0.0.1:8188/history/<prompt_id>

The response is {} (or empty of outputs) while the job is queued and running, then contains the node outputs once finished. A new PNG appears under ComfyUI/output/.

Minimal Python client

import json, time, urllib.request

BASE = "http://127.0.0.1:8188"

with open("workflow_api.json") as f:
    workflow = json.load(f)

body = json.dumps({"prompt": workflow}).encode()
req = urllib.request.Request(f"{BASE}/prompt", data=body,
                             headers={"Content-Type": "application/json"})
prompt_id = json.loads(urllib.request.urlopen(req).read())["prompt_id"]
print("queued", prompt_id)

while True:
    hist = json.loads(urllib.request.urlopen(f"{BASE}/history/{prompt_id}").read())
    if prompt_id in hist:
        print(json.dumps(hist[prompt_id], indent=2)[:500])
        break
    time.sleep(1)

Always send the object wrapped as {"prompt": ...} — a bare workflow JSON is rejected with a validation error.

EndpointMethodPurpose
`/prompt`POSTQueue a workflow, returns `prompt_id`
`/history/{prompt_id}`GETFetch results once the job finishes
`/view?filename=...`GETDownload a generated image by filename
`/queue`GETInspect pending and running jobs
`/interrupt`POSTStop the currently executing job

Paths and payload fields are the ones documented for the version you installed — *check the documentation* if a call returns 404.

Step 3. Verify end to end and lock the server down

Illustration: Step 3. Verify end to end and lock the server down
Illustration: Step 3. Verify end to end and lock the server down

What to do: run one full generation through the API only (no browser), confirm the file on disk, then restrict access.

python client.py
ls -la output/ | tail -n 5

Why: a browser success only proves the UI works; a scripted success proves your application path works, which is the actual goal.

How to check: the script prints a prompt_id and then a JSON history block, and output/ shows a freshly timestamped .png. Open the file — it must match the prompt's subject, not be a black or noise image. If the folder stays empty while the history shows a completed job, your Save Image node wrote to a different filename prefix — inspect the node's filename_prefix.

For remote access, change the bind address and put the server behind a reverse proxy with authentication:

python main.py --listen 0.0.0.0 --port 8188
python main.py --port 8189          # second instance on another port

ComfyUI ships without user accounts: anyone who reaches the port can queue jobs on your GPU. Whether your build includes any auth option — *check the documentation*; otherwise terminate TLS and basic auth at nginx/Caddy, and never expose port 8188 directly to the internet.

Troubleshooting

Problem. ComfyUI exits immediately with a missing-module error

source venv/bin/activate
pip install -r requirements.txt
python -c "import torch; print(torch.__version__)"

Problem. Generation crashes on the first queue

python main.py --lowvram --port 8188

Problem. The server refuses to start while the UI is still open in another tab

lsof -i :8188          # Windows: netstat -ano | findstr :8188
kill <PID>
python main.py --port 8189

Summary and next steps

You now have ComfyUI running as a local server that accepts workflows over HTTP, so any script or app can queue an image job and collect the result. Next, wrap the /prompt + /history pair in your own service endpoint, add a queue or timeout policy, and keep the GPU port private behind a reverse proxy.

FAQ

Do I need an NVIDIA GPU to run this?

No — ComfyUI runs on CPU as well, but generation is significantly slower. Check the documentation for current supported accelerators before buying hardware.

Where exactly do I put the .safetensors file?

In ComfyUI/models/checkpoints/. After copying, refresh the browser page and the model name appears in the Load Checkpoint dropdown.

Why does my POST to /prompt return a validation error?

You probably sent the raw UI workflow or the file saved by the normal save action. Re-export with Save (API Format) and wrap the object as {"prompt": <workflow>}.

Is the ComfyUI API compatible with the OpenAI images API?

No. It has its own graph-based request format, so existing OpenAI SDK code needs an adapter that translates your prompt into the exported workflow JSON.

🤖 AI summary