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

> AI Release · @ai_release1 · https://ai-release.org/guides/kak-zapustit-lokalnyy-server-generatsii-izobrazheniy-co_en.html

## TL;DR
- Time to complete: about 60 minutes of hands-on work (model download time depends on file size and your connection).
- Difficulty: Intermediate.
- You will need: Python 3 (check the version ComfyUI's docs list as supported), `git`, `curl`, ComfyUI, one Stable Diffusion checkpoint in `.safetensors` format, and either an NVIDIA GPU with current drivers or a CPU-only fallback.

## Requirements and setup
![Illustration: Requirements and setup](https://ai-release.org/guides/img/kak-zapustit-lokalnyy-server-generatsii-izobrazheniy-co-en-1.jpg?v=1793090783)


- **OS:** Linux or macOS (bash blocks below) or Windows 10/11 (PowerShell blocks). Paths in examples are Linux/macOS; on Windows replace `/` with `\`.
- **Python:** run `python3 --version`. ComfyUI documents which Python versions it supports — check the docs for the current requirement instead of guessing.
- **Git:** `git --version`.
- **curl:** `curl --version` (used to test the HTTP API).
- **GPU:** an NVIDIA card with an up-to-date driver makes generation fast; ComfyUI also runs on CPU, but expect it to be slow — confirm current hardware requirements in the docs.
- **Disk space:** checkpoint files are multi-gigabyte. Check the size shown on the model's download page before you start.
- **Network:** the machine must be able to reach GitHub and the PyTorch package index during installation.

Pre-flight checklist:

- [ ] `python3 --version` prints a version
- [ ] `git --version` prints a version
- [ ] At least the free space equal to your checkpoint size is available
- [ ] You have a `.safetensors` checkpoint file on disk (or a download link)

> 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](https://ai-release.org/guides/kak-zapustit-ii-model-lokalno-na-svoem-kompyutere-gayd.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide), and the licensing side of choosing a checkpoint is covered in [Open-weight AI models: how to run them for free in 2026](https://ai-release.org/guides/kakie-ii-modeli-imeyut-otkrytye-vesa-i-kak-ih-zapustit.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide).

## 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.

```bash
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:

```bash
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:**

```bash
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](https://ai-release.org/guides/img/kak-zapustit-lokalnyy-server-generatsii-izobrazheniy-co-en-2.jpg?v=1793090788)


**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`.

```bash
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.

```bash
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:

```bash
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

```python
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.

| Endpoint | Method | Purpose |
|---|---|---|
| `/prompt` | POST | Queue a workflow, returns `prompt_id` |
| `/history/{prompt_id}` | GET | Fetch results once the job finishes |
| `/view?filename=...` | GET | Download a generated image by filename |
| `/queue` | GET | Inspect pending and running jobs |
| `/interrupt` | POST | Stop 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](https://ai-release.org/guides/img/kak-zapustit-lokalnyy-server-generatsii-izobrazheniy-co-en-3.jpg?v=1793090796)


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

```bash
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:

```bash
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**
- Error: `ModuleNotFoundError: No module named 'torch'`
- Cause: the virtual environment is not active, or PyTorch was installed into the system interpreter while ComfyUI runs from `venv`.
- Solution: activate the environment and reinstall:
```bash
source venv/bin/activate
pip install -r requirements.txt
python -c "import torch; print(torch.__version__)"
```

**Problem. Generation crashes on the first queue**
- Error: `RuntimeError: CUDA out of memory. Tried to allocate ... MiB`
- Cause: the requested resolution, batch size, or model precision exceeds available VRAM.
- Solution: lower the **Empty Latent Image** width/height, keep batch size at 1, and restart with lower-memory flags:
```bash
python main.py --lowvram --port 8188
```

**Problem. The server refuses to start while the UI is still open in another tab**
- Error: `OSError: [Errno 98] Address already in use`
- Cause: an older ComfyUI process still holds port 8188.
- Solution: find and stop it, or start on a different port:
```bash
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.
