Allow Claude Code's WebFetch for specific domains only

Claude Code Published:

How WebFetch(domain:...) rules match, what each wildcard position covers, why a bare WebFetch rule differs from domain:*, and why a redirect target needs its own permission.

Verified on Sep 8, 2026 These tools change quickly. Please also check the latest official documentation.
Contents
  1. Allow only the domains you need
  2. What each wildcard position covers
  3. "Allow everything" has two spellings
  4. Things to watch for
  5. Summary

You want Claude to look things up, but not to reach any site it likes. That requirement is expressible as a WebFetch(domain:...) rule in permissions.

Rules match against the hostname of the requested URL. Matching is case-insensitive, and a trailing . is stripped from both the rule and the hostname, so example.com. and example.com are treated the same.

KEY POINT

What you will learn

  • How to write WebFetch(domain:...) and what each wildcard position covers
  • The difference between WebFetch and WebFetch(domain:*)
  • How this interacts with the sandbox network allowlist, and the redirect trap

Allow only the domains you need

This allows an internal documentation host and one official site:

{
  "permissions": {
    "allow": [
      "WebFetch(domain:code.claude.com)",
      "WebFetch(domain:*.internal.example.com)"
    ],
    "deny": [
      "WebFetch(domain:pastebin.com)"
    ]
  }
}

Domains in allow are fetched without a prompt; everything else prompts as usual. Put hosts you never want fetched in deny. Deny is evaluated before allow, so adding an allow rule later does not unblock it.

Choosing "Yes, and don't ask again for <domain>" at a permission prompt also writes a WebFetch(domain:...) allow rule into your local settings. The list grows without you editing anything, so review it in /permissions now and then.

What each wildcard position covers

A wildcard means different things depending on where it sits. Matching fetches against a wildcard requires Claude Code v2.1.172 or later.

RuleMatchesDoes not match
domain:example.comexample.comSubdomains
domain:*.example.comapi.example.com, a.b.example.comexample.com itself
domain:example.*example.orgexample.evil.com
domain:*Every domain—

That domain:example.* does not match example.evil.com is the important property. In any position other than a leading *. or a bare *, the wildcard matches only the text between two dots. This keeps a trailing wildcard from reaching domains an attacker could register.

"Allow everything" has two spellings

A bare WebFetch rule — the tool name with no domain: part — and WebFetch(domain:*) both cover every URL, but Claude Code applies them differently. Only the domain: form touches the sandbox's allowed-domain list.

RuleIn allowIn deny
WebFetchClaude fetches without prompting you. Doesn't change which hosts sandboxed commands can reachClaude Code removes the tool, so Claude can't fetch at all. Doesn't change which hosts sandboxed commands can reach
WebFetch(domain:*)Claude fetches without prompting you, and sandboxed commands can reach any hostClaude Code keeps the tool and refuses each fetch, and sandboxed commands can't reach any host

用語解説

How this relates to the sandbox: the Bash sandbox pre-allows no domains by default. Alongside sandbox.network.allowedDomains, your WebFetch(domain:...) allow rules count as allowed domains. But the sandbox honors only two wildcard forms — a leading *. and a bare * (bare * requires v2.1.186 or later). A rule like domain:example.* matches fetches but has no effect on sandboxed commands.

Things to watch for

A redirect target needs its own permission

WebFetch does not follow a cross-host redirect automatically. It returns a text result naming the original URL and the redirect target, and Claude fetches it with a second WebFetch call. The redirect target therefore needs an allow rule or a one-off approval of its own. Allowing a shortener or a redirector does not allow whatever it points at.

Other documented behavior worth knowing:

  1. An HTTP URL is upgraded to HTTPS automatically.
  2. HTML responses are converted to Markdown, and that conversion is not configurable.
  3. Responses are cached for 15 minutes by default. From v2.1.233 you can change the duration with CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS.
  4. There is a built-in set of preapproved documentation domains that are fetched without a prompt. The specific list could not be confirmed in the official documentation.

For keeping secrets out of the agent's reach, see Keep API keys and secrets away from AI coding tools; for the read side, Deny reading .env in Claude Code. The overall allow/ask/deny design lives in the parent article, Design permissions in Claude Code's settings.json.

Summary

  • WebFetch(domain:...) matches the hostname, case-insensitively, ignoring a trailing dot
  • *.example.com covers subdomains only; write example.com separately if you want the apex
  • A trailing wildcard never crosses a dot, so example.* does not match example.evil.com
  • "Allow everything" is either a bare WebFetch or WebFetch(domain:*); only the latter also widens what the sandbox can reach
  • A cross-host redirect target needs its own allow rule or approval

FAQ

Does WebFetch(domain:*.example.com) also match example.com itself?
No. A leading *. matches a subdomain at any depth but not the apex domain. Write two rules if you want both.
Should I allow WebFetch or WebFetch(domain:*)?
Both cover every URL, but only the domain: form also adds its domain to the sandbox's allowed-domain list. Use the bare WebFetch rule when you don't want to change what sandboxed commands can reach.
What happens when an allowed page redirects to another domain?
WebFetch does not follow a cross-host redirect. It returns text naming the original URL and the redirect target, and Claude fetches it on a second call — so the redirect target needs permission of its own.

Primary sources

This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.