WebFetch: prompt-based extraction ignored — full raw page dumped into context, exhausting 1M-token window after 3-4 fetches
Summary
WebFetch (and the Fetch tool used inside background/loop sessions) does not honor its own prompt parameter for extraction. Even when the caller explicitly asks for a narrow, extracted answer (e.g. "extract exactly which model IDs support X"), the tool injects the entire converted page (full Markdown, including every table, <Note>/<Tip> block, and code sample) into the conversation transcript/context. On documentation pages such as docs.claude.com/platform.claude.com, a single page is 20–30 KB of Markdown. Doing 3–4 such fetches in a row — a completely normal pattern when cross-referencing a handful of doc pages — is enough to consume essentially all of a 1,000,000-token context window, derailing the rest of the session.
Environment
- Claude Code version:
2.1.198 - OS: macOS 26.5.2 (BuildVersion 25F84), Darwin 25.5.0
- Model in session:
claude-sonnet-5 - Reproduced in: a background/loop agent session doing multi-source research (fetching Anthropic docs + comparing against OpenAI/Google docs) inside a project with no git commits yet
Steps to Reproduce
- Start a Claude Code session (interactive or background/subagent) on any project.
- Ask it a question that requires checking a handful of
docs.claude.com/platform.claude.compages, e.g.: "Which Claude models support theeffortparameter and which levels does each support?" - Observe Claude issuing
WebFetch/Fetchcalls with a specific, narrowprompt, for example:
````
Fetch(url: "https://platform.claude.com/docs/en/build-with-claude/effort.md",
prompt: "Extract exactly which Claude model IDs support the effort parameter,
which effort levels (low/medium/high/xhigh/max) each supports, and
which models error when...")
- The tool result is logged as
Received 22.2KB (200 OK). - Immediately after, the full page is dumped verbatim into the transcript — starting from the
# Effortheading and continuing through every section (How effort works, the full effort-levels table, every<Note>/<Tip>callout,Effort with extended thinkingper-model bullet list,Best practices,Next steps, etc.) — none of it filtered down to what thepromptasked for. - Repeat for 3–4 pages (in the observed session: the Claude models overview page, the effort.md page, and two more fetched in parallel against OpenAI/Google docs for comparison) and the context is effectively exhausted — a 1,000,000-token window filled after only 3–4 fetches.
Expected Behavior
When a prompt/extraction instruction is supplied to WebFetch, the tool should return a short, targeted extract (ideally on the order of a few hundred to a couple thousand tokens) that answers the prompt — not the raw page. This is the entire point of passing a prompt argument instead of doing a plain fetch: it should behave like a mini sub-agent call that reads the page and returns a distilled answer, similar to how Task/sub-agent results only surface a final summary rather than every tool call's raw output.
Actual Behavior
- The extraction step appears to be skipped or bypassed: the full HTML→Markdown conversion of the page is inserted into context regardless of the
prompt. - This happened consistently across every fetch observed in the session (screenshots 1, 2, 3, 4, 6 all show large, unfiltered Markdown dumps — headings, full code samples in Python/TypeScript/C#, full
<Note>blocks, full tables — fromdocs.claude.com/platform.claude.compages). - Screenshot 4 is the clearest evidence: it shows the actual
Fetch(...)invocation with itspromptargument on one line, followed byReceived 22.2KB (200 OK), followed immediately by the complete, un-summarized document body. - Because the research task legitimately required checking multiple pages (and even ran 4 fetches in parallel to cross-reference Anthropic's
effortdocs against OpenAI'sreasoning_effortand Google'sthinking_levelequivalents), context filled up almost immediately, well before the actual coding task could proceed.
Impact
- Makes any multi-page research/verification task (a common and encouraged pattern — "don't guess, verify against live docs") prohibitively expensive in context, even on a 1M-token model.
- Defeats the purpose of the
promptparameter entirely — if it doesn't reduce what lands in context, there's no reason to pass it vs. a bare fetch. - Forces users/agents to either avoid
WebFetchfor anything beyond a single quick lookup, or to burn most of the context budget on raw HTML-derived Markdown instead of on the actual task. - Particularly bad for background/subagent sessions doing autonomous verification loops, where several fetches per iteration is the normal shape of the work.
Suspected Root Cause
Likely one of:
- The
promptis being sent to the underlying fetch/convert step but the extraction/summarization sub-call that should condense the page against that prompt is not actually running (or its output is discarded and the raw converted content is returned instead). - There's a size threshold under which the tool short-circuits straight to "return raw content" without ever invoking extraction, and typical doc pages (20–30 KB) fall under it.
- The extraction step runs, but its result is being displayed/appended in addition to the raw page rather than replacing it in the transcript that becomes context.
Suggested Fixes
- Guarantee that when a
promptis supplied, only the model-produced extract (not the raw fetched content) is returned as the tool result — enforce this at the tool-result-construction layer, not just as a best-effort instruction to an inner model call. - Add a hard cap on how many tokens a single
WebFetchresult can inject into context (e.g. a few thousand tokens), truncating/summarizing server-side before it ever reaches the caller's context, with a clear "truncated — N KB total, use a more specific prompt or fetch a sub-section" notice. - Where no
promptis given, still consider returning a capped/paginated result (mirroringRead'soffset/limitpattern) rather than the full page, so a plain fetch of a large doc can't alone eat hundreds of thousands of tokens. - Surface an estimated token count for the fetched content before/along with injecting it into context, so the acting model can decide whether to proceed, narrow the prompt, or fetch a smaller section.
- Consider de-duplicating repeated fetches of the same URL within a session/run.
Related observation (possibly a separate issue)
In the same session, an EnterWorktree call failed with Failed to resolve base branch "HEAD": git rev-parse failed because the target repo had no commits yet, and the background session then blocked a subsequent Write with: "This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout..." — i.e., background-session isolation has no fallback for a repo with zero commits, forcing the agent to either fail or write directly to the shared checkout. Flagging this in case it's useful, but happy to file it separately if preferred.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗