「アクセスログにGPTBotやClaudeBotがたくさん来ているが、本当にOpenAIやAnthropicのクローラーなのか」。
AI検索対策を始めると、こうした疑問を持つWeb担当者の方が増えてきます。
結論から言うと、ログに書かれた名前だけでは、本物かどうか分かりません。
クローラーが名乗る「ユーザーエージェント」(アクセス元のプログラムが自己申告する名前)は、誰でも自由に書き換えられるからです。
この記事は、自社のサーバーやアクセスログを見られる、中小企業のWeb担当者向けです。
各社が公開しているIPアドレスの一覧、DNSを使った確認方法、動かせるスクリプト、なりすましを見つけたあとの対処を、順に説明します。
IPアドレスとは、インターネット上の住所にあたる番号です。DNSとは、ホスト名とIPアドレスを対応させる仕組みです。
内容は、2026年10月17日に各社の公式ドキュメントと、公開されているIP一覧のファイルを開いて確かめたものです。
ログの集計やAIからの訪問の見つけ方は、次の記事にあります。
ChatGPTで自社サイトがどう表示、引用されているかを確かめる方法
この記事は、そこで見つけたアクセスが「本物か」を確かめる手順に絞ります。
先に結論:確かめるときの6つのこと
結論を表にまとめます。右の列は、公式ページやIP一覧のファイルで確かめられたことです。
| 論点 | 確かめられたこと | この記事の判断 |
|---|---|---|
| 名前だけで判断できるか | Bingの公式ヘルプは、ユーザーエージェントは偽装しやすいと明記している | 名前だけで通さない |
| 何で確かめるか | 各社がIP一覧(JSONファイル)か、DNSでの確認方法を案内している | アクセス元のIPで確かめる |
| 一覧を公開している会社 | OpenAI、Anthropic、Perplexity、Google、Apple、Bingが一覧を公開している | まず一覧と照合する |
| DNSで確かめられる会社 | Google、Apple、Bingが、逆引きと正引きの手順を案内している | 一覧で判断できないときの再確認に使う |
| 見つけたあとの対応 | Perplexityは、名前とIPの両方を条件にするルールを案内している | 名前とIPの組み合わせで制限する |
| 一覧の更新 | 一覧ごとに作成日時が違う。Bingは毎日取り直すよう案内している | 自動で取り直す |
手順は3段階です。ログからIPを抜き出し、公開されている範囲と照合し、合わないものをDNSで確かめます。
この記事で使った情報源
使った情報源は、次の表のとおりです。
| 情報源 | 確かめた内容 |
|---|---|
| OpenAIの「Overview of OpenAI Crawlers」 | 4つのクローラーの役割と、IP一覧のURL |
| Anthropicのヘルプ記事 | 3つのクローラーの役割と、共通のIP一覧 |
| Perplexityの「Perplexity Crawlers」 | 2つのクローラー、IP一覧、WAFの設定例 |
| Googleの「Verify requests from Google crawlers and fetchers」 | 逆引きの手順、5つの一覧ファイル |
| Google検索セントラルのブログ(2026年3月31日) | 一覧ファイルの置き場所の変更 |
| Appleの「About Applebot」 | 逆引きのドメイン、IP一覧 |
| Bing Webmaster Toolsのヘルプ | 逆引きの手順、IP一覧、偽装への注意 |
| Cloudflareのドキュメント | 元の訪問者のIPを受け取るヘッダー |
| nginxの公式ドキュメント | geo、map、回数制限の書き方 |
公式ページは英語版が中心です。この記事では、日本語に直して説明しています。
なぜユーザーエージェントだけでは判断できないのか
AIクローラーの確認で、最初に押さえたいのは、名前と実体が別だという点です。
ユーザーエージェントは名札にすぎない
Webサイトにアクセスするプログラムは、「User-Agent」という項目で、自分の名前を伝えます。
これは受付で名札を見せるようなもので、名札は誰でも作れます。
Bing Webmaster Toolsのヘルプも、ユーザーエージェントの文字列は偽装しやすいと説明しています。
本物かどうかを調べるには、検証ツールなどでIPを確かめるよう案内しています。
Googleは、自社のクローラーを名乗る迷惑なアクセスを心配する人向けに、本物かどうかの確認方法を案内しています。
放置すると何が困るか
なりすましを放置したときに起きる問題を、表にします。
| 起きること | 内容 |
|---|---|
| 集計が狂う | AIクローラーの訪問だと思っていたものが別物だと、効果測定が正しくできない |
| 許可が抜け穴になる | 「GPTBotという名前なら制限しない」設定だと、名前を偽ったプログラムも通る |
| サーバーの負荷 | 大量のアクセスで表示が遅くなったり、サーバーの利用料が増えたりする |
一方で、なりすましが今すぐ問題になるサイトばかりではありません。
負荷がかかっていなければ、確認と記録から始めれば十分です。
確かめに使えるのはアクセス元のIP
名札は見ずに、どこから来たかを見ます。それがアクセス元のIPアドレスです。
各社は、自社のクローラーが使うIPアドレスを、一覧にして公開しています。
IPアドレスは、ユーザーエージェントのように、アクセスするプログラムが好きに書き換えられるものではありません。
一覧がない会社や、一覧と合わないIPは、DNSで確かめます。
確かめる方法は2つ:一覧との照合とDNS
確かめる方法は、大きく2つに分かれます。
方法1:公開されているIP範囲の一覧と照合する
各社が公開しているJSONファイルには、クローラーが使うIPの範囲が並んでいます。
ログのIPがその範囲に入っていれば、その会社のクローラーである可能性が高くなります。
件数が多いときは、スクリプトで機械的に照合できます。
方法2:逆引きと正引きのDNSで確かめる
IPアドレスからホスト名を調べるのが「逆引き」です。ホスト名からIPアドレスを調べるのが「正引き」です。
逆引きで出たホスト名が、その会社のドメインで終わり、正引きで元のIPに戻れば、本物と判断できます。
Google、Apple、Bingが、この方法を公式に案内しています。
流れの全体像
2つの方法を組み合わせた流れを、図にまとめます。
一覧で一致すれば、そこで確認は終わります。一致しないものだけを、DNSで確かめます。
各社が公開している確認方法の一覧
主なクローラーについて、本物を確かめる方法をまとめます。
2026年10月17日時点で、公式ページに書かれている内容と、実際に開いたファイルをもとにしています。
| 運営会社 | 主なクローラー名 | IP範囲の一覧 | 逆引きDNSでの確認 |
|---|---|---|---|
| OpenAI | GPTBot、OAI-SearchBot、ChatGPT-User、OAI-AdsBot | openai.com の gptbot.json、searchbot.json、chatgpt-user.json、adsbot.json | 読んだページに案内はなかった |
| Anthropic | ClaudeBot、Claude-User、Claude-SearchBot | claude.com/crawling/bots.json(3つ共通の1本) | 読んだページに案内はなかった |
| Perplexity | PerplexityBot、Perplexity-User | www.perplexity.com の perplexitybot.json、perplexity-user.json | 読んだページに案内はなかった |
| Googlebot など | developers.google.com/crawling/ipranges/ の5つのファイル | googlebot.com、google.com、googleusercontent.com | |
| Apple | Applebot | search.developer.apple.com/applebot.json | applebot.apple.com |
| Microsoft | Bingbot | www.bing.com/toolbox/bingbot.json | search.msn.com |
表の読み方
表の「読んだページに案内はなかった」は、私が読んだ公式ページに、逆引きDNSの手順が出てこなかったという意味です。
別のページに案内がある可能性までは、否定できません。
OpenAI、Anthropic、Perplexityの3社は、IP一覧との照合が基本の確認方法です。
Google、Apple、Bingは、一覧とDNSの両方を使えます。
OpenAIのクローラーを確かめる
OpenAIの公式ドキュメント「Overview of OpenAI Crawlers」は、4つのクローラーを紹介しています。
4つのクローラーと一覧の場所
| クローラー | 役割 | IP一覧 |
|---|---|---|
| OAI-SearchBot | ChatGPTの検索機能の結果に、サイトを表示するためのもの | openai.com/searchbot.json |
| GPTBot | 生成AIの基盤モデルの学習に使われる可能性のある内容を集めるもの | openai.com/gptbot.json |
| ChatGPT-User | ChatGPTやカスタムGPTでの、利用者の操作をきっかけにページを取りに来るもの | openai.com/chatgpt-user.json |
| OAI-AdsBot | ChatGPTの広告として登録されたページの安全性を確かめるもの | openai.com/adsbot.json |
名前と一覧の組み合わせまで見る
ログに「GPTBot」とあっても、IPがgptbot.jsonの範囲になければ、本物とはいえません。
名前と一覧の組み合わせまで見るのが、基本の考え方です。
名乗った名前と、一致した一覧が食い違う場合も、記録しておきましょう。
たとえば、GPTBotを名乗るIPが、searchbot.jsonにだけ載っているケースです。
ChatGPT-Userは巡回クローラーとは違う
ChatGPT-Userは、利用者の質問に答えるために動くものです。自動で巡回するクローラーではありません。
OpenAIは、利用者の操作によるものなので、robots.txtのルールが適用されない場合があると説明しています。
また、ChatGPT-Userは、検索結果に表示するかどうかの判断には使われないとも書かれています。
検索結果への表示を管理したいときは、OAI-SearchBotをrobots.txtで指定するよう案内されています。
OpenAIはさらに、OAI-SearchBotについて、サイトを検索結果に表示するには、公開されているIP範囲からのアクセスを許可するよう勧めています。
AIが自社サイトを閲覧する仕組みは、次の記事も参考になります。
Anthropicのクローラーを確かめる
Anthropicのヘルプ記事は、3つのクローラーを紹介しています。
3つのクローラーと、止めたときの影響
| クローラー | 役割 | 止めたときの影響(公式の説明) |
|---|---|---|
| ClaudeBot | モデルの学習に貢献しうるWebの内容を集める | 今後の内容が、学習用のデータから除外される |
| Claude-User | Claudeの利用者の質問に答えるため、サイトにアクセスする | 利用者の質問に対して内容を取得できなくなり、サイトの見え方が下がる可能性がある |
| Claude-SearchBot | 検索結果の質を高めるため、Webを巡回する | 検索のための索引づけができなくなり、サイトの見え方や正確さが下がる可能性がある |
3つ共通のIP一覧がある
AnthropicのIP一覧は、claude.com/crawling/bots.jsonの1本です。
OpenAIやPerplexityと違って、クローラーごとには分かれていません。
ヘルプ記事には、アクセス元のIPがこの一覧に載っていれば、Anthropicのクローラーだと分かる、という説明があります。
そのため、一覧に載っていても、ClaudeBotなのかClaude-Userなのかは、一覧だけでは区別できません。
IPでの遮断は、オプトアウトとして確実とは限らない
同じヘルプ記事は、学習用の収集を断るには、robots.txtを書き換える必要があるとしています。
IPアドレスで遮断する方法は、robots.txtを読む妨げになるため、確実な断り方として働かない場合があると説明されています。
本物かどうかの確認にはIP一覧を使い、断りたいときはrobots.txtを使う、と分けて考えるのが基本です。
Claudeの検索での見え方は、次の記事にまとめています。
Perplexityのクローラーを確かめる
Perplexityの公式ドキュメント「Perplexity Crawlers」には、2つのクローラーが載っています。
2つのクローラーと一覧の場所
| クローラー | 役割 | IP一覧 |
|---|---|---|
| PerplexityBot | 検索結果にサイトを表示し、リンクするためのもの。基盤モデルの学習には使わないと説明されている | www.perplexity.com/perplexitybot.json |
| Perplexity-User | 利用者の質問に答えるため、ページを取りに来るもの | www.perplexity.com/perplexity-user.json |
Perplexity-Userは、利用者の依頼による取得なので、一般にrobots.txtのルールを無視すると説明されています。
名前とIPの両方を条件にするルールが案内されている
同じページには、WAFの設定例が載っています。
CloudflareのWAFでは、ユーザーエージェントの条件と、IPの条件を、ANDで組み合わせる設定が例示されています。
AWS WAFでも、IPセットとユーザーエージェントの条件を組み合わせるルールが案内されています。
この設定例は、本物を通す「許可」のルールです。
名前とIPの両方を見るという考え方は、偽物を止める「遮断」のルールにも使えます。
取得先が転送される点に注意
公式ドキュメントに載っているURLは、www.perplexity.comのものです。
2026年10月17日に、手元のコマンドで取得すると、www.perplexity.aiへ転送されました。
自分で取得するスクリプトを書くときは、転送を追う作りにしておくと安全です。
Perplexityの引用の仕組みは、次の記事にあります。
Googleのクローラーを確かめる
Googleは「Verify requests from Google crawlers and fetchers」というページで、確かめ方を案内しています。
クローラーは3種類に分かれる
Googleのクローラーと取得ツールは、3つの種類に分けられています。
| 種類 | 説明 | 逆引きのホスト名の例 | IP一覧 |
|---|---|---|---|
| 一般的なクローラー | Googlebotなど。robots.txtを必ず守る | crawl-から始まる名前の googlebot.com | common-crawlers.json |
| 特定用途のクローラー | AdsBotなど。robots.txtを守る場合と、守らない場合がある | rate-limited-proxy-から始まる名前の google.com | special-crawlers.json |
| 利用者の操作で動く取得ツール | 利用者が取得を頼んだもの。robots.txtは無視される | google.com または gae.googleusercontent.com | user-triggered-fetchers-google.json、user-triggered-fetchers.json、user-triggered-agents.json |
一般的なクローラーの逆引きは、geo.googlebot.comのホスト名になることもあります。
手順は逆引きと正引きの2段
Googleが案内する手動の確認は、次の順です。
- ログのIPを、hostコマンドで逆引きする
- ホスト名が、googlebot.com、google.com、googleusercontent.comのどれかで終わるか確かめる
- そのホスト名を正引きして、元のIPに戻るか確かめる
自動で大量に調べるときは、IP一覧との照合が案内されています。
一覧のIPは、「192.0.2.0/24」のようなCIDR表記で書かれています。
一覧ファイルの置き場所が変わった
Google検索セントラルのブログ(2026年3月31日)に、置き場所の変更が載っています。
一覧ファイルは、/search/apis/ipranges/から/crawling/ipranges/へ移りました。
古い場所は、投稿から6か月以内に、新しい場所へ転送する予定とされています。
2026年10月17日に、旧来のgooglebot.jsonのURLを開くと、新しいcommon-crawlers.jsonへ転送されました。
古い名前のファイルを決め打ちしたスクリプトは、転送に頼る形になっています。
公式ページに載っているURLを使い、ときどき見直すのが安全です。
Appleのクローラーを確かめる
Appleのサポート記事「About Applebot」には、2つの確認方法があります。
逆引きと、IP一覧の2通り
1つ目は、逆引きで *.applebot.apple.com のホスト名になるかを見る方法です。
記事には、hostコマンドでの逆引きの例と、同じIPに戻ることを確かめる例が載っています。
2つ目は、記事内のリンクにある「Applebot IP CIDRs」のJSONファイルと照合する方法です。
ファイルのURLは、search.developer.apple.com/applebot.jsonです。
「一般に」という書き方に注意
Appleの記事は、Applebotからのアクセスを、逆引きで「一般に見分けられる」と書いています。
DNSでの確認は、一覧と合わせて使うと確実です。
Bingのクローラーを確かめる
Bing Webmaster Toolsのヘルプは、Bingbotの確認方法を3つ挙げています。
DNSとIP一覧と確認ツール
1つ目は、逆引きでsearch.msn.comで終わるホスト名になり、正引きで同じIPに戻ることを確かめる方法です。
2つ目は、IPを入れるだけで確かめられる「Verify Bingbot」ツールです。
3つ目は、Bingbotの公式IP一覧と照合する方法で、一覧のURLはwww.bing.com/toolbox/bingbot.jsonです。
一覧は毎日取り直す
Bingのヘルプには、一覧を毎日更新し直すよう書かれています。IPの一覧はいつでも変わりうるためです。
2012年の古い公式ブログには、IPの一覧は公開しないという記述がありました。
いまのヘルプでは一覧が案内されているので、古い記事の情報を信じないよう気をつけてください。
古い情報をもとに、IPを決め打ちで許可すると、新しいIPから来た本物のBingbotを止めてしまいます。
公開されている一覧の状態を見る
2026年10月17日に、各社のJSONファイルを実際に取得して、中身を確かめました。
ファイルごとの作成日時と件数
| 一覧 | 作成日時(ファイル内の値) | 範囲の件数 | IPv6の範囲 |
|---|---|---|---|
| OpenAI GPTBot | 2026年9月22日 | 18 | なし |
| OpenAI OAI-SearchBot | 2026年1月2日 | 39 | なし |
| OpenAI ChatGPT-User | 2026年10月7日 | 234 | なし |
| Anthropic | 2026年10月7日 | 38 | なし |
| PerplexityBot | 2025年2月7日 | 8 | なし |
| Perplexity-User | 2025年10月17日 | 4 | なし |
| Google 一般的なクローラー | 2026年10月16日 | 317 | あり |
| Google 特定用途のクローラー | 2026年10月16日 | 272 | あり |
| Apple Applebot | 2026年9月15日 | 24 | なし |
| Bing Bingbot | 2024年1月3日 | 28 | なし |
この表から読み取れること
1つ目は、更新の頻度が会社ごとに大きく違うことです。
Googleは前日の作成ですが、Bingは2024年1月、PerplexityBotは2025年2月の日付でした。
古い日付は、更新が止まっている場合と、変更がなかっただけの場合があります。
どちらなのかは、ファイルの中身だけでは判断できません。
2つ目は、Google以外の一覧に、IPv6の範囲が見当たらないことです。
IPv6のアクセスが来たとき
IPv6のIPからGPTBotを名乗るアクセスが来ると、IP一覧では「一致なし」と出ます。
私が読んだOpenAI、Anthropic、Perplexityのページには、IPv6の扱いが書かれていませんでした。
一覧とも合わず、DNSでの確認方法も案内されていないため、判断がつかないアクセスとして記録に残します。
遮断するかどうかは、そのアクセスの量や、サイトへの影響を見て決めます。
本物かどうかを確かめる3ステップ
手順は、次の3ステップです。
- アクセスログから、AIクローラーを名乗るアクセスのIPを抜き出す
- 抜き出したIPを、各社の公開IP範囲と照合する
- 一覧で判断できないものは、逆引きと正引きで確かめる
ステップ1:ログからIPを抜き出す
ログの集計は、別の記事で扱っているので、ここでは最低限にとどめます。
Apacheやnginxのcombinedというふつうのログなら、行の先頭がアクセス元のIPです。
次のコマンドは、AIクローラーの名前を含む行から、IPごとの回数を数えます。
grep -iE 'GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-User|Claude-SearchBot|PerplexityBot|Perplexity-User|Applebot|bingbot|Googlebot' access.log \
| awk '{print $1}' | sort | uniq -c | sort -rn > suspect_ips.txt
suspect_ips.txt には「回数 IPアドレス」の形で入ります。
名前ごとに分けたIPの一覧も作っておくと、照合のときに便利です。
grep -i 'GPTBot' access.log | awk '{print $1}' | sort -u > gptbot_ips.txt
サイトがCloudflareなどを経由している場合は、先頭のIPは、訪問者のものでなく、配信側のものになります。その対処は、あとの「注意点とよくある失敗」の節で説明します。
ステップ2:公開IP範囲と照合する
IP範囲の一覧は、「192.0.2.0/24」のような「CIDR表記」で書かれています。
「/24」は範囲の広さを表し、この例なら192.0.2.0から192.0.2.255までの256個のIPを意味します。
目で見て判断するのは大変なので、スクリプトで照合します。
次のPythonスクリプトは、各社のJSONファイルを取得し、受け取ったIPがどの一覧に含まれるかを表示します。
Python 3の標準機能だけで動きます。
JSONの書き方が会社ごとに違っても対応できるよう、「IP範囲として読める文字列」をすべて拾う作りにしています。
#!/usr/bin/env python3
"""公開IP範囲(JSON)と、ログから抜き出したIPを照合するスクリプト"""
import ipaddress
import json
import sys
import urllib.request
# 2026年10月17日時点で、各社の公式ドキュメントに載っている一覧ファイル
SOURCES = {
"OpenAI GPTBot": "https://openai.com/gptbot.json",
"OpenAI OAI-SearchBot": "https://openai.com/searchbot.json",
"OpenAI ChatGPT-User": "https://openai.com/chatgpt-user.json",
"PerplexityBot": "https://www.perplexity.com/perplexitybot.json",
"Perplexity-User": "https://www.perplexity.com/perplexity-user.json",
"Anthropic": "https://claude.com/crawling/bots.json",
"Google 一般クローラー": "https://developers.google.com/static/crawling/ipranges/common-crawlers.json",
"Apple Applebot": "https://search.developer.apple.com/applebot.json",
"Bing Bingbot": "https://www.bing.com/toolbox/bingbot.json",
}
def collect_networks(data):
"""JSONの中から、IP範囲として読める文字列をすべて取り出す"""
networks = []
if isinstance(data, dict):
for value in data.values():
networks.extend(collect_networks(value))
elif isinstance(data, list):
for value in data:
networks.extend(collect_networks(value))
elif isinstance(data, str):
try:
networks.append(ipaddress.ip_network(data, strict=False))
except ValueError:
pass
return networks
def load_networks(url):
if url.startswith(("http://", "https://")):
req = urllib.request.Request(url, headers={"User-Agent": "ip-range-check/1.0"})
with urllib.request.urlopen(req, timeout=30) as res:
data = json.load(res)
else: # ローカルに保存したJSONファイルも読める
with open(url, encoding="utf-8") as f:
data = json.load(f)
return collect_networks(data)
def main():
ranges = {}
for name, url in SOURCES.items():
try:
ranges[name] = load_networks(url)
except Exception as e: # 取得に失敗した一覧は飛ばして警告だけ出す
print(f"[警告] {name} の一覧を取得できませんでした: {e}", file=sys.stderr)
for line in sys.stdin:
text = line.strip()
if not text:
continue
try:
ip = ipaddress.ip_address(text)
except ValueError:
print(f"{text}\t(IPアドレスではありません)")
continue
hits = [name for name, nets in ranges.items()
if any(ip.version == n.version and ip in n for n in nets)]
print(f"{ip}\t{', '.join(hits) if hits else '一致なし'}")
if __name__ == "__main__":
main()
check_ip_ranges.py の名前で保存し、次のように使います。
python3 check_ip_ranges.py < gptbot_ips.txt
出力は「IPアドレス[タブ]一致した一覧の名前」の形です。
GPTBotを名乗るIPが「OpenAI GPTBot」と一致すれば、本物の可能性が高くなります。「一致なし」なら要注意です。
一覧の取得に失敗したときは、その一覧だけ警告を出して先へ進みます。警告が出た回の結果は、鵜呑みにしないでください。
ステップ3:逆引きと正引きで確かめる
IP一覧を公開していない会社のクローラーや、一覧と一致しなかったIPは、DNSで確かめます。
考え方は次のとおりです。
- 逆引き:IPアドレスからホスト名を調べる
- ドメインの確認:ホスト名が、その会社の公式ドメインで終わっているか確かめる
- 正引き:そのホスト名からIPアドレスを調べ、元のIPに戻るか確かめる
なぜ正引きまで必要なのか
逆引きの結果は、IPアドレスを管理する側が設定できます。
そのため、本物のGoogleとは関係のないIPの持ち主が、逆引きの結果を「crawl-○○.googlebot.com」に見せかけることもできます。
一方、googlebot.comの正引きの結果は、Googleにしか設定できません。
往復して元のIPに戻れば、本物と判断できます。この仕組みは、筆者の説明です。
手作業で確かめるなら、ターミナルでhostコマンドを2回使います。
host 66.249.66.1
host crawl-66-249-66-1.googlebot.com
1行目が逆引き、2行目が正引きです。この例は、Googleの公式ページに載っているものです。
実際には、ログに残っていたIPで試してください。
件数が多いときのスクリプト
件数が多いときは、次のシェルスクリプトが便利です。digコマンドが入っているLinuxやmacOSで動きます。
#!/usr/bin/env bash
# 使い方: ./verify_dns.sh 66.249.66.1 googlebot.com
ip="$1"
suffix="$2"
# 1. 逆引き(IP → ホスト名)
name=$(dig +short -x "$ip" | head -n 1)
name="${name%.}" # 末尾のドットを取る
if [ -z "$name" ]; then
echo "$ip 要注意: 逆引きできません"; exit 1
fi
# 2. ホスト名が想定ドメインで終わるか
case "$name" in
*."$suffix") ;;
*) echo "$ip 要注意: 想定外のホスト名 $name"; exit 1 ;;
esac
# 3. 正引き(ホスト名 → IP)で元のIPに戻るか
if { dig +short A "$name"; dig +short AAAA "$name"; } | grep -qxF "$ip"; then
echo "$ip 本物: $name"
else
echo "$ip 要注意: 正引きの結果が一致しません ($name)"; exit 1
fi
使い方は、IPと、想定するドメインを渡すだけです。
./verify_dns.sh 66.249.66.1 googlebot.com
筆者の環境で試すと、「本物」と表示されました。ドメインに evil-googlebot.com を渡すと、「想定外のホスト名」と出ます。
ドメインの末尾を比べるときは、先頭にドットを含めて比べています。
単に「googlebot.comで終わる」だけで判断すると、「evil-googlebot.com」のような紛らわしいドメインを、本物と誤認してしまうためです。
一覧のIPをまとめて調べるなら、次のようにループで回します。
while read -r ip; do ./verify_dns.sh "$ip" search.msn.com; done < bingbot_ips.txt
bingbot_ips.txt は、ステップ1の gptbot_ips.txt と同じ要領で、「bingbot」を含む行から作ります。
第2引数に渡すドメイン
第2引数に渡すドメインは、会社ごとに決まっています。
| 確かめたい相手 | 第2引数に渡すドメイン |
|---|---|
| Googlebot(一般的なクローラー) | googlebot.com |
| Bingbot | search.msn.com |
| Applebot | applebot.apple.com |
| AdsBotなど、Googleの特定用途のもの | google.com |
googleusercontent.comは、利用者の操作で動くGoogleの取得ツールの一部で出てきます。
Googlebotを名乗るアクセスは、まずgooglebot.comで確かめるのが安全です。
判定結果の読み方
照合の結果を、次のように読み分けます。
結果ごとの判断の目安
| 結果 | 意味 | 次の行動 |
|---|---|---|
| 名乗った名前の一覧と一致 | 本物の可能性が高い | そのまま通す |
| 別の会社の一覧にだけ一致 | 名前と実体が食い違う | 記録して、制限を検討する |
| 一覧と一致しないが、逆引きと正引きは一致 | 一覧が古いか、別の用途のIPの可能性 | 一覧を取り直して、もう一度照合する |
| どの一覧にも一致せず、逆引きもできない | なりすましの疑いが強い | 記録して、遮断か回数制限を検討する |
| 正引きが元のIPに戻らない | 逆引きだけを偽った疑いがある | 記録して、遮断か回数制限を検討する |
| IPv6で、一覧のない会社を名乗る | 判断材料が足りない | 記録だけ残し、量を見て決める |
一致しなかったときに最初に疑うこと
「一致なし」と出ても、すぐに偽物とは決められません。
最初に疑うのは、一覧が古い、取得に失敗している、ログのIPが配信側のIPになっている、の3点です。
この3つを確かめてから、DNSでの確認に進みます。
なりすましを見つけたときの対応
なりすましと分かったら、遮断や制限をかけます。いきなり止める前に、記録を残します。
まず記録を残す
遮断する前に、次の情報を記録しておくと、本物を誤って止めたときに原因をたどれます。
- IPアドレスと、名乗っていたユーザーエージェント
- アクセスの時間帯と回数
- 照合の結果(どの一覧とも一致しない、逆引きできない、正引きが一致しない など)
WAFやファイアウォールでブロックする
CloudflareやAWS WAFなどのWAFを使っているなら、管理画面からルールを追加するのが手軽です。
「AIクローラーの名前を名乗っている」かつ「公開IP範囲に含まれない」アクセスを遮断する、組み合わせのルールにします。
IPを1つずつ止める方法は、相手がIPを変えると効かなくなります。
nginxで遮断する
自社でサーバーを管理している場合は、nginxの設定でも同じことができます。
まず、公開JSONからnginx用の一覧ファイルを作るスクリプトです。
#!/usr/bin/env python3
"""公開IP範囲のJSONから、nginx の geo 用の設定ファイルを作る"""
import ipaddress, json, sys, urllib.request
def collect(data):
if isinstance(data, dict):
return [n for v in data.values() for n in collect(v)]
if isinstance(data, list):
return [n for v in data for n in collect(v)]
if isinstance(data, str):
try:
return [ipaddress.ip_network(data, strict=False)]
except ValueError:
return []
return []
nets = []
for url in sys.argv[1:]:
# User-Agent を付けないと、Python 標準の名前のアクセスを拒否するサイトがある
req = urllib.request.Request(url, headers={"User-Agent": "ip-range-check/1.0"})
with urllib.request.urlopen(req, timeout=30) as res:
nets.extend(collect(json.load(res)))
if not nets:
sys.exit("IP範囲が1件も取れませんでした。設定は更新しません。")
for n in sorted(set(nets), key=lambda n: (n.version, n)):
print(f"{n} 1;")
make_nginx_geo.py の名前で保存し、OpenAIの3つの一覧から設定ファイルを作ります。
python3 make_nginx_geo.py https://openai.com/gptbot.json https://openai.com/searchbot.json https://openai.com/chatgpt-user.json > /tmp/openai_ranges.conf \
&& sudo mv /tmp/openai_ranges.conf /etc/nginx/openai_ranges.conf
&& でつないでいるので、取得に失敗したときは、既存の設定ファイルを上書きしません。
一覧が空のまま反映されると、本物のOpenAIのクローラーまで遮断してしまうためです。
次に、nginxの設定(httpブロック内)に、次の内容を加えます。
# 公開IP範囲に含まれるIPなら 1、それ以外は 0
geo $openai_ip {
default 0;
include /etc/nginx/openai_ranges.conf;
}
# OpenAIのクローラー名を名乗っているのに、公開範囲外なら 1
map "$http_user_agent:$openai_ip" $fake_openai {
default 0;
"~*(gptbot|oai-searchbot|chatgpt-user).*:0$" 1;
}
そして、serverブロック内で遮断します。
if ($fake_openai) {
return 403;
}
設定を変えたら、sudo nginx -t で書き間違いがないか確かめてから、sudo systemctl reload nginx で反映します。
この設定は、nginxの公式ドキュメントで、geoのinclude、mapの正規表現、回数制限の空のキーの扱いを確かめて組みました。ただ、筆者の環境にはnginxが入っておらず、実機での動作確認はしていません。
必ず検証用の環境で試してから、本番に反映してください。
いきなり止めずに、回数制限から始める
判断に迷うアクセスは、いきなり遮断せずに、「回数制限」(一定時間あたりのアクセス数に上限を設けること)から始める方法もあります。
誤って本物を止めても、影響を小さくできます。nginxなら、次のように書けます。
# なりすましの疑いがあるときだけ、IPごとに1分あたり30回までに制限
map $fake_openai $suspect_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $suspect_key zone=suspect:10m rate=30r/m;
# server または location ブロック内
limit_req zone=suspect burst=10 nodelay;
limit_req_status 429;
nginxの回数制限は、キーが空のアクセスには適用されません。
そのため、本物のクローラーや一般の訪問者には影響せず、疑わしいアクセスだけが制限されます。
上限の数値は、サイトの規模に合わせて調整してください。
対応の選び方
| 対応 | 向いている場面 | 注意点 |
|---|---|---|
| 記録だけ残す | 負荷がなく、数も少ない | 数が増えたら見直す |
| 回数制限 | 本物かもしれない疑いが残る | 上限を低くしすぎない |
| 遮断 | 一覧と合わず、DNSでも一致しない | 一覧の取り直しを必ずセットにする |
| 何もしない | 自社の目的に影響がない | 許可設定が名前だけなら抜け穴になる |
注意点とよくある失敗
IP範囲は変わるので、定期的に取り直す
IP範囲の一覧は、固定ではありません。
Perplexityは、一覧が定期的に更新されると明記し、自動で取り直す仕組みを勧めています。Bingは、毎日取り直すよう案内しています。
一覧を一度コピーしただけだと、新しいIPから来た本物のクローラーを遮断してしまいます。
cron(決まった時刻にコマンドを自動実行する、Linuxの仕組み)などで、1日1回程度取り直しましょう。
# 毎日 4:10 に一覧を取り直し、成功したときだけ nginx に反映する例
10 4 * * * python3 /opt/scripts/make_nginx_geo.py https://openai.com/gptbot.json https://openai.com/searchbot.json https://openai.com/chatgpt-user.json > /tmp/openai_ranges.conf && mv /tmp/openai_ranges.conf /etc/nginx/openai_ranges.conf && nginx -t && systemctl reload nginx
この行は、管理者の権限で動くcronに書く想定です。
あわせて、取得に失敗したときや、一覧が空だったときに、通知が届くようにしておくと安心です。
CDN経由では、ヘッダーから元のIPを取る
Cloudflareのようなサービスを使っていると、ログに残るIPは、Cloudflare側のものになります。
すると、すべてのアクセスが「一致なし」になってしまいます。
Cloudflareの公式ドキュメントは、元の訪問者のIPがCF-Connecting-IPというヘッダーで届くと説明しています。
また、複数のIPが並ぶことのあるX-Forwarded-Forより、CF-Connecting-IPかTrue-Client-IPを使うよう勧めています。
nginxなら、ngx_http_realip_moduleの設定を使います。
set_real_ip_from(信頼するIPの指定)と、real_ip_header CF-Connecting-IP; の2つを書きます。
設定すると、ログや設定内のIPが、元の訪問者のものに置き換わります。
Apacheならmod_remoteipのRemoteIPHeader CF-Connecting-IP と、RemoteIPTrustedProxyを使います。
大事なのは、このヘッダーを信用する相手を、Cloudflareから届いたアクセスに限ることです。
ヘッダーは、送る側が書き換えられるため、誰からでも信用すると、なりすまし側が好きなIPを名乗れてしまいます。この説明は、筆者の見解です。
よくある失敗
| 失敗 | 内容と直し方 |
|---|---|
| ユーザーエージェントの名前だけで許可している | よくある抜け穴。名前とIPの両方を条件にする |
| 逆引きだけで判断している | 逆引きの結果は偽装できる。正引きで元のIPに戻ることまで確かめる |
| ドメインの末尾を雑に比べている | 「googlebot.comを含む」で判断すると、似た名前のドメインを見逃す。先頭のドットまで含めて比べる |
| 古い一覧やURLを使い続けている | 定期的な取り直しと、URLの見直しをセットで行う |
| 利用者の操作で動くものを、巡回クローラーと同じに扱っている | ChatGPT-UserやPerplexity-Userは、robots.txtが適用されない場合がある |
| 一覧のIPv4だけを見ている | IPv6のアクセスは「一致なし」になる。判断材料が足りないものとして記録する |
利用者の操作で動くものは、遮断を別に考える
ChatGPT-UserやPerplexity-Userは、利用者の質問をきっかけに動きます。
止めると、利用者がAIに質問したときに、あなたのサイトの情報が使われにくくなる可能性があります。
Anthropicは、Claude-Userを無効にすると、利用者の依頼による検索での見え方が下がる可能性があると説明しています。
遮断するかどうかは、なりすましの確認とは別に判断しましょう。
作業チェックリスト
- ログに残っているIPが、訪問者のIPになっている
- AIクローラーを名乗るアクセスのIPを、名前ごとに抜き出した
- 公開IP一覧(JSON)と照合した
- 一覧がない、または一致しないIPは、逆引きと正引きで確かめた
- なりすましと判断したIPと、その理由を記録した
- 遮断または回数制限を設定し、設定の書き間違いを確認した
- IP一覧を定期的に取り直す仕組みを作った
よくある質問
Q1. なりすましのアクセスは放置しても問題ありませんか?
負荷がかかっていなければ、すぐに困ることは少ないかもしれません。
ただ、AIクローラーの訪問状況を正しく把握できなくなり、「AIクローラーの名前なら通す」設定では抜け穴になります。少なくとも、確認と記録はしておきましょう。
Q2. 本物のクローラーをIPアドレスで遮断すれば、学習に使われなくなりますか?
確実とはいえません。
Anthropicはヘルプ記事で、IPでの遮断はオプトアウトとして確実に働くとは限らないとして、robots.txtを案内しています。
利用を断りたい場合はrobots.txtを使い、IP一覧は本物かどうかの確認に使うのが基本です。
Q3. サーバーを触れない場合は、どうすればよいですか?
アクセスログをダウンロードできれば、照合だけは、この記事のスクリプトで行えます。
遮断や回数制限は、利用中のサービスの管理画面に、WAFやアクセス制限の機能があるかを確認してください。
Q4. どのくらいの頻度で確認すればよいですか?
IP一覧の取り直しは、自動で1日1回程度が目安です。
ログの照合は、AI検索対策の効果を確認するタイミング(月1回など)で行います。
急にアクセスが増えたときは、その都度確認してください。この頻度は、筆者の目安です。
Q5. 逆引きを、アクセスのたびに行っても大丈夫ですか?
おすすめしません。
DNSの問い合わせには時間がかかり、表示が遅くなるおそれがあるためです。
照合は、ログに対して後からまとめて行うか、確かめた結果を保存して使い回しましょう。この点は、筆者の判断です。
Q6. IPv6のアクセスは、どう確かめればよいですか?
Google、Apple、Bingは、逆引きと正引きの手順を案内しています。考え方はIPv6でも同じですが、筆者は、IPv6のアドレスでスクリプトを試していません。
OpenAI、Anthropic、Perplexityは、私が読んだページに、DNSでの確認方法がありませんでした。判断がつかないアクセスとして記録に残します。
まとめ
AIクローラーの名前(ユーザーエージェント)は、誰でも名乗れます。
ログに書かれた名前だけでは、本物かどうか判断できません。確かめるには、アクセス元のIPアドレスを使います。
- OpenAI、Anthropic、Perplexityは、IP一覧(JSON)を公開しています。Google、Apple、Bingは、IP一覧とDNSの両方を案内しています。
- 手順は、「ログからIPを抜き出す、公開範囲と照合する、合わないものはDNSで再確認する」の3段階です。
- DNSでは、逆引きだけでなく、正引きで元のIPに戻ることまで確かめます。
- なりすましは、名前とIPを組み合わせたルールで遮断するか、まずは回数制限で様子を見ます。
- IP一覧は変わります。自動で取り直す仕組みを作り、CDN経由のサイトは、信頼できる配信元のヘッダーから元のIPを取り出します。
まずは手元のログから、GPTBotを名乗るアクセスのIPを照合するところから始めてみてください。
この記事に書いたことを、そのまま御社のページに
生成AIに引用されるページを、お話しいただくだけでお作りします。お時間をいただくのは初回15分のヒアリングだけです。まず1ページ、無料でお作りします。
OKが出るまで、何度でも直します。事実が違う、言い回しが硬い、この話は入れないでほしい。どれも遠慮なくおっしゃってください。何度お直ししても、追加の料金はいただきません。
これまでに127社にご利用いただきました。毎月ご依頼いただいている方の6割以上が、月10ページを選ばれています。料金はページに掲載しています。
ページを増やしても問い合わせが来ないなら、原因はページの外にあります。その場合は、下の入口からご相談ください。
自社のマーケティング課題を根本から解決しませんか?
ウェブサイトから要素を引き算し、訪れた人が迷わず次の一歩に進む形へ組み直す。初回60分のオンラインで御社のサイトを一緒に読み、どこから直すべきかをお伝えします。手順をまとめた無料の診断と解説動画もご用意しています。
初回は無料・60分・オンライン完結・その場で契約のお願いはいたしません


