OpenRouter Image Understand
One API key, every vision model — this node shops for you
- image
- image1
- image2
- image3
- image4
- history
- text
- history
- payload
OpenRouter's whole pitch is "stop making accounts." One API key, one billing relationship, and you can call Claude, GPT, Gemini, and a hundred other models through the same endpoint - swap the model name, keep everything else. Yogurt OpenRouter Image Understand is that idea as a ComfyUI node: feed it an image (or five), tell it what to look at, and it returns the model's verdict as text. If you do any captioning, tagging, or "describe this reference image so I can prompt from it" work, this is the node that makes it a one-block step instead of a Python detour.
How it works
The node takes your image tensors, encodes them to base64, and sends a standard multimodal chat request to OpenRouter with the vision model you pick. It's a client, not a local model - no weights, no VRAM, just an HTTP call, which is exactly why it's useful in the middle of a generation graph: you can caption a candidate image and feed the caption straight into a prompt-building node in the same run.
The default model_name is anthropic/claude-3.5-sonnet, which is fine, but the point of OpenRouter is that this field is a menu. Want cheap batch captioning? Point it at a fast flash-tier model. Need meticulous detail? Claude or a strong Gemini variant. The node's payload output also gives you the raw response object, so you can inspect exactly what the API sent back instead of guessing.
Inputs worth knowing
- api_key - paste an OpenRouter key (get one at openrouter.ai/keys), or leave it blank if you've set up the config file /
OPENROUTER_API_KEYenv var. The README's priority order is node field, thenapi_key.json, then env var. - model_name - OpenRouter model IDs are slash-qualified (
provider/model). Anything with vision support works. - image, image1, image2, image3, image4 - up to five images, which is more than most standalone vision nodes give you. Multi-image input is where this node actually shines: hand it a character sheet of references and ask for a single consistent description, or a before/after pair and ask what changed.
- system_prompt and prompt - same split as everywhere: style vs. request. The system prompt is where you'd say "you are an expert image analyst."
- temperature - default 1; lower it for deterministic tagging.
- max_tokens - default 8192, which is plenty for a description but worth capping if you're doing thousands of calls.
There's also infrastructure_provider (auto/azure/aws routing), provider_list (a comma-separated override like openai,azure,together to force specific providers), seed, proxy_url, timeout, retry_count, chat_template, and an extra JSON field.
Outputs
- text - the description/answer (STRING). Wire this into a Save Text node, a prompt builder, or a conditional.
- history - updated conversation for multi-turn, loops back into the
historyinput. - payload - the raw API response (any type), for when you want the structured data instead of just the text.
Install and setup
Same pack, same story: ComfyUI Manager, search "ComfyUI-YogurtNodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/yogurt7771/ComfyUI-YogurtNodes.git
cd ComfyUI-YogurtNodes && pip install -r requirements.txt
Then restart ComfyUI. The OpenAI/OpenRouter nodes need the openai package, which the requirements file installs. For the key, the cleanest setup is custom_nodes/ComfyUI-YogurtNodes/yogurt_nodes/llm/api_key.json:
{ "openrouter": "YOUR_API_KEY" }
Where people get burned
Two real failure modes. First, a blank api_key field only works if the file or env var is present - the field is required, and if nothing is configured you get an auth error, not a graceful hint. Second, OpenRouter model IDs change: claude-3.5-sonnet was the default this node shipped with, but model availability shifts and the exact slug you saved in a workflow can 404 later. If you suddenly get "model not found" errors on an old workflow, the model name is the first thing to check. And remember - this sends your images to a third-party API. For proprietary reference material, a local vision node is the more private option, but for everyday captioning this is hard to beat.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| api_key | STRING | API key for accessing OpenRouter API | |
| model_name | STRING | anthropic/claude-3.5-sonnet | OpenRouter vision model name |
| infrastructure_provider | COMBO | auto | Infrastructure provider (auto, azure, aws, etc.) - Optional |
| system_prompt | STRING | System-level prompt that affects the overall conversation style | |
| prompt | STRING | Main prompt content input by the user | |
| temperature | FLOAT | 1.000–2 | Sampling temperature, higher values produce more random outputs |
| top_p | FLOAT | 0.000–1 | Sampling probability threshold, controls output diversity |
| max_tokens | INT | 81920–32768 | Maximum number of tokens in the generated text |
| retry_count | INT | 11–10 | Number of retries when request fails |
| chat_template | STRING | <-system-> {{system_instruction}} <-/system-> <-user-> {{prompt}} <-/user-> | Content template for the generated text |
| provider_list | STRING | Provider list (comma separated, e.g: 'openai,azure,together'), empty means use infrastructure_provider | |
| proxy_url | STRING | 代理URL,格式: protocol://user:pass@addr:port,支持http,https,socks5,socks5h | |
| seed | INT | -1-1–2147483647 | Random seed for generation (-1 for random) |
| timeout | INT | 00–2147483647 | Timeout for the request in seconds, 0 means no timeout |
| imageopt | IMAGE | — | |
| image1opt | IMAGE | — | |
| image2opt | IMAGE | — | |
| image3opt | IMAGE | — | |
| image4opt | IMAGE | — | |
| historyopt | HISTORY | — | |
| extraopt | STRING | {} | Extra parameters for the request, in JSON format |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |
| history | HISTORY | — |
| payload | * | — |