Image2Prompt
The ComfyUI node that just forwards your image to an API
- images
- text
The name is a small lie. This node doesn't run any image-to-prompt model itself - no weights, no VRAM, no local AI. What Image2Prompt actually does is hand your image to a remote API and paste whatever caption comes back into your workflow. That's the whole job, and it's the first thing to understand before you install it.
That's a different beast from the usual ComfyUI image-captioning route (WD14 Tagger, BLIP, Florence2 - all local and free). Those run on your machine. This one is a thin client for a specific external service. If you don't already have access to an API that speaks this node's protocol, it won't do anything useful for you. The whole pack (Chinese README, one author, one commit) is written around a particular hosted image-to-prompt service - think "paid or internal API, not your GPU."
How it works
Reading the source, the flow is straightforward. Image2Prompt takes the first image in your batch, converts the ComfyUI tensor to a PIL image, downscales it so it's no wider than 1000px and no taller than 800px (LANCZOS resampling, which keeps the payload small), and base64-encodes it as a PNG - without the data:image/png;base64, prefix.
Then it POSTs to {APIUrl}/generate with your key in an authorization header:
{
"authorization": "your-api-key"
}
{
"type": "img2img",
"base64": "<the encoded image>"
}
The response has to come back shaped like {"code": 200, "neutralText": "...", "promptText": "..."}. If code is 200 the node returns neutralText or promptText depending on the Neutral switch; anything else prints an error to the console and, after all retries are exhausted, returns None. The protocol is bespoke - point it at an arbitrary image-to-prompt API and it will not just work.
The inputs and outputs that matter
- images (IMAGE) - wire this from Load Image or any node that outputs an image tensor.
- APIUrl (STRING) - the base URL of the service. The node appends
/generateitself, so don't add the path. - APIKey (STRING) - sent in the
authorizationheader. - RetryCount (INT, default 3) - retries on a failed request, with a 1-second wait between attempts.
- Neutral (BOOLEAN, default true) - returns the API's "neutral" description versus the "prompt-style" one.
- text (STRING output) - feed it into a CLIP Text Encode node as the positive prompt.
That's the entire surface. Five inputs, one output, nothing hidden.
Installing it
ComfyUI Manager is the easy path: search for ComfyUI-NudeJS-Image2Prompt and hit install. Or clone it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/NudeJS-dev/ComfyUI-NudeJS-Image2Prompt
Then restart ComfyUI. Dependencies are just requests and Pillow - both already ship in ComfyUI's embedded Python, so there are no heavy installs and no model files to download. This is about the lightest install you'll do.
Where people get burned
- It needs a specific API. The README's
https://api.example.comis a placeholder, not a real endpoint. Without a service that implements this exactcode/neutralText/promptTextcontract, the node returnsNoneand you're stuck debugging a black box. Your first troubleshooting step should be confirming the API actually speaks this protocol. - Only the first image is processed. Batches are silently reduced to their first frame. Feed it one image at a time.
- There's a hidden double-retry. Your
RetryCountdrives the visible loop, but the requests session also has a hardcoded retry for HTTP 429 and 5xx statuses baked in. Slow services can feel extra slow. - Privacy is on you. This node sends your image to a third-party server by design. Don't feed it anything sensitive, and check what the service does with your uploads.
- Failures are silent-ish. Errors print to the ComfyUI console, not to the node, so watch the terminal output. A
Noneresult can also crash downstream nodes that assume they're getting a string.
If you've got access to a service that speaks this protocol, this is a clean little bridge - two minutes to install, one node to wire, and your captions land straight in the prompt encoder. If you don't, save yourself the confusion and use a local tagger instead.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| APIUrl | STRING | — | |
| APIKey | STRING | — | |
| RetryCount | INT | 30–100 | — |
| Neutral | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |