現在のブラウザが JavaScript でヘッドレス ブラウザであるかどうかを検出する方法

現在のブラウザが JavaScript でヘッドレス ブラウザであるかどうかを検出する方法

ヘッドレスブラウザとは何ですか?

ヘッドレス ブラウザは、グラフィカル インターフェイスで実行できるブラウザです。ヘッドレス ブラウザをプログラムで制御して、テストの実行、Web ページのスクリーンショットの取得など、さまざまなタスクを自動的に実行できます。

なぜ「ヘッドレス」ブラウザと呼ばれるのでしょうか?

「ヘッドレス」という言葉は、元々は「ヘッドレス コンピュータ」から来ています。 「ヘッドレス コンピュータ」に関する Wikipedia のエントリ:

ヘッドレス システムとは、モニター (つまり「ヘッド」)、キーボード、マウスなしで動作するように構成されたコンピュータ システムまたはデバイスです。ヘッドレス システムは通常、ネットワーク接続を介して制御されますが、一部のヘッドレス システム デバイスでは、デバイス管理のために RS-232 シリアル接続も必要です。運用コストを削減するために、サーバーはヘッドレス モードで実行されることがよくあります。

ヘッドレスブラウザを検出するのはなぜですか?

前述の 2 つの無害な使用例の他に、ヘッドレス ブラウザを使用して悪意のあるタスクを自動化することもできます。最も一般的な形式は、Web クローラー、トラフィックの偽装、または Web サイトの脆弱性の検出です。

非常に人気のあるヘッドレス ブラウザは Phantomjs です。Qt フレームワークをベースとしているため、一般的なブラウザと比較してさまざまな機能があり、識別方法も多数あります。

しかし、Chrome 59 以降、Google はヘッドレス Google Chrome ブラウザをリリースしました。 Phantomjsとは異なり、他のフレームワークではなくオーソドックスなGoogle Chromeをベースに開発されているため、プログラムが通常のブラウザなのかヘッドレスブラウザなのかを区別することが困難です。

以下では、プログラムが通常のブラウザで実行されているか、ヘッドレスブラウザで実行されているかを判断するためのいくつかの方法を紹介します。

ヘッドレスブラウザの検出

注: これらの方法は 4 台のマシン (Linux 2 台、Mac 2 台) でのみテストされていますが、ヘッドレス ブラウザーを検出する方法は他にもたくさんあります。

ユーザーエージェント

まず、ブラウザの種類を判断する最も一般的な方法である、ユーザーエージェントを確認する方法を紹介します。 Linux コンピュータ上の Chrome バージョン 59 ヘッドレス ブラウザのユーザー エージェント値は次のとおりです。

「Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml、Gecko に類似) HeadlessChrome/59.0.3071.115 Safari/537.36」

したがって、次のようにしてヘッドレス Chrome ブラウザかどうかを検出できます。

if (/HeadlessChrome/.test(window.navigator.userAgent)) {
  console.log("Chrome ヘッドレスが検出されました");
 }

ユーザーエージェントは HTTP ヘッダーから取得することもできます。ただし、これらのシナリオは両方とも簡単に偽造できます。

プラグイン

navigator.plugins は、現在のブラウザのプラグイン情報を含む配列を返します。通常、通常の Chrome ブラウザには、Chrome PDF ビューアや Google Native Client などのデフォルトのプラグインがいくつか用意されています。対照的に、プラグインのないヘッドレス モードでは、空の配列が返されます。

(navigator.plugins.length == 0)の場合{
  console.log("Chrome ヘッドレスである可能性があります");
}

言語

Google Chrome には、現在のブラウザの言語設定を取得できる JavaScript プロパティが 2 つあります。navigator.language と navigator.languages です。最初のものはブラウザインターフェースの言語を参照し、2 番目のものはブラウザユーザーが選択したすべての二次言語を格納する配列を返します。ただし、ヘッドレス モードでは、navigator.languages は空の文字列を返します。

if (navigator.languages ​​== "") {
  console.log("Chrome ヘッドレスが検出されました");
}

ウェブGL

WebGL は、HTML キャンバスで 3D レンダリングを実行できる一連の API を提供します。これらの API を通じて、グラフィックス ドライバーのベンダーとレンダラーを照会できます。

Linux 上の通常の Google Chrome ブラウザでは、レンダラーとベンダーの値は「Google SwiftShader」と「Google Inc.」として取得されます。

ヘッドレス モードでは、「Mesa OffScreen」 (ウィンドウ システムを使用しないレンダリング テクノロジの名前) と、オープン ソースの Mesa グラフィック ライブラリのオリジナル プログラマーである「Brian Paul」が表示されます。

 var キャンバス = document.createElement('キャンバス');
 var gl = canvas.getContext('webgl');
  
 var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
 var ベンダー = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
 var レンダラー = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
  
 if (ベンダー == "Brian Paul" && レンダラー == "Mesa OffScreen") {
  console.log("Chrome ヘッドレスが検出されました");
 }

ヘッドレス ブラウザのすべてのバージョンで、これら 2 つの値が同じであるわけではありません。ただし、現在ヘッドレスブラウザでは値は「Mesa Offscreen」と「Brian Paul」です

ブラウザの機能

Modernizr は、HTML および CSS のさまざまな機能に対する現在のブラウザのサポートを検出できます。通常のChromeとヘッドレスChromeの唯一の違いは、ヘッドレスモードではHIDPI/Retinaのヘアラインがサポートされているかどうかを検出するために使用されるヘアライン機能がないことです。

if (!Modernizr["ヘアライン"]) {
  console.log("Chrome ヘッドレスである可能性があります");
}

画像の読み込みに失敗しました

最後に、私が見つけた最後の方法であり、最も効果的と思われる方法は、ブラウザで正しく読み込まれていない画像の高さと幅を確認することです。

通常の Chrome では、正常に読み込めなかった画像のサイズはブラウザのズームに関係しますが、絶対にゼロにはなりません。ヘッドレス Chrome ブラウザでは、この画像の幅と高さはどちらも 0 です。

var body = document.getElementsByTagName("body")[0];
var image = document.createElement("img");
画像を拡大
image.setAttribute("id", "偽画像");
body.appendChild(画像);
image.onerror = 関数(){
	画像の幅が 0 の場合、画像の高さは 0 になります。
		console.log("Chrome ヘッドレスが検出されました");
	}
}

上記は、JavaScript を使用して現在のブラウザがヘッドレス ブラウザであるかどうかを検出する方法の詳細です。JavaScript の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • NodeJSとブラウザにおけるこのキーワードの違い
  • JavaScriptはブラウザがIEかどうかを判定します
  • ブラウザのウェブページの自動スクロールとクリックを実現する JavaScript のサンプル コード
  • JavaScript を使用してブラウザでウェブカメラを使用する方法
  • JavaScript を使用してブラウザ履歴 API を操作する方法
  • JSクロスブラウザXMLアプリケーションプロセスの詳細な説明
  • モバイルブラウザがWeChat共有を呼び出す(JS)
  • ブラウザのJavaScriptデバッグ機能は使用できません。解決策
  • よく使われるJavaScriptツールの機能まとめ(ブラウザ環境)
  • js に基づいてブラウザの種類を判断する例

<<:  シェルを使用してMySQLデータバックアップスクリプトを作成する

>>:  Linux で固定 IP を設定する方法 (テスト済みで効果的)

推薦する

Vue ルーターにパラメータを渡すときにページを更新するとパラメータが失われる問題に対処する方法

目次概要方法1: params経由でパラメータを渡す方法2: クエリを通じてパラメータを渡す方法3:...

CentOS 8 に MySql をインストールしてリモート接続を許可する方法

ダウンロードしてインストールします。まず、システムに MySQL または MariaDB があるかど...

vuex での Getter の使用法の詳細な説明

序文Vuex を使用すると、ストア内に「ゲッター」を定義できます (これはストアの計算されたプロパテ...

JavaScript Canvas は動的なワイヤーフレーム効果を描画します

この記事では、JavaScript Canvasの動的なワイヤーフレーム効果を描画する具体的なコード...

CSS3を使用してヘッダーアニメーション効果を作成する

Netease Kanyouxi公式サイト(http://kanyouxi.163.com/)(棚...

Zabbix による VMware Exsi ホストの監視のグラフィカルな手順

1. 仮想化 vcenter に入り、ブラウザでログインし (クライアントは設定する場所を見つけませ...

wgetはウェブサイト全体(サブディレクトリ全体)または特定のディレクトリをダウンロードします

wgetコマンドを使用して、親ディレクトリの下のサブディレクトリ全体をダウンロードします。親ディレク...

CSS ブラウザ互換性の問題に対する 4 つの解決策

フロントエンドは、技術が急速に進化するだけでなく、知っておくべき事柄が多すぎるという理由で大変な仕事...

MySQL パフォーマンス最適化のための魔法のツール、Explain の基本的な使用分析

導入MySQL には、SELECT ステートメントを分析し、開発者が最適化できるように SELECT...

Ansibleを使用してディレクトリ内のすべてのコンテンツを削除する方法

Ansible を使用する学生は、以下に示すように、Ansible が特定のフォルダーまたはファイル...

HTML 終了タグの問題と W3C 標準

W3C の原則によれば、XML の各開始タグには対応する終了タグが必要です。つまり、<html...

Linux で SpringBoot jar プログラム デプロイメント シェル スクリプトを起動および停止する方法

では早速、コードをお見せしましょう。具体的なコードは次のとおりです。 #!/bin/bash cd ...

gbk utf8 GBK と UTF-8 ウェブページエンコーディングを正しく理解して使用する方法

Web ページ エンコーディングは英語では web page encoding と翻訳され、Web ...

プレーンな JS オブジェクトの代わりに Map を使用する場合

目次1. マップは任意のタイプのキーを受け入れます2. マップにはキー名に関する制限はありません3....

Centos7環境でYUMを構築する方法

1. yumソースの設定ファイルを入力します 2.lsで設定ファイルを表示する 3. ディレクトリを...