高価なレジデンシャルIPを取得し、ローテーションを設定し、リアルなUser-Agentを設定したのに、パーサーは依然としてCAPTCHAに飛ばされるか、空の応答を受け取ります。問題はほとんど常にIPではなく、TLSフィンガープリンタにあります。あなたがHTTPSリクエストを送信するライブラリは、実際のブラウザのようには「聞こえません」。Wildberries、Ozon、Cloudflare、Akamaiのアンチボットシステムは、あなたのIPアドレスを確認する前にこれを見抜きます。
TLSフィンガープリンタとは何か、なぜIPよりも重要なのか
クライアントがHTTPS接続を確立すると、サーバーにClientHelloパケットを送信します。これはTLSハンドシェイクの一部です。その中には、サポートされているTLSバージョンのリスト、暗号スイートのセット、拡張の順序、楕円曲線、圧縮アルゴリズムが暗号化されています。このパラメータのセットは、「ライブラリ + オペレーティングシステム + TLSスタックのバージョン」の組み合わせごとにユニークです。
Chrome、Firefox、Safariはそれぞれ独自の方法でClientHelloを形成し、このセットはリクエストごとにほとんど変わりません。これは、簡単に偽造できるIPやUser-Agentとは異なります。一方、標準のHTTPライブラリ(requests、urllib3、Javaの標準HttpClient、Node.jsの組み込みTLSスタック)は、ブラウザとは異なる方法でOpenSSLや他のライブラリを使用するため、全く異なるClientHelloを生成します。
そのため、完璧に「クリーンな」レジデンシャルIPを接続し、リアルなChromeの新しいUser-Agentを設定しても、ブロックされることがあります。サーバーは住宅用のIPを見て、「Chrome 124」というヘッダーを見ますが、TLSハンドシェイクは「これはPythonスクリプトです」と言っています。不一致は、アンチボットにとって明確な信号です。
アンチボットシステムはJA3/JA4でパーサーをどのように特定するか
ClientHelloのパラメータをコンパクトな識別子に変換するために、JA3(およびその新しいバージョンJA4)アルゴリズムが使用されます。これはTLSバージョン、暗号、拡張、曲線のリストを取得し、それらを文字列に結合してMD5でハッシュ化します。結果は、769,47-53-5-10...,0-23-65281...,29-23-24,0のような短いハッシュで、クライアントの「フィンガープリンタ」を一意に識別します。
アンチボットプロバイダー(Cloudflare、Akamai、PerimeterX、DataDome、WildberriesやOzonが使用する類似のもの)は、人気のあるHTTPライブラリ(requests、aiohttp、Scrapy、Node fetch、Java HttpClient、Go net/http)の既知のJA3/JA4ハッシュのデータベースを保持しています。ハッシュが「スクリプト」の既知のシグネチャと一致し、Chrome/Firefox/Safariのシグネチャと一致しない場合、リクエストは行動分析の前に疑わしいとマークされます。
次に、システムはTLSフィンガープリンタと宣言されたUser-Agentの一致を確認します。ヘッダーに「WindowsのChrome 124」と書かれていて、TLSフィンガープリンタがPythonの標準ライブラリのOpenSSL 1.1.1に対応している場合、これはTLS/HTTPの不一致と呼ばれ、自動化の検出において最も信頼性の高い信号の1つです。これにより、完璧なレジデンシャルIPと正しいヘッダーがあっても、パーサーが特定されます。
自分のTLSフィンガープリンタを確認する方法: ツール
問題を修正する前に、サーバーが見ているものを確認する必要があります。あなたのJA3/JA4ハッシュとClientHelloの完全なパラメータセットを表示するいくつかの公開サービスがあります:
- tls.peet.ws — JA3、JA4、暗号と拡張のリストをJSON形式で表示し、スクリプトによる自動チェックに便利です。
- ja3er.com — 特定のライブラリやブラウザに関連付けられた既知のJA3ハッシュのデータベース。
- browserleaks.com/tls — あなたのフィンガープリンタを典型的なブラウザと視覚的に比較します。
- Wireshark ローカル — スクリプトからリクエストを送信する際の生のClientHelloパケットを確認したい場合。
実践的なテストは簡単です: 通常のChromeでtls.peet.wsを開き、JA4ハッシュを記録します。次に、同じプロキシを介してあなたのパーサーから同じアドレスにGETリクエストを送信し、ハッシュを比較します。異なる場合、サーバーは「ブラウザ」と「スクリプト」の違いを各リクエストで認識しており、IPがどれだけクリーンであっても関係ありません。
Pythonでの確認: requests, httpx, curl_cffi
標準のPythonライブラリがパーサーを出力する理由を実際に見てみましょう。requestsを介した通常のリクエスト:
import requests
resp = requests.get("https://tls.peet.ws/api/all", proxies={
"https": "http://user:pass@proxy_host:port"
})
print(resp.json()["tls"]["ja4"])
# 結果は本物のChromeのJA4とは異なります。
# requestsはPythonの標準sslモジュールを使用するためです。
問題は、requestsとhttpxが、sslモジュールを介してシステムのOpenSSLを使用しているため、TLSの拡張の順序とセットが厳密に固定されており、Chrome/Firefoxとは一致しないことです。解決策は、ブラウザの実際のTLSプロファイルを再現するパッチされたcurlを使用するcurl_cffiライブラリです:
from curl_cffi import requests as cffi_requests
resp = cffi_requests.get(
"https://tls.peet.ws/api/all",
impersonate="chrome124",
proxies={"https": "http://user:pass@proxy_host:port"}
)
print(resp.json()["tls"]["ja4"])
# ハッシュはデスクトップの本物のChrome 124と同じになります。
impersonateパラメータは、curl_cffiがClientHelloだけでなく、HTTP/2ヘッダーの順序(フレーム順序)も再現するようにします。これはフィンガープリンタにも含まれます。tls-clientライブラリ(Go用)や、実際のブラウザを介してパーシングする人のためのundetected-chromedriverも同様のアプローチを使用しています。
ヘッドレスブラウザ(Playwright、Puppeteer、Selenium)を介してパーシングを行う場合、TLSフィンガープリンタはChromium/Firefoxエンジンによって生成され、デフォルトで実際のブラウザと一致します。しかし、ここで別の問題が発生します — JSレベルでの自動化のシグネチャ(webdriverフラグ、canvasフィンガープリンタ)があるため、ヘッドレスシナリオにはplaywright-stealthのようなパッチが追加で必要です。
TLS + HTTP/2 + ヘッダー: なぜこの組み合わせが重要なのか
TLSフィンガープリンタは、検出のための一つの層に過ぎません。アンチボットシステムは、同時に複数のレベルを照合します:
- TLS ClientHello (JA3/JA4) — 暗号と拡張のセット。
- HTTP/2フィンガープリンタ — 疑似ヘッダーの順序(:method、:path、:authority)、SETTINGSフレームの設定、ウィンドウサイズ。
- HTTPヘッダー — 通常のヘッダーの順序とセット(Accept-Language、Sec-Ch-Ua、Sec-Fetch-*)。
- User-Agent — TLSプロファイルのバージョンに一致する必要があります: UAが「Chrome 124」と言い、TLSがChrome 110に一致する場合、これも疑わしいです。
よくある間違いは、User-Agentを最新のChromeバージョンに更新し、curl_cffiや他のライブラリのTLSプロファイルを更新するのを忘れることです。このようなバージョンの不一致は、完全なマスキングがないのと同じくらいアンチボットに明確に見えます。impersonateのバージョンとUser-Agentのバージョンが一致していることを確認し、新しいブラウザのバージョンがリリースされる際には両方のパラメータを同期して更新してください。
もう一つのポイントは、ヘッダーの順序です。ブラウザはヘッダーを厳密に定められた順序で送信しますが、多くのHTTPライブラリはそれらをアルファベット順またはコードに追加された順序でソートします。ヘッダーのセットがブラウザと同じであっても、順序が間違っていると、DataDomeのような高度なアンチボットシステムにとって追加の信号となります。
プロキシの役割: なぜクリーンなIPでは救われないのか
レジデンシャルIPは特定のタスクを解決します — 地理、ASN、アドレスの評判による疑念を減らします。データセンターのIPは、そこから大量の自動化トラフィックが流れるため、しばしばブラックリストに載っていますが、レジデンシャルIPは実際のプロバイダーや一般ユーザーに属しています。Wildberries、Ozon、またはAvitoのパーシングにはこれが重要です: クリーンなIPがなければ、リクエストはこの特性だけでブロックされ、TLSを確認することすらありません。
しかし、IPとTLSフィンガープリンタは、独立した保護層であり、異なる問題を解決します。IPはサーバーに「どこから」リクエストが来たかを伝え、TLSフィンガープリンタは「何を使って」送信されたかを伝えます。したがって、クリーンなIPと正しいTLSプロファイルの組み合わせは、安定したパーシングのための最小限のセットです。高頻度のリクエストや攻撃的なアンチボットに対しては、レジデンシャルプロキシを使用する方が良いです。これにより、IPの評判による禁止の割合が低くなりますが、必ず実際のブラウザのTLSプロファイルを正しく再現するライブラリと組み合わせてください。
マーケットプレイスでの価格監視では、速度とリクエストの量が重要であるため、データセンタープロキシとcurl_cffiを介したTLSマスキングを組み合わせて使用することがよくあります — これはレジデンシャルプロキシよりも安価で、サイトのアンチボットシステムがそれほど攻撃的でない場合には十分に効果的です。また、サイトがモバイルネットワークを積極的に確認するタスク(例えば、アプリのモバイルバージョンをAPIを介してパーシングする場合)では、モバイルプロキシを使用します — これにより、オペレーターのネットワークの評判によって追加の信頼レベルが得られます。
検出されないパーサーの設定チェックリスト
パーサーを本番環境で起動する前に、確認を一つのプロセスにまとめてください:
- tls.peet.wsを介してスクリプトのJA4ハッシュを測定し、同じバージョンの実際のブラウザと比較します。
- TLSインパーソネーションをサポートするライブラリを使用します: curl_cffi(Python)、tls-client(Go)、CycleTLS(Node.js)。
- TLSプロファイルのバージョン(impersonate)をUser-Agentのバージョンと同期させます。
- HTTPヘッダーの順序を確認します — 実際のブラウザと一致する必要があり、アルファベット順ではありません。
- タスクの地理に応じて、クリーンなレジデンシャルまたはモバイルIPを接続します。
- IPのローテーションをTLSプロファイルとは別に設定します — 一方を他方に厳密に結びつけないでください。
- 新しいChromeのバージョンがリリースされる際には、定期的にTLSプロファイルを更新します — 古いシグネチャは、思っているよりも早くアンチボットのデータベースに入ります。
- JSチェックがあるシナリオ(Cloudflare Challenge)では、クリーンなHTTPクライアントの代わりにstealthパッチを適用したヘッドレスブラウザを使用します。
ライブラリとツールの比較
| ツール | ブラウザのTLSフィンガープリンタ | 速度 | 使用するタイミング |
|---|---|---|---|
| requests / httpx | いいえ、スクリプトを出力します | 高い | TLS検出のないサイト、内部API |
| curl_cffi | はい、正確なコピー | 高い | マーケットプレイス、Cloudflare/Akamaiのアンチボット |
| tls-client (Go) | はい | 非常に高い | 高い負荷、大量パーシング |
| Playwright / Puppeteer | はい、実際のエンジン | 低い | JSレンダリング、Cloudflare Challenge、複雑なSPA |
| Scrapy (標準) | いいえ | 高い | 厳しいアンチボット保護のないサイト |
結論
TLSフィンガープリンタは、多くのパーサーが完全に無視している保護層であり、理想的なIPとUser-Agentの選定にリソースを費やしながら、TLSハンドシェイクの構造自体がサーバーがヘッダーを確認する前に自動化を示すことを忘れています。解決策は、TLSインパーソネーションをサポートするライブラリ(curl_cffi、tls-client)を使用し、プロファイルのバージョンをUser-Agentと同期させ、スケールアップ前に最終的なJA4ハッシュを確認することです。
IPは依然として重要な要素です — クリーンなアドレスがなければ、理想的なTLSフィンガープリンタでもネットワークの評判によるブロックを回避することはできません。マーケットプレイスのパーシングや価格監視には、正しいTLS設定とレジデンシャルプロキシを組み合わせることが理にかなっています — この組み合わせは両方の検出層を閉じ、長時間のパーシングセッションでの禁止の割合を大幅に減少させます。