nanobot is a self hosted agent with web search and page fetching built in. Unusually for this series, it has a real proxy setting. It is also the first tool we have read where turning that setting on turns something else off, on purpose. The reason is worth a page. We read release v0.3.5 on 20 September 2026.
The setting
The web tools carry three fields worth knowing:
| Setting | What it does | Default |
|---|---|---|
tools.web.proxy | a proxy URL, handed to the HTTP client | none |
tools.web.user_agent | the user agent for web requests | none |
tools.web.fetch.use_jina_reader | lets a hosted reader fetch the page | on |
Set the first one and every web fetch and keyless search goes through it. That is the whole configuration, and it is more than most projects in this family offer.
What the setting switches off
Here is the part that is easy to miss. The client is built like this:
if proxy:
kwargs["proxy"] = proxy
else:
kwargs["transport"] = _pinned_dns_transport()
mounts = httpx_env_proxy_mounts()
The pinned transport makes sure the connection goes to the address that was checked. Without it, a name that changes between the check and the connection gives a second answer. It cannot do that job behind a proxy, because the client no longer resolves anything. The proxy does.
The check itself does not go away. Before every request, and again before any redirect, the URL is resolved. It is refused if it lands on a private, loopback, link local or cloud metadata address. Their block list names the metadata range in a comment. The loopback exception is deliberately narrow: no private ranges, no link local addresses, and no public names that happen to resolve to loopback.
So the practical consequence is simple. With a proxy configured, what the proxy can reach is what the agent can reach. Use a line that exits on the public internet, not one that sits inside a network you care about.
Two ways to set it
If you do not set tools.web.proxy, the process proxy settings are still honoured. That is not free behaviour here. A client with a custom transport normally ignores the environment entirely. So the project reads the proxy settings itself and rebuilds them as mounts.
It is done carefully. A value with no scheme is treated as http://. The exceptions are honoured too. A no proxy value of * disables proxying completely, and each listed host becomes a direct route. There are patterns for localhost and for domain suffixes. On Windows the lookup falls back to the system settings.
That gives you a choice. Set the variables and keep the pinned transport, or set the field and get the proxy on every web request.
Who does the searching
The search tool has eight backends and one rule that matters more than the rest:
| How it is configured | Whose address searches |
|---|---|
| a vendor with its key set | the vendor's |
| a vendor with the key missing | yours, through the fallback |
| a self hosted instance with a base URL | yours |
Seven providers share the same shape. If the key is absent, the provider silently becomes DuckDuckGo. A typo in an environment variable does not produce an error. It moves the search from a vendor's servers to your own address. That is the lane that gets rate limited.
If your searches suddenly start failing, check the key before you check anything else. And if you are deliberately using the keyless fallback, that is exactly when a proxy earns its money.
The reader that is on by default
Page fetching uses a hosted reader unless you turn it off. So by default some fetches are performed by a third party and your address is not involved. Two things follow. The page you read was fetched from somewhere else, which may explain a different answer. And the URL was disclosed to that service.
The project guards the second point properly. A URL carrying credential material is never sent to the reader. That covers userinfo, a signed parameter, a token or a key. Their comment explains the direction of error: over matching only costs the local fallback, under matching leaks a secret. We covered that service on our Jina Reader page. Its keyless lane is the most rate limited one it has.
Which proxy type fits it?
Residential, for the sources that answer a hosting address differently. Our own paired test is the size of that effect: 4 of 13 sites answered a residential address differently from a server one, with plain requests of the kind this fetch sends.
The traffic is small. Search results and page text are stripped of tags before the agent sees them, so a per gigabyte line goes a long way. Two notes for this project. The setting takes a URL, so a login would sit in the configuration file. An allowed address avoids that: on a Residential Premium plan your machine's address can be allowed, up to 150 per plan. And because the proxy now resolves and connects, pick a line whose exit is on the open internet. The residential proxies page lists the plans, and the plan API manages allowed addresses from code.
What breaks
- A search works, then stops working. Check the key. Without it the provider becomes the keyless fallback and your address does the searching.
- A fetch reports a location you did not configure. The hosted reader fetched the page. Turn it off if you want your own address used.
- A URL with a token is never fetched through the reader. That is the credential guard, working as intended.
- Your no proxy list is ignored. It is honoured only on the environment path, not when the field is set.
- The agent cannot reach an internal service. It refuses private addresses by design, on every request and every redirect.
What this page does not cover
We read the release as text and did not run the agent. So we did not watch a fetch use an address, did not exercise the pinned transport and did not measure a run's traffic. We read the web tool, its client construction and the network security module closely, and the rest of a large repository not at all. We did not check what the browser and shell tools do about proxies, only the web tools. This project pushed to its main branch hours before we read it and the release is five days old, so check your version. We will read it again by 20 October 2026.
Where to go from here
Proxies for OpenClaw covers a larger agent with the same question and a very different answer. Proxies for Jina Reader covers the hosted reader this tool uses by default, including the two headers it accepts. Proxies for SearXNG covers the self hosted search backend, where the searching returns to your own machine.
Sources
- The web tools configuration with its proxy and user agent fields, the client construction that chooses between a proxy and the pinned transport, the provider fallback to a keyless search, and the reader that is on by default with its credential guard (nanobot/agent/tools/web.py). The address check, the blocked ranges and the rebuilt environment proxy mounts (nanobot/security/network.py). HKUDS/nanobot, release v0.3.5 of 15 September 2026, read 20 September 2026.
- Our paired address test of 19 September 2026: 16 URLs, plain requests, two runs from our server and two through a residential line of our house plan. Raw output is kept in the research folder of our OpenClaw page.
- Plans, allowed addresses and per gigabyte pricing. HProxy documentation, hproxy.com/docs, 20 September 2026.


