Why Claude Code’s WebFetch Might Be Quietly Lying to You?
Photo by Glenn Carstens-Peters on Unsplash
I hope this article does not make you go back and audit every research task you’ve handed to Claude Code over the past few months.

Gist of it is:

WebFetch, the tool Claude uses to pull content off a webpage, doesn’t actually hand the full page back to your main model.

It routes through a smaller, cheaper model first, which reads the page and writes a summary.

Your main model never sees the raw text.

It only sees somebody else’s notes on it.

That distinction sounds small until you think about what a summarizing model actually does under pressure.

It doesn’t just compress, it fills gaps.

Ask it “what are the key numbers here” and it will hand you numbers, whether or not the page actually has them in the shape you asked for.

One user described asking Claude to research memory architecture for an agent project and getting back specific stats and quotes that looked completely legitimate.

When they pushed back and asked “are you actually reading these papers,” Claude admitted it wasn’t.

It caught a fabricated citation, a framework name that didn’t exist anywhere in the source, and a stat that looked like it had been averaged across two numbers pulled from unrelated tables.

I’ve been building an AI-tool-hooked content pipeline for months now, and research accuracy is basically my entire product.

If a subagent is quietly rounding numbers or inventing a framework name and I don’t catch it, that error doesn’t stay contained.

It goes into an article, gets indexed, gets picked up by someone’s GEO pipeline, and now it’s out there as fact.

That’s the actual cost here, not “the AI made a mistake” but “the mistake had somewhere to go.”

Why this happens and why it’s easy to miss?

The reason this slips past most people is that the failure mode is invisible in the output.

A hallucinated stat and a verified one read exactly the same.

Both come out as confident prose with the right tone and the right level of specificity.

You only catch it if you go open the tool call, look at what WebFetch actually returned, and compare it against the source yourself.

Almost nobody does that on a regular research task, because the whole point of delegating research to an agent is that you don’t want to read fifteen pages of raw HTML.

There’s a second wrinkle that makes this worse for anyone doing broad research across many pages.

Even when WebFetch isn’t hallucinating outright, it often only grabs part of a long page, and there’s no reliable way to know which part.

If the fact you actually needed was three screens down, it just isn’t there, and the model has no way to flag that it’s working from a partial view.

What actually fixes it

The fix people landed on, independently and from different angles, comes down to one principle:

Stop letting a model summarize a page before your main model ever sees it.

A few concrete versions of this showed up repeatedly.

The simplest is forcing raw fetches.

Instead of relying on WebFetch, tell Claude to curl the page directly and read the actual text.

One person reported this caught 17 errors across roughly 30 papers in a research pass, including two cases where WebFetch’s conclusions were reported backwards from what the source actually said.

Curl has a real limitation though.

JavaScript-heavy pages don’t render properly, so you get an empty shell instead of content.

That’s where tools like Trafilatura come in.

It’s a Python CLI that strips out the HTML, JS, and CSS clutter and hands back clean readable text, which plays nicer with curl’s blind spot on dynamic pages.

A few people had wired this into their workflow as a drop-in replacement, disabling WebFetch entirely at the settings level and pointing Claude at Trafilatura through a CLAUDE.md instruction instead.

The more disciplined version of this, and the one I think actually matters if you’re doing anything higher stakes than a quick lookup, is treating the fetch step as a data operation rather than a reasoning operation.

One person put it well:

don’t ask a fetching step to summarize, ask it to extract.

Summarization prompts implicitly reward the model for producing something that sounds complete, numbers and all, whether the page had them or not.

Extraction prompts, where you’re asking for verbatim quotes with a location attached, don’t carry that same incentive.

There’s nothing to invent if the task is literally copy this line.

The most rigorous setup I saw combined a few of these ideas into a standing rule:

identify which claims are actually load-bearing for the research before searching, require at least two independently read sources for those, allow single-source treatment for peripheral details, and never cite from a search snippet since a snippet is index text, not the actual page.

Anything that can’t be verified gets listed as a stated gap instead of getting smoothed over.

It’s more overhead per research task, but it turns “trust the summary” into something closer to an actual audit trail.

You can see the queries used, the sources actually read, what got triaged away and why, and what got blocked and never verified at all.

What I’m changing

For my own workflow, I’m not going to pretend I need the full audit-trail version of this for every quick fact check.

But for anything that ends up as a claim in a published article, especially the kind of specific stat or quote that reads as authoritative, I’m adding a rule to always fetch raw and never trust a WebFetch summary as a primary source.

If a page is JS-heavy and curl comes back empty, that’s the signal to open it manually rather than accept a thin result and move on.

The uncomfortable part of all this is what it implies about the

“Claude is giving me false information” complaints floating around.

A chunk of those probably aren’t model quality issues at all. They’re tooling issues, where the source material got mangled before the model doing the reasoning ever saw it.

If you’re only looking at the final answer, you have no way to tell the difference between a model that reasoned badly and a model that reasoned perfectly well on bad input.

Worth checking which one you’re actually dealing with before you write off the tool entirely.

In case we are meeting for the first time, come over here, it’ll be worth the roller coaster of articles that are gonna come up in the next few weeks.