リンク切れ監視で「200が返ったから大丈夫」と判定していませんか。実際には、URLの一部が間違っていてもサーバーが 301 で正解へ転送してくれることがあります。転送を追う監視ツールから見ると、間違ったURLも正しいURLもまったく同じ「200」です。2026年8月4日に実測した結果をもとに、この盲点と検出方法を整理します。
curl で実際に取得した結果です。挙動はサービス側の実装変更で変わりうるため、参考にする際はご自身の環境で追試してください。手順は本文に記載しています。
リンク切れ監視が見落とすもの
社内のリンク集、記事内の参照リンク、ブックマークの棚卸し。URL が生きているかを機械的に確かめたいとき、多くの実装は次のことをします。
- URL に GET(または HEAD)を投げる
- リダイレクトを追う
- 最終的なステータスが 2xx なら「生きている」と記録する
この方法は「URL が壊れているか」は検出できますが、「URL が間違っているか」は検出できません。両者は違います。前者はサーバーが 404 を返す状態、後者はサーバーが親切に正解へ転送してくれるせいで、間違いのまま 200 が返る状態です。
実測:ユーザー名が間違っていても 200 が返る
記事URLに投稿者名が含まれるサービスでは、この現象が起きやすくなります。ある技術記事共有サービスで、実在する記事のスラッグを使い、パスのユーザー名部分だけを変えてアクセスした結果が次のとおりです(2026年8月4日測定)。
| リクエストしたURLの形 | ステータス | Location |
|---|---|---|
| 正しい投稿者名 + 実在するスラッグ | 200 | (なし) |
| 別人の実在する投稿者名 + 実在するスラッグ | 301 | 正しい投稿者のURL(?redirected=1 付き) |
| 存在しない投稿者名 + 実在するスラッグ | 301 | 同上 |
| 正しい投稿者名 + 存在しないスラッグ | 404 | (なし) |
読み取れることは明快です。このサービスは記事をスラッグだけで解決しており、パスのユーザー名部分は権威を持っていません。存在しないユーザー名を書いても、実在する別人の名前を書いても、301 で真の所有者のURLへ吸収されます。逆に、スラッグが存在しなければユーザー名が正しくても 404 です。
リダイレクトを追う監視ツールから見ると、これらはすべて「最終 200」です。ユーザー名を書き間違えたリンクも、投稿者が改名した後の古いリンクも、まったく同じく健全に見えます。
何が困るのか
- 所有者の取り違えに気づけない。 「Aさんの記事」としてリンクしていたつもりが、実は別人の記事だった、という誤りが 200 の陰に隠れます。
- 改名の追跡ができない。 引用元の著者が名前を変えても、リンクは通り続けるので、表示している著者名だけが古いまま残ります。
- 正規URLに揃わない。 検索エンジンには canonical で正解が伝わりますが、自分の管理下にあるリンク集の中身は古いままです。集計や重複排除をURL文字列で行っていると、同じ記事が複数の見た目で残ります。
- コピペ由来の事故が残り続ける。 手でURLを組み立てたときのタイプミスが、一度も赤くならないまま定着します。
検出する方法1:リクエストしたURLと最終URLを比べる
いちばん簡単で、どのサービスにも効く方法です。リダイレクトを追ったうえで、最終URLが元のURLと一致しているかを確認します。curl なら %{url_effective} を出力すれば取れます。
# 追跡した最終URLとステータスを並べて出す curl -sL -o /dev/null \ -w 'status=%{http_code}\nfinal=%{url_effective}\n' \ "$URL" # リダイレクトを追わず、3xx をそのまま観測する curl -s -o /dev/null \ -w 'status=%{http_code}\nlocation=%{redirect_url}\n' \ "$URL"
監視の判定を次のように分けると、見落としが消えます。
| 観測 | 意味 | 扱い |
|---|---|---|
| 200、かつ最終URL=元のURL | URLが正しく、生きている | OK |
| 200 だが最終URLが元のURLと異なる | 転送されている。元のURLは古いか誤っている | 要確認(リンクを最終URLへ更新する) |
| 3xx(追わない設定で観測) | 同上 | 要確認 |
| 4xx / 5xx | 壊れている | NG |
比較の際は、サービスが付ける追跡用クエリを無視するのを忘れないでください。上の実測では転送先に ?redirected=1 が付きます。これを含めたまま文字列比較すると、正しく更新した後も永久に「不一致」と判定され続けます。クエリを落としてから比べるか、既知のパラメータを除去してから比べます。
検出する方法2:公開APIで所有者を突き合わせる
URLの一致だけでは「誰の記事か」までは分かりません。サービスが公開APIを持っている場合、ユーザー名で記事一覧を取得し、そこに目的のスラッグが含まれるかを確かめるのが確実です。上のサービスには認証不要のエンドポイントがあり、2026年8月4日時点で次の形の JSON を返しました。
# ユーザー名を指定して記事一覧を取る(認証不要・2026-08-04 実測) curl -s "https://zenn.dev/api/articles?username=<name>&order=latest" # レスポンスの形(抜粋) { "articles": [ { "slug": "66fc12c8dc1f61", "path": "/<name>/articles/66fc12c8dc1f61", "published_at": "2026-08-04T09:31:15.165+09:00", "article_type": "tech", "user": { "username": "<name>" } } ] }
この path は、そのユーザーの記事としての正規パスです。手元のリンク集にある URL のパスがここに含まれていなければ、ユーザー名が誤っている(あるいは記事の所有が移っている)と判定できます。ステータスコードでは絶対に分からない情報です。
一般化:URLのどの部分が「実体のキー」なのか
この話はひとつのサービスの癖ではなく、URL設計の一般的な性質です。多くのサイトで、URLは次の2種類の要素の組み合わせになっています。
- キー: 実体を一意に引くための部分(記事ID、スラッグ、ハッシュ)。ここが違えば 404 になる。
- 飾り: 人間が読むための部分(ユーザー名、カテゴリ名、記事タイトルのローマ字表記、日付)。ここが違ってもサーバーは正解へ転送してくれることがある。
自分が監視・集計しているURLについて、どこがキーでどこが飾りかを一度確かめておくと、誤検知と見落としの両方が減ります。確かめ方は簡単で、飾りだと思う部分をわざと壊してアクセスし、404 になるか 301 になるかを見るだけです。上の実測はまさにそれを行ったものです。
あわせて、リダイレクトの種類も見ておくと運用判断がしやすくなります。恒久的な移動(301 / 308)なら手元のリンクを書き換えるべきで、一時的な移動(302 / 307)なら書き換えるべきではありません。HTTP ステータスコード全体の整理は「HTTPステータスコード入門」にまとめています。
チェックリスト
- 監視ツールは最終URLを記録しているか。ステータスだけを見ていないか。
- 元のURLと最終URLを比較しているか。比較の前に追跡用クエリを除去しているか。
- 301 / 308 を「OK」ではなく「要更新」として扱っているか。
- URLに含まれる人名・カテゴリ名が正しいことを、URL以外の手段で確かめているか。
- APIを叩く監視は、間隔・User-Agent・キャッシュ・429 の扱いを決めているか。
実測の再現手順(2026年8月4日)
- 実在する記事のスラッグを公開APIから取得:
curl -s "https://zenn.dev/api/articles?order=latest" - ユーザー名部分を(1)正しい名前、(2)実在する別人の名前、(3)存在しない名前 に差し替えて
curl -s -o /dev/null -w '%{http_code} %{redirect_url}'を実行 - スラッグ部分を存在しない値に差し替えて同じ観測を実行
- 転送先ページの
<link rel="canonical">が真の所有者のURL(クエリなし)を指していることを確認
上記はすべて筆者が実行した結果です。サービス側の実装は変わりうるため、恒久的な仕様ではありません。
よくある質問(FAQ)
リンク監視で200が返れば、そのURLは正しいと言えますか?
言えません。URLの一部が間違っていても、サーバーが301で正しいURLへ転送する設計になっていることがあります。リダイレクトを追う監視ツールから見ると最終ステータスは200になるため、間違ったURLも健全に見えます。
間違ったURLを検出するにはどうすればよいですか?
リクエストしたURLと最終URLを比較します。curl なら -w '%{url_effective}' で最終URLを取得できます。比較の前に、サービスが付ける追跡用クエリ(例: ?redirected=1)を除去してください。リダイレクトを追わずに3xxをそのまま観測する方法も有効です。
URLに含まれるユーザー名が正しいかは、どうやって確かめますか?
ステータスコードでは分かりません。サービスが公開APIを持っている場合は、ユーザー名で記事一覧を取得し、目的のスラッグがその中に含まれるかを突き合わせます。含まれていなければ、ユーザー名が誤っているか所有が移っています。
URLのどの部分が間違っても転送されるのかを、どう見極めますか?
飾りだと思う部分をわざと壊してアクセスし、404になるか301になるかを見ます。404になる部分が実体を引く「キー」、301で吸収される部分が人間向けの「飾り」です。