Claude's Web Fetch Tool Checks Where a URL Came From, Not What It Is
Claude's web_fetch tool blocks any URL that didn't already appear in the conversation from an allowed source, and Claude Managed Agents just added a second, host-level filter on top of that. If your bot's design assumes the model can freely follow links it finds, you need to know exactly which three sources count and which don't.
AI-assisted editorial: researched and drafted with AI using the primary sources linked below. Examples are illustrative; they are not measured product results. Editorial policy.
Key takeaways
- web_fetch only follows URLs from user messages, client-side tool results, or prior web_search/web_fetch results — never from Claude's own output or the system prompt.
- A hardcoded URL in your system prompt will be rejected with url_not_in_prior_context; put it in the first user message instead if the bot must fetch it live.
- In Claude Managed Agents with limited networking, allowed_hosts now also gates web_search and web_fetch, so a missing host causes a 400 at session creation, not a runtime surprise.
The Fetch Tool Checks Provenance, Not Content
Claude's web_fetch tool does not decide whether to retrieve a URL by looking at the URL itself. It decides by asking where that URL came from. Anthropic's documentation lists exactly three sources that count: URLs in user messages, URLs in client-side tool results, and URLs from a previous web_search or web_fetch result. Anything else is invisible to the tool, even if the string is identical to a URL that would otherwise be allowed.
This matters most for the sources that do not count. The documentation is explicit that Claude cannot fetch a URL that appears only in its own output, and separately, that a URL living only in the system prompt is also out of reach. When a fetch is attempted against a URL that never surfaced through one of the three allowed channels, the tool returns a url_not_in_prior_context error to the agent rather than making the request.
The nuance worth remembering: a client-side tool result still counts as an allowed source even when that result just echoes text Claude generated a moment earlier. So the rule is about which channel carried the URL into the conversation, not about who or what originally wrote the string.
Sources: Web fetch tool - Claude Platform Docs.
Worked Example: A URL That Never Gets Fetched
Illustrative case: a small ops bot is told, in its system prompt, to always check a vendor's status page before answering incident questions — something like 'Check https://vendor.example.com/status for current incidents.' The model calls web_fetch directly against that URL because it's sitting right there in its instructions.
That call fails. The URL lives only in the system prompt, which is not one of the three allowed sources, so the tool returns url_not_in_prior_context instead of a page. If the bot's error handling doesn't expect this, it will look like the fetch tool is broken, when in fact it's working as documented.
The practical fix is to stop treating the system prompt as a place to park URLs the bot must act on. Put the URL in the first user message of the session instead, or have the bot call web_search for the vendor's status page so the URL arrives as a search result. Both paths put the URL through an allowed channel, and the subsequent fetch succeeds.
A second, more forgiving case: the bot fetches a vendor's changelog page, and that page's returned content contains a link to a specific release note. Following that second link works, because the URL arrived via a previous web_fetch result — one of the three allowed sources. Chained discovery through fetched pages is supported; chained discovery through your own prompt text is not.
Sources: Web fetch tool - Claude Platform Docs.
Managed Agents Added a Second Filter in October 2026
As of the October 7, 2026 Claude Platform release notes, Claude Managed Agents running in a cloud environment with limited networking now apply that environment's allowed_hosts list to web_search and web_fetch as well. A web_fetch call for a URL on a host that allowed_hosts doesn't match returns a url_not_allowed error, and web_search simply omits results from hosts outside the list.
This is a separate check from the provenance rule above, and it stacks on top of it. A URL can pass the prior-context test and still be blocked for landing on a host the environment hasn't allowlisted. If allowed_hosts lists no hosts at all, neither tool returns anything — not a page, not a search result.
The allowlist match is exact unless an entry starts with a wildcard: an entry for example.com does not cover docs.example.com. Anthropic's own guide on restricting web search and web fetch domains confirms the same exact-match behavior for the per-tool allowed_domains and blocked_domains lists that sit on top of allowed_hosts.
There's also a deployment-time check worth knowing about before you ship: creating or updating a Managed Agents session fails with a 400 error if an enabled web tool's allowed_domains contains a host that isn't inside allowed_hosts. That's a cheap, deterministic failure you can catch in a staging deploy, rather than something that surfaces only when the agent tries to fetch a real page in production.
Sources: Claude Platform release notes - Claude Platform Docs, Restrict web search and web fetch domains - Claude Platform Docs.
What to Build Around This
Treat both checks as expected branches in your bot's logic, not failure states to patch around. If your bot needs to fetch a specific, known URL on every run, send that URL in the user message rather than the system prompt — it's the only placement guaranteed to satisfy the prior-context rule. If the bot discovers URLs by searching or by reading pages it already fetched, those chains work without extra effort, because each step lands through an allowed source.
If you're deploying on Managed Agents with limited networking, align allowed_hosts and any per-tool allowed_domains or blocked_domains before you deploy, not after. A session that fails to create with a 400 error is a far cheaper signal than a live agent silently getting empty search results or a stream of url_not_allowed errors it has no instructions for handling.
Finally, don't write error handling that assumes web_fetch failures mean the network is down or the page moved. url_not_in_prior_context and url_not_allowed are both policy decisions, not outages. A bot that retries a blocked fetch in a loop, or escalates it as an incident, is treating a security control as a bug.
- Allowed URL sources: user messages, client-side tool results, prior web_search/web_fetch results.
- Not allowed: Claude's own output, the system prompt.
- Managed Agents add a host-level allowed_hosts check on top, independent of the provenance rule.
Sources: Web fetch tool - Claude Platform Docs, Claude Platform release notes - Claude Platform Docs.
Primary sources
Sources checked 2026-10-16. Standards and product documentation can change; follow the linked version when implementing.
BotBento is in development. Suggest a correction.