本文へスキップ

ボット検知の仕組みと、Clearcote がエンジンにパッチを当てる理由

一般的な手法では、navigator.webdriver へのパッチ、WebGL ベンダーの偽装、navigator.plugins の上書きをスクリプトから行います。それでも検知ツールには見抜かれます。その理由は、偽装し損ねたプロパティがまだ 1 つ残っているからではなく、構造的なものです。

整合性を図にすると、こうなります。互いに裏付け合う独立したシグナルが、1 つのアイデンティティを形作ります。どこにもつながっていない 2 つの点(裏付けのない偽装値)が、クロスチェックで読み取られる継ぎ目です。

JavaScript による偽装は自ら正体を明かす

JS による偽装とは、本来ネイティブ関数があるべき場所に置かれた関数です。検知側は、返された値はいったん脇に置き、その値を返しているものがネイティブかどうかを調べます:

手がかりJS による偽装を見抜ける理由
toString による自己露呈ネイティブメソッドを文字列化すると function get vendor() { [native code] } になりますが、上書きした関数は自身のソースコードになります。.toString() を 1 回呼ぶだけで見抜けます。
ディスクリプタ / hasOwnPropertygetOwnPropertyDescriptor は再定義されたプロパティを露呈させます。また hasOwnProperty('toString') は、ネイティブ関数なら false を返すところ、改ざんされた関数では true を返します。
誤った this での TypeErrorネイティブの getter は、誤ったレシーバーで呼ばれると特定の TypeError をスローします。素朴な shim は黙ったままで、その沈黙こそがシグナルになります。
Realm の再取得検知側は、新しい iframe や Web Worker から手付かずの Function.prototype.toString を取得し、それをあなたの getter に適用します。メインワールドのパッチとは別の realm です。返ってくるのはあなたのソースコード。これで見破られます。

Clearcote にはそのようなレイヤーがありません。navigator.userAgent の getter は C++ の getter そのものです。[native code] と報告するのは、それが実際にネイティブコードだからであり、メインフレーム、iframe、ワーカーのどの realm でも同一です。検知される JavaScript の乗っ取り自体が存在しません。

ボット検知の 3 つのレイヤー

現代のアンチボットシステムは、構造的に異なる 3 つのサーフェスを、それぞれ別の場所で読み取ります。1 つのツールで 3 つすべてに対処できることはまれです:

レイヤー手がかり対処する場所Clearcote
A · ドライバ / バイナリChromeDriver の cdc_ 変数、WebDriver プロトコルのサーフェスCDP を直接使い、chromedriver を使わない✅ 素の Chromium バイナリで、ドライバの痕跡なし
B · CDP の副作用Runtime.enable によるリーク、注入された init スクリプト、メインワールドでの実行、自動化ツール既定のビューポート制御 / CDP クライアントのレイヤー✅ エンジンが Runtime.enable のリークを無効化し、SDK はデフォルトでスクリプトを注入せず、起動時のデフォルト設定は自動化ツール既定のビューポートを使いません(クライアントが独自のスクリプトをどこで実行するかはクライアント次第です)
C · フィンガープリントのサーフェスcanvas、WebGL、オーディオ、フォント、navigator、TLS(メインフレーム、iframe、ワーカーのすべてで)エンジン(C++)。JS による上書きは自ら正体を明かすため✅ これが Clearcote です

最も重要なこと:偽装と実体の継ぎ目がない

制御がエンジン内にあるため、ページから見える JavaScript も、その下のネットワークハンドシェイクも、1 つの本物の Chromium から来ています。クロスチェックで捕捉されるような「偽装した JS と本物の TLS」の継ぎ目はありません。これはまさに、インジェクション型のツールが見破られる原因となる失敗パターンです。1 つの --fingerprint シードから、canvas、WebGL、オーディオ、フォント、ハードウェアにわたって内部で一貫した 1 台のマシンが生成されます。その下の TLS と HTTP/2 のハンドシェイクはエンジン自身のもので、ペルソナがエンジンの実際のバージョンを報告するため、両者は一致します。この状態を保つには、brandVersion を未設定のままにしてください。

ノイズそのものが手がかりになる場合は、ノイズをオフにします。アイデンティティの偽装は有効なまま、canvas と WebGL は本来の値を返します(レンダリングされたオーディオとクライアント矩形にはどちらの場合もノイズが加わらず、AudioContext のサンプルレート/レイテンシのスカラー値は引き続きペルソナに従います。その理由はこちら):

javascript
await launch({ fingerprint: "u1", fingerprintNoise: false });   // identity on, per-site farbling off

ノイズをオフにすると、同じマシン上のアイデンティティは 1 つの canvas ハッシュを共有します。canvasNoise: false は canvas 2D のノイズだけをオフにし、WebGL のノイズは維持します(ライセンスビルド、150 r12 以降)。

ネットワークとロケールの整合性

ペルソナは全体の半分にすぎません。タイムゾーン、言語、WebRTC のアドレスも、トラフィックの発信元と一致している必要があります。プロキシを使う場合は geoip を指定して起動してください。SDK がプロキシの出口 IP を調べ、その地域に合わせてタイムゾーン、言語リスト、位置情報、WebRTC アドレスを設定します。地域を特定できなければ起動を中止します。指定しない場合、プロキシがどの国にあっても、タイムゾーンは言語に従います(en-US ならニューヨーク)。オプションについては Playwright & Puppeteer を参照してください。

Clearcote が JavaScript を注入するのではなく、C++ エンジンにパッチを当てているのはこのためです。制御できる項目はフィンガープリントフラグを、エンジンがすべてのシグナルの整合性をどう保っているかはアーキテクチャを参照してください。