Google スプレッドシートでWebサイトのURLリストや参照リンクを管理している際、「リンク切れ(404 Not Found)になっているページがないか一括で確認したい」という場面はよくあります。
しかし結論から言うと、「指定したURLのWebページが実際に存在するか(サーバーが正常に応答するか)」を直接判定する専用の標準関数は、Google スプレッドシートには用意されていません。
名前が似ている ISURL 関数がありますが、これは文字列がURLの形式になっているかをチェックするだけで、実際にWebページへアクセスして存在を確認する機能はありません。
本記事では、標準関数の IMPORTXML を活用してページのタイトルタグ取得成否から存在を判定する仕組みと、通常は配列展開できない IMPORTXML を MAP 関数と LAMBDA を使って列の末尾まで1つの数式で自動展開(スピル)させる実践テクニック、そして実務運用で発生しやすい誤判定やトラブルなどの重要注意点を詳しく解説します。
専用の存在チェック関数がない理由とISURLの落とし穴
スプレッドシートにはURLを扱う関数として ISURL が用意されていますが、リンク切れの検知には使用できません。
しかし、ISURL 関数が判定しているのは、あくまで「入力された文字列がURLの書式(http:// や https:// から始まっているかなど)を満たしているかどうか」という構文チェックのみです。
ISURL 関数の動作例
=ISURL("https://example.com/not-found-page")→ TRUE(存在しないURLでも書式が合っていればTRUE)=ISURL("ただの文字列")→ FALSE
このように、実際にページが削除されて404エラーになっていても、ドメインの有効期限が切れていても、ISURL はすべて「TRUE(URLである)」と返してしまいます。
つまり、スプレッドシート上で「ページが生きているか(リンク切れしていないか)」を調べるには、別の方法でWebページへの通信結果を判定する必要があります。
標準関数で代用する仕組み(IMPORTXMLとISERRORの組み合わせ)
Google Apps Script(GAS)を使わずに標準関数だけで存在チェックを行う場合、最も実用的なアプローチが IMPORTXML 関数と ISERROR 関数の組み合わせ です。

判定ロジックの考え方
IMPORTXML は、指定したURLのWebページからXPathを使って特定のHTML要素を取得する関数です。
Webページが存在し正常にアクセスできる場合、HTML内には通常 <title> タグが存在します。そこで、XPathに "//title" を指定してタイトルタグを読み取りに行きます。
- ページが存在する場合(200 OK): ページのタイトルテキストが正常に取得される。
- ページが存在しない場合(404 Not Found など): GoogleサーバーがHTMLを取得できず、
IMPORTXMLは取得不可のエラー(#N/A 等)を返す。
この「エラーになるかどうか」を ISERROR 関数で判定することで、ページが存在するかどうかを疑似的に判別します。
単一行(D2セルなど)で使う基本数式
C2セルにURLが入力されている場合、判定結果を表示したいセル(D2セル)に以下の数式を入力します。
=IF(C2="", "", IF(ISERROR(IMPORTXML(C2, "//title")), "なし", "あり"))
数式の各パーツの役割は以下の通りです。
IF(C2="", "", ...):C2セルが空欄の場合は何も表示せず空欄にします。IMPORTXML(C2, "//title"):C2セルのURLへアクセスし、ページタイトルを取得します。ISERROR(...):IMPORTXMLがエラーになった場合は TRUE、タイトルが正常に取得できた場合は FALSE を返します。IF(..., "なし", "あり"):エラー(TRUE)なら「なし」、正常取得(FALSE)なら「あり」と出力します。
1つの数式で末尾まで自動展開する(MAPとLAMBDAの連携)
実務では、数百行におよぶURLリストをチェックすることがよくあります。
通常、数式を下方向へ自動展開させる際には ARRAYFORMULA を使いますが、IMPORTXML などの外部通信を伴うインポート系関数は ARRAYFORMULA による配列引数に対応していません。

MAP関数とLAMBDAによる配列展開
この課題を解決するのが、スプレッドシートのラムダヘルパー関数である MAP 関数 と LAMBDA の組み合わせです。
MAP 関数を使うと、指定したセル範囲の各行を1つずつ順番に引数として取り出し、指定した処理(LAMBDA内の計算)を実行してくれます。これにより、IMPORTXML でもエラーを起こさずに末尾行まで自動展開(スピル)が可能になります。
コピペで使える自動展開数式
D2セルに以下の数式を1つだけ入力します。
=MAP(C2:C, LAMBDA(url, IF(url="", "", IF(ISERROR(IMPORTXML(url, "//title")), "なし", "あり"))))
数式のポイント
- MAP(C2:C, LAMBDA(url, …)): C列の各行を1つずつ「url」という変数に代入して順次処理するため、ARRAYFORMULAで起きる制約を回避できます。
- url=”” の空行除外: URLが入力されていない行に対しては空白(
"")を出力するため、データが存在しない下の行に余計な判定が表示されません。 - D2セルのみに入力: この数式はD2セルから下方向へ自動的にスピル(結果を展開)します。D3以降のセルにあらかじめ値や数式が入っていると「#REF!(展開先が空ではありません)」エラーになるため、D3以降は必ず空欄にしてください。
実務運用で知っておくべき重要注意点(誤判定やトラブルの主な原因)
この数式は構文(書き方)としては成立しており、数十件程度の簡易確認であれば動作しますが、実際の業務運用では誤判定やトラブルが発生しやすいため注意が必要です。
現場で運用する際に「無理が生じやすい(挙動が不安定になる)」主な理由は以下の通りです。
うまく機能しにくい4つの主な理由
- 通信タイムアウト・遅延による「誤判定」:
IMPORTXML は外部サーバーへ通信してデータを取得します。Google側の通信遅延やタイムアウト(「データを読み込んでいます…」の状態)が発生すると、数式側では「エラー」とみなされてしまいます。その結果、実際にはWebページが正常に存在しているにもかかわらず「なし」と判定される現象が頻繁に発生します。 - 全行指定(C2:Cなど)による同時アクセス制限(クォータ制限):
C2:C のように列全体を指定すると、シートの空行も含めて数百〜千行単位で一度に外部リクエストが走ります。スプレッドシートの外部データ取得関数には同時実行数の上限制限があるため、途中でリクエストが弾かれ、エラーが多発する大きな原因になります。 - 404エラーページに <title> が存在する場合の誤判定:
Webサーバーの設定によっては、ページが存在しない(404 Not Found)場合でも、「404 Not Found」や「お探しのページは見つかりませんでした」といったタイトルのHTMLページを返す仕様になっているケースが多々あります。この場合、タイトルタグ自体は正常に取得できてしまうため、リンク切れ(ページ不在)なのに「あり」と誤判定されてしまいます。 - シートを開くたびに再計算が走り非常に重くなる:
数式による判定の場合、スプレッドシートを開き直したり任意のセルを編集するたびに、すべてのURLへの外部Webアクセスが再実行されます。そのためシート全体の動作が著しく重くなり、開くたびに結果が変わってしまうなど、挙動が安定しません。
その他の制限事項
- サイト側のセキュリティ制限(Bot遮断): CloudflareなどのBot対策やWAFが導入されているサイトでは、Googleサーバーからの通信が弾かれて「なし」と判定されます。
- タイトルタグのないURL: PDFファイル、画像、ZIPファイルなどの直接URLは、ファイルが実在していてもタイトルが存在しないため「なし」になります。
- HTTPステータスコードの区別不可: 「200(正常)」「301(転送)」「404(不在)」「500(サーバー障害)」を識別できません。
【根本解決】シートを開いた時に自動再計算するGAS実装ガイド
404誤判定を防ぎ、スプレッドシートを開いたタイミングで自動的に最新のリンクチェックを実行するGASの具体的な実装コード・トリガー設定手順は、以下の別記事で詳しく解説しています。
→ スプレッドシートを開く時にリンク切れを自動再計算するGAS・HTTPステータスで確実に一括判定する実装手順
大量チェックや確実な判定を行いたい場合の代替手段
「数百件以上のURLを安定してチェックしたい」「404エラーページを確実に検出したい」「シートを軽く保ちたい」という場合は、数式による判定ではなく、Google Apps Script(GAS)で結果をセルに書き込む方法が最も現実的で確実です。
Google Apps Script(GAS)で一括判定するスクリプト
GASの UrlFetchApp.fetch メソッドを使用すれば、タイトルタグの有無ではなく、Webサーバーが返す実際のHTTPレスポンスコード(200、404等)を直接判定できます。
さらに、数式ではなく「判定結果の文字列(あり/なし)」をセルに直接一括書き込みするため、シートを開き直すたびに再計算が走って重くなるトラブルも完全に回避できます。
/*
* B列のURLをチェックし、C列に「あり」「なし」を一括書き込みします
*/
function checkUrlValidity() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
if (lastRow < 2) return;
// B2から最終行までのURLを取得
const urls = sheet.getRange(2, 2, lastRow - 1, 1).getValues();
const results = [];
for (let i = 0; i < urls.length; i++) {
const url = urls[i][0];
if (!url || typeof url !== "string" || !url.startsWith("http")) {
results.push(["なし"]);
continue;
}
try {
const response = UrlFetchApp.fetch(url, {
muteHttpExceptions: true,
followRedirects: true
});
const statusCode = response.getResponseCode();
// 200番台(正常にアクセス可能)なら「あり」
if (statusCode >= 200 && statusCode < 300) {
results.push(["あり"]);
} else {
results.push(["なし"]);
}
} catch (e) {
results.push(["なし"]);
}
}
// C列に一括反映
sheet.getRange(2, 3, results.length, 1).setValues(results);
}
専用リンクチェッカーツールの利用
サイト全体の数千〜数万URLを調査する場合や、SEO内部監査を行う場合は、スプレッドシートではなく専用ツールの利用が効率的です。
- Screaming Frog SEO Spider: サイト内の内部・外部リンク切れやリダイレクトチェーンを高速かつ詳細にスキャンできる業界標準ツール。
- ブラウザ拡張機能(Check My Links など): 開いているWebページ上のリンク切れをワンクリックで視覚的にハイライト。
まとめ(標準関数とスクリプトの賢い使い分け)
Webサイト内のリンク切れを放置することは、ユーザーの離脱を招くだけでなく、検索エンジンのクローラーが無駄なリクエストを消費し、SEO評価にも悪影響を及ぼします。
用途に応じた使い分けの目安
- 標準関数(IMPORTXML + MAP): 数十件程度の小規模なリストで、GASを使わずにその場で大まかな存在確認をしたいときの簡易チェック向け(タイムアウトや404ページのタイトル誤判定に注意)。
- Google Apps Script(GAS): 数十〜数百件以上のURLを誤判定なく確実に判定したい場合、またはシートの動作を軽く保ちたい場合の本番運用向け。
- 専用ツール(Screaming Frog等): サイト全体のリンク切れ一括監査や定期巡回向け。
手軽さの裏にある「タイムアウト誤判定」「404ページのタイトル取得問題」「シート再計算負荷」といった制約を理解した上で、用途に合わせて最適な手法を選択してください。
