TLSフィンガープリンティング (JA3/JA4): なぜクリーンなIPがブロックされるのか

あなたの住宅IPはクリーンで、ヘッダーも完璧なのに、最初のリクエストで403が返ってくる。原因はTLSハンドシェイクにあります。これは、HTTPが交換される前にアンチボットシステムが読み取るフィンガープリントです。

すべてのスクレイパーが最終的に直面するパズルがあります:住宅IPはクリーンで、User-Agentは最新のChrome文字列、ヘッダーは完璧な順序であるのに、最初のリクエストで403が返ってきます。何を回転させても解決しません。原因は、ヘッダーが読まれる前にブロックが発生したことです。現代のアンチボットシステムはTLSハンドシェイクをフィンガープリントし、デフォルトのPython、Go、curlクライアントは、HTTPの一層下のClientHelloでボットとして自らを示します。これがJA3とJA4のフィンガープリンティングが行うことであり、なぜcurlが同じURLで403を受け、ブラウザが200を受けるのかという理由です。

TLSフィンガープリンティングが読み取るもの

すべてのHTTPS接続はTLSハンドシェイクで始まります。クライアントは、特定の順序で、希望するTLSバージョン、サポートする暗号スイート、提供する拡張機能(SNI、ALPNなど)、楕円曲線、ポイントフォーマットを広告するClientHelloを送信します。それらのどれもがブラウザを直接名指しするわけではありませんが、正確な組み合わせと順序はソフトウェアスタックのほぼユニークな署名です。ChromeのリストはFirefoxのものと異なり、どちらもPythonのrequestsやGoのnet/httpとは大きく異なります。ハンドシェイクを読むことで、HTTPのバイトが交換される前にクライアントを推測できます。

JA3: 5つのフィールドを1つのMD5ハッシュに

JA3は、Salesforceのエンジニアによって2017年に発表された古典的な方法です。ClientHelloから5つのフィールド(TLSバージョン、暗号、拡張機能、楕円曲線、ポイントフォーマット)を取り、それらを連結し、MD5を通して文字列を実行します。具体的な例として、フィールドは

771,4865-4866-4867,0-11-10-35-16-5-13,29-23-24,0

e7d705a3286e19ea42f587b344ee6865にハッシュされます。これは標準のcurlビルドに属するフィンガープリントです。アンチボットベンダーはこれらのハッシュのデータベースを保持しています。JA3が既知のスクレイピングライブラリと一致するリクエストは、より厳しいレート制限、チャレンジ、または完全なブロックを受けます。最も強力なチェックは相関関係です。User-AgentがChrome 120を主張しているのに、JA3がpython-requestsを示している場合、その矛盾だけで失敗するのに十分です。

なぜJA3がJA4に取って代わられたのか

JA3には安定したシグナルとしての弱点がありました。Chrome 110とFirefox 114以降、ブラウザはフィンガープリンティングに対抗するためにTLS拡張機能の順序をランダム化します。つまり、実際のブラウザは今や各セッションで異なるJA3ハッシュを生成します。そのため、生のJA3は正規のユーザーに対して誤検知を投げます。業界の対応は、JA3N(ハッシュ前に拡張をソートしてランダム化をキャンセルする正規化されたバリアント)と、JA3の創設者自身が構築したFoxIOの新しいスキームであるJA4です。

JA4はより読みやすく、偽装が難しいです。3部構成のa_b_cレイアウトを使用し、例えばt13d1516h2_8daaf6152771_e5627efa2ab1です。プレフィックスだけでも多くを示します:tはTCP、13はTLS 1.3、dはドメインベースのSNI、15は暗号スイート、16は拡張機能、h2は最初のALPNとしてのHTTP/2 — その後、ソートされた暗号と拡張機能プラス署名アルゴリズムの2つの切り捨てられたハッシュが続きます。JA4はファミリーの一部です:JA4Sはサーバーをフィンガープリントし、JA4HはHTTPヘッダー、JA4Xは証明書、JA4Tは生のTCPレイヤーをフィンガープリントします。

デフォルトのクライアントがTLSハンドシェイクでブロックされ、ブラウザ形状のクライアントが通過する図、HTTPが送信される前に
JA3/JA4のルックアップはハンドシェイクで行われます — 不一致のフィンガープリントは、ヘッダーが読まれる前に403です。

なぜクリーンなIPがあなたを救わないのか

これはプロキシにのみ投資する人々をつまずかせる部分です。清潔な住宅IPは、トラフィックが実際のネットワークから来ていることをサイトに伝えます。ブラウザと一致しないTLSハンドシェイクは、トラフィックがスクリプトから来ていることを示します。これらの2つのシグナルが一致しない場合、ハンドシェイクが勝ちます。なぜなら、それは偶然に偽装するのがはるかに難しいからです。千のクリーンな出口を回転させても、すべてのリクエストが同じpython-requestsのJA3を持っている場合、すべてのリクエストで失敗します。IPとフィンガープリントは別々の軸です — 両方を正しくする必要があります。

具体的には、Cloudflareで保護されたターゲットに対する通過率に現れます:デフォルトのrequestsクライアントはリクエストの約2%をクリアし、HTTP/2を使用するhttpxは少し良くなり、ブラウザと一致するクライアントは80%台中盤に達します。すべての場合で同じIPプールです。変数はTLSスタックです。Akamaiは、TLSフィンガープリントとHTTP/2フィンガープリント — SETTINGSフレーム値、ウィンドウサイズ、ストリーム優先度 — を組み合わせることでさらにハードルを上げるため、HTTP/2レイヤーがスクリプト化されているように見える場合、正しいJA3でも捕まることがあります。なぜAkamaiがほとんどのプロキシトラフィックをブロックするのかについての私たちの詳細な解説は、そのスタックについてさらに深く掘り下げます。

Cloudflareのクライアント別通過率の棒グラフ、デフォルトのpython-requestsからhttpx、curl_cffi、ヘッドレスブラウザまで
すべての場合で同じクリーンなIP — 通過率を変えるのはTLSスタックだけです。修正はハンドシェイクであり、出口ではありません。

実際に通過する偽装オプション

暗号文字列を調整して標準クライアントにブラウザハンドシェイクを取り付けることはできません — OpenSSLとurllib3のノブは、JA3が読み取るすべてのパラメータを公開しているわけではありません。機能するのは、ブラウザの正確なTLS方言を話すクライアントです:

# curl_cffi: a browser-shaped handshake in two lines
from curl_cffi import requests

session = requests.Session(impersonate="chrome120")
r = session.get(
    "https://example.com",
    proxies={"https": "http://USER:PASS@gate.quantumproxies.io:8000"},
    timeout=20,
)
print(r.status_code)  # matched JA3 + a clean residential exit

そのスニペットの中のプロキシに注目してください。偽装とクリーンな出口は補完的であり、代替ではありません:ブラウザ形状のハンドシェイクがTLSチェックを通過させ、クリーンな住宅IPがリクエストを評判ブロックリストから外します。それらを組み合わせることで、両方の軸を一度に修正します。

Scraper APIでTLSアームレースをスキップ

問題を丸ごと手放すタイミング

DIYの偽装は、ターゲットが検出を回転させ、HTTP/2フィンガープリントを追加し、またはJavaScriptの実行を要求するまで機能します — その時点で、ブラウザエミュレーションライブラリをセカンドジョブとして維持することになります。Scraper APIは、実際の回転するブラウザフィンガープリントを持ち、HTTP/2レイヤーに一致し、必要に応じてJSを実行し、1回の呼び出しでクリーンなHTML、Markdown、またはJSONを返します。それはTLSアームレースを他人の問題に変え、データに集中できるようにします。サイトが自動化をどのようにフラグするかの全体像については、すべてのプロキシ検出シグナルに関するガイドをご覧ください。

よくある質問

JA3フィンガープリントとは何ですか?

JA3フィンガープリントは、TLS ClientHelloから取得した5つのフィールド — TLSバージョン、暗号スイート、拡張機能、楕円曲線、ポイントフォーマット — のMD5ハッシュです。各ソフトウェアスタックがこれらのフィールドを異なる順序で並べるため、ハッシュはHTTPデータが交換される前にクライアント(Chrome、Firefox、curl、Python)を識別します。

JA3とJA4の違いは何ですか?

JA3は5つのClientHelloフィールドをMD5でハッシュし、ブラウザが拡張順序をランダム化すると壊れます。FoxIOのJA4は、ハッシュ前にフィールドをソートしてそのランダム化を生き延び、人間が読めるメタデータプレフィックスを追加し、QUIC/HTTP/3、ALPN、署名アルゴリズムをカバーします。JA4はより信頼性のある現代的なシグナルであり、JA3NはJA3のための正規化された暫定策です。

プロキシだけでTLSフィンガープリンティングをバイパスできますか?

いいえ。プロキシはIPを変更しますが、ハンドシェイクは変更しません。TLSフィンガープリントが既知のスクレイピングライブラリと一致する場合、出口を回転させても助けにはなりません — すべてのリクエストがボットのシグネチャを持ち続けます。ブラウザのTLSスタックを再現するクライアントが必要で、その上にIPの評判のためのクリーンなプロキシが必要です。

Python requestsには検出可能なTLSフィンガープリントがありますか?

はい。requestsは、独特の暗号と拡張順序を持つurllib3を使用しており、アンチボットベンダーによってカタログ化されているため、そのJA3は既知のボットシグネチャです。curl_cffiimpersonateプロファイルを切り替えて、ブラウザと一致するハンドシェイクを送信してください。

TLSフィンガープリンティングはHTTPの下で戦いを移動させました。これが、ヘッダートリックとIP回転が単独で十分でなくなった理由です。ハンドシェイクを一致させ、出口をクリーンに保てば、リクエスト1で403が発生する問題は消えます。これは技術的なガイダンスであり、サイトの規約を無視する免許ではありません — 常に法律とターゲットのルールに従ってスクレイピングしてください。

Scraper APIにJA3、JA4、HTTP/2を任せましょう