comfyanonymous/ComfyUI
comfy_api_nodes/
Built-in nodes that call paid third-party AI APIs from inside ComfyUI workflows. ~40,000 lines, the second-largest package by line count after comfy/. The --disable-api-nodes flag turns the whole thing off.
Why this is its own package
Each provider needs:
- An HTTP client with auth (the user's
api_key_comfy_org) - Pydantic request/response schemas
- File upload (images, videos, audio) and download
- Polling for async jobs (most providers don't return synchronously)
- Error mapping into ComfyUI's exception model
Rather than scattering this across comfy_extras/, the team gave it a dedicated package with shared infrastructure under comfy_api_nodes/util/.
Layout
comfy_api_nodes/
├── __init__.py
├── nodes_<provider>.py # One file per provider — the nodes themselves
├── apis/ # Generated Pydantic models (regenerate via comfy_api/generate_api_stubs.py)
│ ├── __init__.py # 6,155 lines, generated
│ └── schemas/ # Source schemas (input)
└── util/ # Shared HTTP client, conversions, polling
├── __init__.py
├── _helpers.py
├── client.py # 40,695 lines — the API client base
├── common_exceptions.py
├── conversions.py # Image ↔ base64 ↔ URL, video reframe, audio
├── download_helpers.py # Robust downloads with retries
├── upload_helpers.py # Pre-signed URL uploads, multipart
├── request_logger.py # Per-request log lines for debugging
└── validation_utils.pyProviders
There is roughly one nodes_<provider>.py file per integrated service. Sizes vary based on how many endpoints the provider exposes. The largest are video providers because video APIs typically expose many quality/length/style knobs.
| Provider | File | Lines |
|---|---|---|
| Kling | comfy_api_nodes/nodes_kling.py |
3,327 |
| Wan (Comfy Org) | comfy_api_nodes/nodes_wan.py |
2,222 |
| ByteDance | comfy_api_nodes/nodes_bytedance.py |
2,111 |
| Vidu | comfy_api_nodes/nodes_vidu.py |
1,728 |
| Recraft | comfy_api_nodes/nodes_recraft.py |
1,200+ |
| Magnific | comfy_api_nodes/nodes_magnific.py |
1,000+ |
| Gemini | comfy_api_nodes/nodes_gemini.py |
~900 |
| Tripo | comfy_api_nodes/nodes_tripo.py |
~800 |
| ElevenLabs | comfy_api_nodes/nodes_elevenlabs.py |
~800 |
| Stability | comfy_api_nodes/nodes_stability.py |
~700 |
| Meshy | comfy_api_nodes/nodes_meshy.py |
~700 |
| Hunyuan3D (cloud) | comfy_api_nodes/nodes_hunyuan3d.py |
~700 |
| OpenAI | comfy_api_nodes/nodes_openai.py |
~800 |
| Grok | comfy_api_nodes/nodes_grok.py |
~600 |
| Ideogram | comfy_api_nodes/nodes_ideogram.py |
~600 |
| Veo (Google) | comfy_api_nodes/nodes_veo2.py |
~500 |
| Runway | comfy_api_nodes/nodes_runway.py |
~400 |
| BFL (Black Forest) | comfy_api_nodes/nodes_bfl.py |
~500 |
| Topaz | comfy_api_nodes/nodes_topaz.py |
~400 |
| Bria | comfy_api_nodes/nodes_bria.py |
~250 |
| Hitpaw | comfy_api_nodes/nodes_hitpaw.py |
~280 |
| Luma | comfy_api_nodes/nodes_luma.py |
~500 |
| LTXV | comfy_api_nodes/nodes_ltxv.py |
~150 |
| Minimax | comfy_api_nodes/nodes_minimax.py |
~350 |
| Moonvalley | comfy_api_nodes/nodes_moonvalley.py |
~430 |
| Pixverse | comfy_api_nodes/nodes_pixverse.py |
~340 |
| Quiver | comfy_api_nodes/nodes_quiver.py |
~200 |
| Reve | comfy_api_nodes/nodes_reve.py |
~330 |
| Rodin | comfy_api_nodes/nodes_rodin.py |
~370 |
| Sonilo | comfy_api_nodes/nodes_sonilo.py |
~220 |
| Sora | comfy_api_nodes/nodes_sora.py |
~120 |
| Wavespeed | comfy_api_nodes/nodes_wavespeed.py |
~140 |
The full list is whatever files are in comfy_api_nodes/ at HEAD.
How a typical provider node works
sequenceDiagram
participant Node
participant Util as comfy_api_nodes/util/client.py
participant API as Provider HTTPS API
Node->>Util: build request from inputs
Util->>Util: upload local images via upload_helpers
Util->>API: POST /generate
API-->>Util: { job_id }
loop polling
Util->>API: GET /jobs/{job_id}
API-->>Util: { status, progress }
Util-->>Node: set_progress
end
API-->>Util: { status: succeeded, result_url }
Util->>Util: download_helpers.fetch(result_url)
Util-->>Node: tensor / video / 3D meshAuthentication uses the user's Comfy Org API key, threaded through the prompt as a hidden api_key_comfy_org input (see SENSITIVE_EXTRA_DATA_KEYS in execution.py). The client never logs the key; it does log full URL + method + status via request_logger.py.
CLI flag and feature flag
--disable-api-nodes turns this whole package off and prevents the frontend from communicating with the internet for API-node use. The flag is declared in comfy/cli_args.py and consulted in start_comfyui in main.py when initializing nodes.
API nodes also opt into the API_NODE = True flag on the ComfyNodeABC so the frontend can mark them visually.
Generated stubs
comfy_api_nodes/apis/__init__.py is 6,155 lines and entirely generated. It contains Pydantic models for every provider's request/response. Don't edit it by hand — edit comfy_api_nodes/apis/schemas/ and run python comfy_api/generate_api_stubs.py.
Integration points
- Loaded by
nodes.init_extra_nodes(init_api_nodes=not args.disable_api_nodes)inserver.py(called frommain.py). - Imports
comfy_api.latestfor the V3 schema and IO types. - Imports
aiohttp(already a runtime dependency). - Each provider node typically imports its own Pydantic model from
comfy_api_nodes/apis/.
Where to start adding a provider
- Drop schemas under
comfy_api_nodes/apis/schemas/. - Run
python comfy_api/generate_api_stubs.pyto regeneratecomfy_api_nodes/apis/__init__.py. - Add
comfy_api_nodes/nodes_<provider>.pymodeled on a similar existing one (Kling, Veo, Stability are good references). - Use the helpers in
comfy_api_nodes/util/:client.pyfor HTTPS,upload_helpers.pyanddownload_helpers.pyfor blob I/O,conversions.pyfor image/video formats. - Make sure
API_NODE = Trueis set on each node class.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.