Nodes/ZMG PLUGIN/API Request Node
ComfyUI Node

API Request Node

Call any API from inside a workflow — no key required, just Python requests

By fq393·Created 2 years ago·Updated 7 months ago· 8
API Request Node
  • anything
  • response
  • passthrough
api_urlhttps://api.example.com/endpoint
request_methodGET
data_formatjson
request_params{}
headers{}
timeout10

If you've ever wanted a workflow to talk to the outside world - hit a tagging service, fire a webhook when a batch finishes, pull a caption from your own LLM server, or POST results to a backend - this is the node for it. The name is refreshingly honest: it's a plain HTTP client that lives in your graph. No API key, no external account, nothing to configure beyond the URL you're calling. You bring the endpoint, it does the talking.

What it does and how

Under the hood it's Python's requests library wrapped in a node. You give it a URL, pick a method (GET, POST, PUT, DELETE), optionally drop in a JSON payload and headers, and it fires the request when the graph runs. The params and headers boxes take JSON strings - so {"model": "gpt-4o"} type stuff, not bare text. If the server replies with JSON, it pretty-prints it for you; anything else comes back as raw text.

The part I actually like: it never crashes your graph. Every failure - timeout, DNS failure, HTTP 400, garbage JSON - comes back as a response string that starts with Error:. That means you can wire the error into a text display or a conditional and handle it gracefully, which is exactly what you want in an automation pipeline.

Inputs and outputs that matter

  • api_url - the endpoint. Must start with http:// or https:// or it bails with an error string.
  • request_method - GET / POST / PUT / DELETE.
  • data_format - json or form. JSON sends the payload as application/json; form sends it URL-encoded. One gotcha: DELETE ignores your params entirely (the code doesn't send a body for DELETE), so don't expect to pass data that way.
  • request_params and headers - JSON strings, both multiline.
  • timeout - seconds, 1–300, default 10.
  • anything - a wildcard passthrough input, plus the node echoes it back as passthrough output. Handy for keeping data flowing while the request happens.

Outputs are just response (STRING) and passthrough (anything). Wire response into a text node, or feed it into the pack's JSON Parser to dig a value out of the reply.

The caching gotcha

This one trips people up. ComfyUI caches node outputs by their inputs, and this node doesn't override IS_CHANGED to force a refresh. So if you point it at a URL whose contents change over time (a status endpoint, an evolving API) and re-run the queue with identical inputs, it will happily return the cached response instead of re-calling. To force a fresh call, change something upstream - bump a seed, feed a changing value into anything - or restart the run with a modified input. It's standard ComfyUI behavior, but for an HTTP node it's easy to mistake for a broken request.

Installing it

The node ships in the ZMG pack. Easiest path is ComfyUI Manager - search "ZMG" or "ComfyUI-ZMG-Nodes" and install. Manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/vanche1212/ComfyUI-ZMG-Nodes
cd ComfyUI-ZMG-Nodes
pip install -r requirements.txt

Then restart ComfyUI. Note the pack README's own install block still points at fq393/ComfyUI-ZMG-Nodes.git, an older handle - use the vanche1212 URL above, which is the live repo. For this node specifically, requests is the only dependency that matters.

When it's not the right tool

It's a one-shot HTTP call per graph run. If you need real-time polling, retry logic, or auth flows beyond a static header, this is too thin - you'd be better off with a dedicated integration node. But for "call an API once, get a string back," it does exactly what it says, and that's rarer in this ecosystem than it should be.

CategoryZMGNodes/network

Inputs (7)

NameTypeDefaultDescription
api_urlSTRINGhttps://api.example.com/endpoint
request_methodCOMBOGET4 options: GET, POST, PUT, DELETE
data_formatCOMBOjson2 options: json, form
request_paramsSTRING{}
headersSTRING{}
timeoutINT101–300
anything*

Outputs (2)

NameTypeDescription
responseSTRING
passthrough*