◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-05-19中級

Claude Code の WebFetch が 403 や空ページを返す時の原因と対処

Claude Code の WebFetch が 403 を返したり、本文が抜けた空のページを返す現象には、いくつか定番の原因があります。Cloudflare のボット検知、クライアントレンダリング、ドメイン許可リスト、キャッシュの4点を切り分けながら、それぞれの実用的な対処法を整理します。

claude-code132webfetchtroubleshooting61cloudflarespaclaude-in-chrome4

「WebFetch で技術ドキュメントを読ませようとしたら、403 が返ってきた」「200 は返っているのに本文がほぼ空で、ナビゲーションだけが残っている」— Claude Code を日常的に使う中で、自動化スクリプトのある日突然うまく動かなくなる代表的な現象です。私自身、自分の運営する Lab 系サイト4本の自動投稿パイプラインで、月に何度かこの種のトラブルにぶつかります。

落ち着いて切り分ければ原因は4つに集約できます。それぞれの見分け方と、私が実運用で採用している対処を順に整理しておきます。

何が起きているのか — WebFetch の挙動を先に押さえる

Claude Code に組み込まれた WebFetch ツールは、内部的には Anthropic 側のサーバーが対象 URL に対して HTTP GET を発行し、得られた HTML をテキスト化してモデルに渡す仕組みです。ここで重要なのは、ブラウザではないという点です。

具体的には次の挙動を持ちます。

  • JavaScript を実行しない: React や Next.js、Vue で構築されたクライアントレンダリング系のページは、初期 HTML のシェル(ローディングスピナーやナビゲーション)だけが返ります。
  • 固定の User-Agent を持つ: 一部のサイト(特に Cloudflare の Bot Fight Mode を有効にしているもの)は、この User-Agent を機械的に弾きます。
  • 結果を一定時間キャッシュする: 同一 URL に対して短時間に再リクエストすると、サーバー側のキャッシュから古いレスポンスが返ることがあります。
  • ドメイン許可リストが効く: --allowedDomains を絞っている運用では、許可対象外のドメインへのアクセスが事前にブロックされます。

つまり「403」「空ページ」「タイムアウト」「想定と違う古い情報」のいずれも、原因はこの4軸のどれかに収まります。

原因1: Cloudflare などのアンチボット保護で 403

Anthropic のヘルプドキュメント、GitHub の生のファイル、Stack Overflow など、Cloudflare の手前にいるサイトでは、WebFetch のリクエストがしばしば 403 で弾かれます。エラーメッセージとしては次のような形で返ってくることが多いです。

Web fetch failed: HTTP 403 — the server refused to fulfill the request

これは Cloudflare の Managed Challenge や Bot Fight Mode が、WebFetch の User-Agent や TLS フィンガープリントを「明らかにブラウザではない」と判定して落としているサインです。私の経験では、特に技術ドキュメントを多用するエージェント運用で頻発します。

私が使っている対処

まず、対象 URL に 同じ情報の代替ソース がないかを最初に検討します。例えば GitHub の https://github.com/owner/repo/blob/main/README.md は 403 になりがちですが、https://raw.githubusercontent.com/owner/repo/main/README.md ならテキスト本文がそのまま取れます。同じく公式ドキュメントには、API リファレンス用の *.json や llms.txt を公開しているケースが増えています。

それでも当該 URL を取りに行く必要があるなら、Claude in Chrome(Chrome MCP)にフォールバックします。プロンプトの中で、こう指示しています。

WebFetch でこのURLを試してください。もし 403 または空ページが返ったら、
mcp__Claude_in_Chrome__navigate でアクセスし、
mcp__Claude_in_Chrome__get_page_text で本文を読み取ってください。
URL: https://example.com/docs

Claude in Chrome は実ブラウザで動くため、Cloudflare のチャレンジを通過できる場合がほとんどです。私のアプリ事業(AdMob を含む収益化)でも、AdMob の管理画面のような JavaScript 重めの SaaS は Chrome MCP 経由でないと触れません。

curl や wget を Bash ツールから叩く方法もありますが、Cowork モードや一部の環境ではネットワーク制限により失敗します。さらに WebFetch を回避する目的での bash 経由のフェッチは Cowork の方針として推奨されていません。Claude in Chrome を使うほうが筋が良いです。

原因2: クライアントレンダリングのページで本文が空

レスポンスは 200 OK なのに、<main> の中身が「Loading...」や「Enable JavaScript」だけ、というケースです。これは原因1よりも厄介で、エラーが出ないため気づきにくいのが特徴です。

代表的なサインは次のようなものです。

  • ナビゲーションのリンク群は読めるのに、記事本文が見つからない
  • 検索結果のリストが「0件」と表示される(実際にはサイトに記事が存在する)
  • 価格表のテーブルが空欄

これは React や Next.js などで構築された SPA で起きます。初期 HTML にはアプリケーションのシェルしか含まれず、本文は fetch() 後にクライアントで描画されるためです。

対処: SSR の有無を確認し、Claude in Chrome へ切り替える

切り分けは、ブラウザの「ページのソースを表示」(View Source)で対象の本文テキストが含まれているかどうかで判断できます。含まれていなければ WebFetch では取れません。

最近の Next.js なら App Router 化で SSR されている場合もありますが、Vercel デプロイの古い構成や、Vite + React + React Router の構成では、本文がクライアントレンダリングのままになっていることが多いです。

この場合、私のワークフローは以下のようになります。

このページは SPA で、WebFetch では本文が取れない可能性が高いです。
mcp__Claude_in_Chrome__navigate でアクセスしてから、
mcp__Claude_in_Chrome__get_page_text でレンダリング後の本文を取得してください。

私が運営する Lab 系4サイト(Claude Lab / Gemini Lab / Antigravity Lab / Rork Lab)も Next.js 16 + App Router 構成ですが、念のためビルド後の view-source: で記事本文が HTML に含まれていることを確認するようにしています。WebFetch で取れることは、AI クローラに対するアクセシビリティそのものでもあるからです。

原因3: ドメイン許可リスト(--allowedDomains)で事前ブロック

Claude Code を CI や定期実行で動かす運用では、--allowedDomains でフェッチ可能なドメインを絞り込んでいるケースが少なくありません。この場合、許可対象外のドメインを WebFetch しようとすると、次のような表示が出ます。

WebFetch is not allowed for domain: stackoverflow.com
Allowed domains: docs.anthropic.com, github.com

仕様通りの挙動です。許可確認ダイアログを抑止しつつ、安全な範囲だけにフェッチを限定したいときに使うフラグですが、許可リストの更新を忘れると本番ジョブが静かに止まります。

対処

私は2014年から個人でアプリ開発を続けていますが、長く運用するほど許可リストは「育てる」ものになります。スクリプト側で固定するのではなく、設定ファイルに切り出しておくと管理が楽です。

# 例: ~/.claude-code/allowed-domains.txt として管理
docs.anthropic.com
www.anthropic.com
raw.githubusercontent.com
api.github.com
developer.apple.com
developer.android.com
admob.google.com
firebase.google.com

CI からは次のように渡します。

claude code --allowedDomains "$(paste -sd, ~/.claude-code/allowed-domains.txt)" ...

新規ドメインへのアクセスが必要になった時は、許可リストへの追記を Pull Request にして、変更履歴を残しておくと、後から「なぜこのドメインを許可したのか」を辿れます。

原因4: 古いキャッシュが返ってきている

WebFetch は内部で短時間のキャッシュを持っており、同一 URL に対しての再リクエストはキャッシュから返されることがあります。リアルタイムのステータスページや、価格を確認したいページで、「更新したはずなのに変わらない」という現象の正体はこれです。

対処

シンプルですが、URL にクエリパラメータを追加するのが最も確実です。

https://example.com/status?_=1716120000

末尾の _= パラメータは多くのサーバーで無視されるため、コンテンツには影響しません。一方、WebFetch にとっては「別の URL」として扱われ、キャッシュをバイパスできます。

ただし、本来キャッシュは料金とレイテンシの両方を抑えるための仕組みです。やみくもにバイパスするとコストに跳ね返るので、本当にリアルタイム性が必要な場面に限定するのがコツです。私の運用では、毎朝の SEO レポート生成(GA / GSC)のように 24 時間で更新される情報には、URL に日付付きパラメータを足すようにしています。

切り分けの順序を固定しておく

実運用で大事なのは、「いま起きている現象が4つのどれなのか」を最短で見極めることです。私が日常的に使っているチェックリストはこの順序です。

  1. レスポンスのステータスコードを確認します。403 / 429 なら原因1、200 なら原因2 か 4 を疑います
  2. view-source: で本文 HTML が含まれているかを確認します。含まれていなければ原因2、Claude in Chrome へ切り替えます
  3. --allowedDomains の設定を確認します。CI 環境で動かしているなら最優先で確認します
  4. URL にダミークエリを足して再フェッチします。それで結果が変わるなら原因4です

ここまで切り分けても解決しないことは、私の経験ではほとんどありません。逆に言えば、原因不明のまま何度も WebFetch を叩き続けると、API 利用料だけが積み上がっていくので、最初の段階で見極める習慣をつけたほうが結果的に安く済みます。

次のアクション

WebFetch で詰まった時の現実的な次の一歩を一つだけ挙げるなら、Claude in Chrome(Chrome MCP)を別チャネルとして常に手元に置いておく ことだと感じています。Cowork の右上から有効化できますし、403 と空ページの両方を一度に解消できます。私自身、Lab 系サイトの自動運用と、累計5,000万ダウンロードのアプリ事業の両方でこの組み合わせを使っていますが、運用コストの観点でも安定性の観点でも、フォールバック先を一つ用意しておくことの価値は大きいです。

実装の参考になれば幸いです。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ Claude Code2026-05-24
Claude Code で連続する Edit が連鎖的に失敗するときの直し方 — old_string が消える・重複する問題
Claude Code が同じファイルへ Edit を連続で投げると、2件目以降が突然『not found』や『not unique』で落ちることがあります。原因は順序依存とコンテキスト二重化で、Read 再実行と分割パッチで救えます。
⟐ Claude Code2026-05-10
Claude Code の Glob と Grep が0件を返すときの原因切り分け
Claude Code の Glob/Grep ツールがファイルを見つけられないとき、.gitignore除外・隠しファイル・パターン記法の落とし穴を切り分け、適切な代替手段で確実に発見する手順をまとめます。
⟐ Claude Code2026-05-10
Claude Code の Read が大きなファイルを最後まで読まないとき — PARTIAL view の受け取り方と offset / limit の設計
Read が大きなファイルを途中までしか返さないとき、Claude Code は PARTIAL view の通知を出しています。通知の受け取り方と、行数ではなくバイト予算で offset / limit を決める方法を、実測値とともにお伝えします。