URLの実在性を検証するとき、最初に確認するのはHTTPステータスコードです。curl で 200 OK が返れば、検証スクリプトは成功と判定しがちです。

しかし、記事の脚注に使うURLでは、HTTPリクエストが成功しただけでは足りません。保存された過去の執筆セッションには、curlベースのURL検証で 200 だったX.comのURLが、同じURLをWebFetchで取得した段階では 402 Payment Required となり、本文を取得できなかった一例が残っています1。そのURLは、読める根拠として確認できなかったため、脚注から外されました。

URL検証の合格とは、HTTP 200 OK を受け取ることではありません。記事で使う取得層が、根拠となる本文を読み、記事の主張との対応まで確認できることです。

この記事では、HTTPステータスを確認する段階を「HTTP層」、返されたデータと期待語を確認する段階を「本文層」、記事で実際に根拠本文を読む手段を「記事取得層」と呼びます。これは取得結果を整理するための呼び方です。

curlで200 OKなのにWebFetchで読めないのはなぜか

保存された一つの事例を、確認できた事実だけに分けると次のようになります。

時点取得層記録された結果判断できること
過去のURL検証curlベースの検証X.comの投稿候補1件が 200HTTP層では成功として記録された
同じ執筆セッションWebFetch402 Payment Required、本文未取得記事で読む本文は取得できなかった
編集判断脚注の採否取得不能候補を除外読めない根拠を採用しなかった

ここから言えるのは、検証した取得層と、記事本文を読むための取得層で結果が一致しなかったことです。現在も同じ応答になることや、402 の原因が支払い・認証・Bot対策のどれかまでは、この一例から判断できません。

この切り分けが重要なのは、脚注の価値が「URLが応答したこと」ではなく、「読者が根拠をたどり、記事の主張を確かめられること」にあるからです。

HTTP 200 OKとは何を保証するのか

HTTP 200 OK は、リクエストが成功したことを示すステータスです。GETの成功レスポンスでは、対象リソースの現在の表現を返す意味を持ちます2。

ただし、ステータスコードと返された表現の内容は別の観測対象です。HTTPの表現はメタデータとデータから構成され、Content-Type はその表現のメディアタイプを示します。Content-Type: text/html であっても、それが期待する記事本文であることや、その本文が引用したい主張と一致することまでは示しません2。

リダイレクトも同じです。curl -L で最終的に 200 になった場合、入力URLが直接本文を返したのではなく、別のURLを経由した結果かもしれません2。入力URL、最終URL、リダイレクト数は分けて記録する必要があります。

Google Searchの技術要件も、Googlebotがブロックされないこと、HTTP 200、indexable contentを別々の条件として扱っています。これらを満たしても、インデックス登録は保証されません3。また、Googleのクローラー向け説明では、200 の応答でも空ページやエラー内容なら soft 404 として扱われる場合があります4。主コンテンツがほとんどないページや、レンダリング後にエラーを表示するページも、ステータスコードだけでは見落とすことがあります5。

したがって、HTTP 200 OK とは「HTTPリクエストが成功した」という入口の合格です。引用したい本文が存在し、正しい内容で、記事で使う取得層から読めることまでは保証しません。

curlとブラウザー・Headless・WebFetchの違い

同じURLでも、取得層によって送る情報、実行する処理、保持する状態が異なります。どれが優れているかではなく、どこまで観測できるかを比較します。

取得層主に確認できるもの別途確認が必要なもの記事での役割
curlのHTTPリクエストステータス、ヘッダー、本文、最終URLJavaScript実行、ブラウザー信号、サービス固有の処理HTTP層と本文層の計測
ブラウザー/HeadlessJavaScript実行後のDOM、環境によってCookieやセッション実行環境ごとの判定差、サービス固有の制限レンダリング後の確認
WebFetchなど記事取得層そのサービスが返した本文、取得エラーcurlや別ブラウザーと同じ本文かどうか脚注を読む層の最終確認
編集上の採用判定根拠本文と記事の主張の対応取得不能の原因の断定採用・未確認・代替の判断

URL検証の三層モデル。HTTP応答、本文の内容確認、記事で根拠を読む取得層を左から右へ分け、最後に読めない分岐を警告色で示した図

User-Agentはリクエストを開始したソフトウェアを示す情報で、サーバーがレスポンスの調整に使うこともあります2。しかし、User-Agent文字列をブラウザー風に変えるだけで、JavaScript、Cookie、セッション、ブラウザー信号まで再現できるわけではありません。MDNも、User-Agentによるブラウザー判定は偽装できるため信頼性が低いと説明しています6。

Bot検出やチャレンジの仕組みを持つサービスでは、ヘッダー、セッションの特性、ブラウザー信号、JavaScriptなど複数の要素が判定に使われることがあります7。Cloudflareの資料でも、チャレンジはクライアント側の処理やブラウザー信号を前提にし、目的URLの前にチャレンジページを置く仕組みが説明されています89。これは取得層の違いを理解する一般的な背景であり、今回のX.comの 402 の原因を示すものではありません。

402 Payment Required についても、ステータスコードだけで支払いが必要だと判断してはいけません。RFC 9110では 402 は将来用途のために予約されているため、今回の記録から 402 の原因を認証や特定の制御方式と断定することはできません2。確実に言えるのは、その取得層では本文を読めなかったという結果です。

出典URLを二段階で検収するやり方

脚注候補の検収は、次の二段階に分けます。

  1. HTTP・本文層を確認する: ステータス、最終URL、ヘッダー、本文が意図した資料かを確認します。
  2. 記事取得層を確認する: 実際に脚注を読むWebFetch、ブラウザー、Headlessなどで、根拠本文を読み、記事の主張との対応を確認します。

200 は第1段階の入口にすぎません。第2段階を通過して初めて、記事の出典として採用できます。下表の項目1〜4が第1段階(HTTP・本文層の確認)、項目5が第2段階(記事取得層の確認)に対応します。

項目確認内容合格条件不合格時の扱い
1HTTPステータス想定した成功条件を満たす未確認として保留
2最終URL・リダイレクト意図した記事・資料を指すリダイレクト先を再確認
3ヘッダー・Content-Typeメディアタイプや圧縮を記録し、想定外を検出できる本文検証前に切り分ける
4本文空本文、エラー・チャレンジ兆候、期待する固有語を確認できる未確認または代替出典へ降格
5実際の記事取得層根拠本文を読み、主張との対応を確認できる脚注に採用しない

curl側の計測は、例えば次のように書けます。これはHTTP層と本文層を確認する設計例であり、今回のX.com URLを現在再計測した結果ではありません。

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

curl -sS -L --compressed \
  -A 'url-check/1.0' \
  -D "$tmp_dir/headers" \
  -o "$tmp_dir/body" \
  -w 'status=%{http_code}\nfinal_url=%{url_effective}\ncontent_type=%{content_type}\nredirects=%{num_redirects}\nbytes=%{size_download}\n' \
  "$url"

rg -n '期待する見出しや固有語' "$tmp_dir/body"

-L でリダイレクトを追跡し、-D でヘッダーを保存し、-w でステータスや最終URLなどの計測値を出力しています。-I は本文を取得しないHEADリクエストなので、本文の存在や期待語を確認する検証とは分けて考えます10。

ただし、この例で確認できるのはcurl側の結果までです。WebFetchやブラウザーで本文を読めることを証明するには、実際に記事で利用する取得層でも確認し、その結果を別に記録します。

脚注の出典URLを採用してよい条件とは何か

出典URLについて、次の三つを分けて記録します。

  • 存在する: URLへのリクエストが応答した。
  • 本文を取得できる: 返されたデータに、空本文・エラー・チャレンジ画面ではなく、確認対象の本文がある。
  • 根拠として読める: 記事で使う取得層から本文を読み、主張との対応を確認できる。

HTTP検証だけが成功したURLは「HTTP確認済み・本文未確認」として採用を保留します。本文は取得できても、期待した主張との対応が不明なら脚注には採用しません。記事で使う取得層から本文と主張の対応まで確認できたものだけを、脚注候補に進めます。

取得不能なURLについては、アクセス制限を回避する方向へ進むのではなく、取得不能だった事実と理由を記録し、代替の一次情報源を探します。HTTP 200 を返す soft 404 など、ステータスコードだけの別の検証ミスについては、URL検証で起きた別の罠でも扱っています。

URL検証スクリプトに何を記録するのがよいか

ステータスコードを捨てる必要はありません。合格判定の一項目として位置づけ、後から「どの層で何が見えたか」を追える形にします。

分類フィールド例目的
時間・入力observed_at, input_url, methodいつ、何を、どのメソッドで見たかを固定
HTTPcurl_exit, status, final_url, redirects通信結果とリダイレクト後の対象を分離
表現content_type, content_encoding, bytes, body_hash返ったデータの形式と量を記録
本文empty, error_marker, challenge_marker, expected_termsoft errorやチャレンジ兆候を検出
取得層fetch_layer, readable, extracted_chars, claim_match記事で使う取得層の可読性を判断
判断verdict, reason, alternative_source採用・未確認・代替の経緯を残す

このフィールド設計は、HTTP仕様や各サービスの資料を組み合わせた実務上の提案です。すべてのサイトに共通する公式の合格規格ではありません。重要なのは、200 だけを残すのではなく、最終URL、本文の兆候、取得層、主張との一致、採用理由を同じ検証記録に置くことです。

よくある疑問:脚注URLの検証をどう考えるか

curlでHTTP 200なのにWebFetchで読めないのはなぜか

取得層が違うため、結果が一致しないことがあります。 200 はHTTPリクエストの成功を示しますが、WebFetch側の取得処理、JavaScript、Cookie、セッション、ブラウザー信号、サービス固有の制約まで同じとは限りません。今回の事例では差が記録されていますが、原因は確定していません。

HTTP 200 OKだけでURL検証してよいか

脚注の採用判定としては不十分です。 最終URL、Content-Type、本文の存在と期待語、記事で使う取得層による本文の可読性、そして主張との対応まで確認します。

402 Payment Requiredなら支払いが必要か

ステータスコードだけでは判断できません。 402 は将来用途のために予約されたコードなので、まずは本文取得不能として脚注採用を保留し、代替の一次情報源を探します。

まとめ:200から本文可読性へ合格条件を更新する

200 OK はHTTP層の成功であり、記事の根拠本文が読めることとは別です。curl、ブラウザー、Headless、WebFetchは観測する層が違うため、記事の採用条件にする取得層を先に決めます。

取得層の差の原因を推測するより、本文を読めない出典を 未確認 に降格し、代替出典へ切り替える方が編集上の判断を再現できます。自分の検証スクリプトにも、最終URL、ヘッダー、本文、取得層、検証時刻、採用理由を追加してみてください。

検証スクリプトやAIを使った情報収集パイプラインの品質改善を検討している場合は、コンタクトフォームから相談できます。

Footnotes

  1. 手元の一次計測記録、2026年8月23日検算済み。保存された過去の一事例について、curlベースのURL検証が 200、同じURLのWebFetchが 402 Payment Required、レスポンス本文未取得、取得不能候補を脚注から除外したことを確認できる。現在の再現性、レスポンスの詳細、402 の原因、他SNSへの一般化は確認対象外。 ↩

  2. HTTP Semantics RFC 9110 IETF、2022年6月、Standards Track。200 OK は §15.3.1、表現メタデータと表現データは §3.2、Content-Type は §8.3、リダイレクトは §15.4、User-Agent は §10.1.5、402 Payment Required は §15.5.3。この記事では各節の定義を要約しており、今回の取得結果やWebFetchの仕様を説明する資料ではありません。 ↩ ↩2 ↩3 ↩4 ↩5

  3. Google Search technical requirements Google Search Central、2025年12月18日更新。Googlebotの到達、HTTP 200、indexable contentを別条件として示す「Google Search technical requirements」節。条件を満たしてもインデックス登録は保証されないという注記も同ページにある。Google Searchの要件をWebFetchやURL検証全般の公式規格へ拡張していません。 ↩

  4. How HTTP Status Codes Affect Google’s Crawlers Google Crawling Infrastructure、2026年2月4日更新。HTTP status codes節の 2xx と 200 (success) の説明、および空ページ・エラー内容が soft 404 になり得る説明。Googleクローラーの処理をWebFetchの挙動と同一視していません。 ↩

  5. Troubleshoot Google Search Crawling Errors Google Search Central、2025年12月18日更新。See if any parts of your site are not crawled, but should be 以下のクロールとインデックスの区別、およびページ可用性・レンダリングに関する説明。今回のX.com事例の原因を示す資料ではありません。 ↩

  6. Browser detection using the user agent string MDN Web Docs、2026年1月6日更新。User-Agentによるブラウザー判定の信頼性と偽装可能性を説明する「Why detecting browsers using the user agent string is unreliable」付近。User-Agent変更だけでブラウザーの状態を再現できるとは述べていません。 ↩

  7. Bot detection engines Cloudflare、2026年5月5日更新。Bot Detection Enginesの説明とJavaScript detections節。User-Agentだけでなく、ヘッダー、セッション特性、ブラウザー信号、JavaScriptなど複数の検出要素を扱う背景として参照しています。対象URLがCloudflareを利用していたという根拠には使っていません。 ↩

  8. How Challenges work Cloudflare、2026年7月6日更新。Available challenges節とチャレンジ種別の対応表。チャレンジがクライアント側の処理やブラウザー信号と関係する一般的な背景として参照しています。 ↩

  9. Interstitial Challenge Pages Cloudflare、2026年7月6日更新。Interstitial Challenge Pages節、特に目的URLの前に表示されるゲートと、JavaScriptでブラウザー信号を評価する説明。今回の 402 の原因を説明する資料ではありません。 ↩

  10. curl man page curl project、ページ上の発行日・版の記載なし、2026年8月23日直接取得。-I, --head、-L, --location、-D, --dump-header、-w, --write-out の各オプション説明。本文を保存しながらヘッダー、最終URL、ステータス、サイズを記録する実装例の根拠として参照しています。実装例そのものは記事上の提案です。 ↩