HTTP and the web
The three nodes on this page solve three different problems, and confusing them is expensive: http_request calls any API as a graph step, fetch_webpage lets an agent read a page behind a link it already has, and websearch searches the internet and returns the model’s answer together with the sources and text excerpts from them.
None of them needs a connection: there is no login and no server to remember. A third-party API key lives not in a connection but in a workspace secret and is substituted through a template.
http_request — the universal door outward
This is the one node that makes an arbitrary HTTP request: method, address, headers, query parameters, body. Anything the platform has no dedicated integration for is done with it — from an internal company service to an API we have never heard of.
- Execute + Data
What you configure
| Field | Values | Note |
|---|---|---|
| Method | GET, POST, PUT, PATCH, DELETE, HEAD | GET and HEAD send no body, whatever sits in Body |
| URL | http/https | templated |
| Headers | JSON object | the whole field is templated, not just the values |
| Query Parameters | JSON object | numbers and booleans are stringified for you |
| Body type | none · json · text · form | form is application/x-www-form-urlencoded, written as a JSON object |
| Body | string | templated; for json it must be valid JSON after substitution |
| Authorization | none · bearer · basic · custom header | fills the Authorization header for you |
| Timeout | 1…120 seconds, 30 by default | a plan may lower the ceiling, never raise it |
| Max response size (bytes) | 1 KiB…10 MB, 1 MB by default | a longer response is truncated |
| Follow redirects | on | every hop is re-checked |
| Parse JSON Response | on | the body is decoded only if the server declared JSON |
| Fail on 4xx/5xx | on | turn it off when a 404 is a normal answer for you |
Templates and secrets
The address, headers, parameters, body and the auth fields all go through the
template engine. So {{ inputs.input }},
{{ nodes.<id>.output.<field> }} and {{ secret.NAME }} all work in them.
URL https://api.example.com/v1/orders/{{ inputs.input.order_id }}
Headers {"X-Api-Key": "{{ secret.SHOP_API_KEY }}"}
Body {"comment": {{ nodes.llm_1.output | tojson }}}
The key lives in Settings → Secrets, not in the graph. This is not hygiene for its own sake: a graph can be exported, shown to a colleague or handed to the assistant, and a token pasted straight into its JSON travels with it.
What the node passes on
The response arrives as a single object. {{ nodes.<id>.output }} is that whole object.
| Field | What is inside |
|---|---|
| status_code | the response code as a number |
| ok | true for 2xx |
| body | parsed JSON when the server sent JSON and parsing is on; otherwise a string |
| text | the raw response text, always |
| headers | response headers |
| url | the final address after every redirect |
| elapsed_ms | round-trip time in milliseconds |
Here the error branch is on by default
On most nodes the on_error output is off and has to be enabled by hand (see
Node errors). On http_request it is on from the start — it is the only
node in the catalogue with that default, and the reason is the nature of the job.
Somebody else’s server answers 500, returns 429, goes silent until the timeout or drops
the connection. That is not a bug in your scenario, it is a normal, expected outcome of
calling somebody else’s infrastructure. With the branch off, the single most common
failure in the product would always end the same way: the whole run dies, the person in the
chat gets nothing, and the author finds out from the run list. With the branch on, you
decide — say “the service is unavailable, try later”, fall back to another source, mail
yourself.
- Execute + Data
What routes control into the error branch: a network failure, a timeout, and — while
Fail on 4xx/5xx is on — any non-2xx answer. Turn that toggle off when the status code
is data to you (a 404 meaning “no such customer”): the node then always takes the success
path and you branch on {{ nodes.<id>.output.ok }} with an ordinary condition.
The error branch receives an object with a code and a message. The author does see the remote’s own response text: the service behind that address is theirs, and its words are the diagnosis. It is never shown to the person in the chat.
Where the node will not go
Every outbound request from the platform goes through a guarded client. It resolves the
hostname and refuses if the address falls into a private range: loopback,
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local 169.254.0.0/16 (the cloud
metadata address), multicast and reserved space. Redirects are followed manually and
re-checked on every hop — otherwise a public address answering 302 to
http://169.254.169.254/ would bypass the check entirely.
The restriction is not cosmetic: the URL field is a template, so part of it may come from a user’s message. Without this check a chatbot becomes a scanner of the internal network of the server it runs on.
Through a proxy
The Proxy field (under advanced settings) sends the request through http://,
https://, socks5:// or socks5h://. Empty means direct. The field is templated, so
an address carrying a password belongs in a workspace secret and reads as
{{ secret.PROXY }} rather than sitting in the graph.
The platform’s own proxy does not apply to this node: the addresses here are yours to pick, so the route is too. The private-network restrictions still hold — a proxy changes the next hop, not where the node is allowed to reach.
fetch_webpage — page reading for an agent
This node has neither a run input nor a success output: it exists only as an agent
tool. Drop it on the canvas, drag tool_out into the Agent extensions port of
ai_agent, and the model decides for itself when to open a link.
What it does: downloads the page, extracts the main content and converts the HTML to
Markdown, dropping navigation and markup. The model gets readable text rather than a
thousand-character <div>. The settings are a length limit (8000 characters by default, up
to 50,000), a timeout (20 seconds by default) and a cap on the raw response size. The limit
belongs to the author, not the model: the model cannot ask for more than you allowed.
Address checking is the same as for http_request: a link into the internal network is
rejected, and the model is told the address is not allowed rather than handed text from an
internal service.
websearch — searching the web
The node searches the web and returns both the model’s answer and the sources themselves, with text excerpts. There is one search node on the platform and it is paid: every search is its own line in the ledger, and on top of that come the tokens of the model that writes the answer from what was found.
It attaches in two ways, and the Node mode field decides which:
- Executable — an ordinary node: a
Queryinput and aSearch resultsoutput. You decide when to search, and the query itself arrives on the port or from the settings field. - As Tool — an agent extension: a
link_extensionwire into theAgent extensionsport. Whether to search, and what to ask, is the model’s call.
How many sources to take is the Max results field: five by default, up to twenty-five. Search modes, engines, domain filters and the way the money is counted have their own page, Web search.
fetch_webpage is the natural partner: search finds the page and brings back an excerpt,
fetch_webpage reads the whole thing when the excerpt is not enough. Both attach to an
agent the same way, and the model picks the order itself.
- Extension
What next
Web search
Modes, engines, domain filters and cost.
Agents and tools
How nodes attach to an agent with an extension link.
Templates
Substitution namespaces and the render-once rule.
Node errors
What arrives in the error branch and which codes exist.
Your own code
When an HTTP node is not enough and you need JavaScript.
Integrations: overview
Connections, secrets and who may change them.