Techcrunch の記事によると、3D スキャンデータの販売を行っている Triplegangers というサイトが ChatGPT のサービスを公開している OpenAI のウェブクローラーのクローリング(スクレイピング)が原因で DDoS 攻撃を受けているかのような状態になり、サイトダウンを引き起こしていた可能性がある、と発表されていました:
https://techcrunch.com/2025/01/10/how-openais-bot-crushed-this-seven-person-companys-web-site-like-a-ddos-attack/
記事によると原因となったスクレイピングボットはサイト全体から数十万枚にも及ぶ画像データを全てダウンロードしようとしていた形跡があり、その結果サイトがダウンしてしまった、らしいです。ウェブアプリケーション/ウェブサービスを運用する立場としても他人事ではなく、怖いニュースです。。。
この件に関しては、Triplegangers 側は「事前承諾なしにサイトデータのスクレイピングを禁じる」旨を記載していたようです。が、Techcrunch は「ウェブ上の記載のみで robots.txt の設定は不充分だった」とも指摘している一方、「そもそも robots.txt も(紳士協定が守られる保証はないので)絶対ではない」とも指摘していて、絶対的な回避方法や情報が提供されているわけではありませんでした。
たしかに robots.txt はウェブクローラーに対して「参照していいページ/しないでほしいページ」を指定する方法ではあるのですが、あくまで紳士協定であって、その協定というかルールを守らないクローラーがないとは言いきれません。特に最近は LLM の学習データをウェブから集めようと試みる人が少なくないことが想像できるので、普通のウェブサイトがいつの間にか学習データ提供元になっていたり、今回のような大量のスクレイピング実行されたり(※今回記事になった例ではスクレイピング時に数百もの異なる IP アドレスが使われていたらしく、悪意がなくても悪質なスクレイピングであったと感じています)するとサイトダウンを引き起こしかねないこともあって、小規模な個人サイトであっても気になってしまうものでした。現に生成 AI 検索エンジンの1つである Perplexity のクローラーは過去に robots.txt を無視していたと指摘されている前科もあって、いつ他人事でなくなるかもわかりません。
そこで「robots.txt の指示を守らないクローラーがやってくる前提で、クローラーボットによるインデックシング/スクレイピングをウェブアプリケーションで拒否する」方法を考え、サンプルを作って公開してみました。
【サンプル】
Node.js で作ったサンプルはこちらです:
https://github.com/dotnsf/block-llm-bots
"git clone" などでダウンロードすると、app.js と block_llm_bots.js という2つの JavaScript ファイルがあることが分かります。アプリケーションとしてクローラーを拒否するモジュールは後者で、前者はそれを組み込んだサンプルとなっています。以下は app.js のコードです:
黒字部分がオリジナルのウェブアプリケーションで、赤字部分がそのウェブアプリケーションにクローラー拒否のモジュールを組み込んでいる1行です(緑字はコメント部です)。block_llm_bots.js が同じディレクトリ上にあれば、この1行だけでクローラーブロックが有効になります。
ブロック対象とするクローラーの(UserAgent の)種類を環境変数 BLOCK_BOTS に(複数の場合はカンマ区切りで)指定します。サンプルでは .env ファイル内で以下のように指定されています:
この例では "PerplexityBot,GPTBot,ChatGPT-User,OAI-SearchBot,Google-Extended" と指定されています。この指定で Perplexity(PerplexityBot), OpenAI(GPTBot, ChatGPT-User, OAI-SearchBot), Google(Google-Extended) の3か所の LLM クローラーからのアクセスを拒否しています。
このサンプル(app.js)を使って試しに動作確認してみましょう。Node.js が導入された環境でこのファイル一式をダウンロードし、依存ライブラリをインストールします:
そして(必要に応じて .env ファイルを編集して拒否するクローラーの種類を変更した上で)アプリケーションを起動します:
特に指定しない場合、アプリケーションは 8080 番ポートで HTTP リクエストを待ち受ける状態になります(変更する場合は環境変数 PORT で指定します)。
この状態で(別ウィンドウなどから)curl を使ってアプリケーションにアクセスしてみます:

{ "status": true } というアプリケーションの「本来の期待通りの」挙動結果が返ってきました。
では次に OpenAI のクローラーをエミュレートして、User-Agent ヘッダに "GPTBot" を指定してアクセスしてみます:

想定通りに GPTBot からのアクセスが遮断された結果、今度は何も表示されませんでした。
この時、サーバー側のコンソールを見ると、"GPTBot" からのアクセスの際にはブロックされた旨が表示されているはずです。期待通りの(特定のボットからのアクセスを遮断するような)挙動が実現できていることが確認できました:

このサンプルのように block_llm_bot.js を組み込むか、または同様の拡張をアプリケーションに行うなどして(robots.txt を無視してくるようなクローラーに対しても)スクレイピングを禁止する機能が実現できそうです。自作サービスにも組み込んでおこっと。
とはいえ、本当に悪質な連中だと UserAgent すらも偽装してくるのかなあ、、そういうのはどうするべきなんだろう?
https://techcrunch.com/2025/01/10/how-openais-bot-crushed-this-seven-person-companys-web-site-like-a-ddos-attack/
記事によると原因となったスクレイピングボットはサイト全体から数十万枚にも及ぶ画像データを全てダウンロードしようとしていた形跡があり、その結果サイトがダウンしてしまった、らしいです。ウェブアプリケーション/ウェブサービスを運用する立場としても他人事ではなく、怖いニュースです。。。
この件に関しては、Triplegangers 側は「事前承諾なしにサイトデータのスクレイピングを禁じる」旨を記載していたようです。が、Techcrunch は「ウェブ上の記載のみで robots.txt の設定は不充分だった」とも指摘している一方、「そもそも robots.txt も(紳士協定が守られる保証はないので)絶対ではない」とも指摘していて、絶対的な回避方法や情報が提供されているわけではありませんでした。
たしかに robots.txt はウェブクローラーに対して「参照していいページ/しないでほしいページ」を指定する方法ではあるのですが、あくまで紳士協定であって、その協定というかルールを守らないクローラーがないとは言いきれません。特に最近は LLM の学習データをウェブから集めようと試みる人が少なくないことが想像できるので、普通のウェブサイトがいつの間にか学習データ提供元になっていたり、今回のような大量のスクレイピング実行されたり(※今回記事になった例ではスクレイピング時に数百もの異なる IP アドレスが使われていたらしく、悪意がなくても悪質なスクレイピングであったと感じています)するとサイトダウンを引き起こしかねないこともあって、小規模な個人サイトであっても気になってしまうものでした。現に生成 AI 検索エンジンの1つである Perplexity のクローラーは過去に robots.txt を無視していたと指摘されている前科もあって、いつ他人事でなくなるかもわかりません。
そこで「robots.txt の指示を守らないクローラーがやってくる前提で、クローラーボットによるインデックシング/スクレイピングをウェブアプリケーションで拒否する」方法を考え、サンプルを作って公開してみました。
【サンプル】
Node.js で作ったサンプルはこちらです:
https://github.com/dotnsf/block-llm-bots
"git clone" などでダウンロードすると、app.js と block_llm_bots.js という2つの JavaScript ファイルがあることが分かります。アプリケーションとしてクローラーを拒否するモジュールは後者で、前者はそれを組み込んだサンプルとなっています。以下は app.js のコードです:
(app.js) //. app.js var express = require( 'express' ), app = express(); app.use( express.Router() ); //. LLM クローラーボットブロックを有効にする app.use( require( './block_llm_bots' ) ); //. .env 内に記載された UserAgent からのリクエストだとこの処理は実行されない app.get( '/', function( req, res ){ res.contentType( 'application/json; charset=utf-8' ); res.write( JSON.stringify( { status: true }, null, 2 ) ); res.end(); }); var port = process.env.PORT || 8080; app.listen( port ); console.log( "server starting on " + port + " ..." );
黒字部分がオリジナルのウェブアプリケーションで、赤字部分がそのウェブアプリケーションにクローラー拒否のモジュールを組み込んでいる1行です(緑字はコメント部です)。block_llm_bots.js が同じディレクトリ上にあれば、この1行だけでクローラーブロックが有効になります。
ブロック対象とするクローラーの(UserAgent の)種類を環境変数 BLOCK_BOTS に(複数の場合はカンマ区切りで)指定します。サンプルでは .env ファイル内で以下のように指定されています:
# ブロックしたいボットの UserAgent をコンマ区切りで羅列する
BLOCK_BOTS=PerplexityBot,GPTBot,ChatGPT-User,OAI-SearchBot,Google-Extended
この例では "PerplexityBot,GPTBot,ChatGPT-User,OAI-SearchBot,Google-Extended" と指定されています。この指定で Perplexity(PerplexityBot), OpenAI(GPTBot, ChatGPT-User, OAI-SearchBot), Google(Google-Extended) の3か所の LLM クローラーからのアクセスを拒否しています。
このサンプル(app.js)を使って試しに動作確認してみましょう。Node.js が導入された環境でこのファイル一式をダウンロードし、依存ライブラリをインストールします:
$ npm install
そして(必要に応じて .env ファイルを編集して拒否するクローラーの種類を変更した上で)アプリケーションを起動します:
$ npm start
特に指定しない場合、アプリケーションは 8080 番ポートで HTTP リクエストを待ち受ける状態になります(変更する場合は環境変数 PORT で指定します)。
この状態で(別ウィンドウなどから)curl を使ってアプリケーションにアクセスしてみます:
> curl "http://localhost:8080/"

{ "status": true } というアプリケーションの「本来の期待通りの」挙動結果が返ってきました。
では次に OpenAI のクローラーをエミュレートして、User-Agent ヘッダに "GPTBot" を指定してアクセスしてみます:
> curl -H "User-Agent: GPTBot" "http://localhost:8080/"

想定通りに GPTBot からのアクセスが遮断された結果、今度は何も表示されませんでした。
この時、サーバー側のコンソールを見ると、"GPTBot" からのアクセスの際にはブロックされた旨が表示されているはずです。期待通りの(特定のボットからのアクセスを遮断するような)挙動が実現できていることが確認できました:

このサンプルのように block_llm_bot.js を組み込むか、または同様の拡張をアプリケーションに行うなどして(robots.txt を無視してくるようなクローラーに対しても)スクレイピングを禁止する機能が実現できそうです。自作サービスにも組み込んでおこっと。
とはいえ、本当に悪質な連中だと UserAgent すらも偽装してくるのかなあ、、そういうのはどうするべきなんだろう?
コメント