クリーンな residential IP を買い、それらを完璧にローテーションしているのに、それでも最初のリクエストで 403 が返ってくる。問題は IP ではありません——あなたの TLS ハンドシェイクです。TLS フィンガープリントにより、サーバーは HTTP リクエストの 1 バイトも読まれる前にクライアントライブラリを特定できます。本ガイドは JA3/JA4 を説明し、Python の requests がなぜ検知が容易なのかを示し、curl_cffi と tls-client で本物のブラウザになりすます動作するコードを提供します。
あらゆるクライアントが HTTPS 接続を開くとき、TLS バージョン、暗号スイート、拡張、楕円曲線、そしてそれらすべての順序を広告する ClientHello を送ります。その順序は、それを構築したライブラリに驚くほど固有です。これをハッシュ化すると JA3 フィンガープリント(あるいはより新しく堅牢な JA4)が得られます。
Chrome は 1 つのフィンガープリントを生成します。Firefox は別のものを。Python の requests(urllib3 と OpenSSL の上に構築)は「自動化」と叫ぶフィンガープリントを生成します——しかもそれは何百万もの bot にわたって同一です。anti-bot システムはこれらのブロックリストを保持しています。あなたの IP がどれほど residential でも、known-bot な JA3 にはフラグが立ちます。
何かを直す前に、まず計測しましょう。あなたのスクレイパーから JIBAO の無料の JA3/JA4 フィンガープリントチェッカーにリクエストを送り、本物の Chrome が示すものと比較してください。JA3 ハッシュが異なれば、ターゲットはあなたを人間と区別できます——そして Cloudflare もそうです。
requests と httpx は TLS をシステムの OpenSSL に委ねます。ヘッダーや User-Agent をいくらでも変えられますが、その下のハンドシェイクは依然として OpenSSL のものであり、Chrome のものではありません。ハンドシェイクのなりすましなしのヘッダーのなりすましこそ、「ブラウザのヘッダーをコピーしたのにまだブロックされる」が起きる最も一般的な理由です。ブラウザの実際の TLS スタックを模倣するクライアントが必要です。
curl_cffi は curl-impersonate——本物のブラウザの TLS と HTTP/2 フィンガープリントを再現する curl のビルド——にバインドします。引数 1 つで、あなたのハンドシェイクは Chrome のように見えます:
# pip install curl_cffi
from curl_cffi import requests
# impersonate a real Chrome TLS + HTTP/2 fingerprint
r = requests.get(
"https://tls.browserleaks.com/json",
impersonate="chrome131",
)
print(r.json()["ja3_hash"]) # now matches real Chrome
API は requests をミラーしているので、既存のスクレイパーの移行はほぼ 1 行の import 変更で済みます。サポートされるターゲットには最近の Chrome、Edge、Safari、Firefox のビルドが含まれます——1 つ選んで最新に保ってください。フィンガープリントはブラウザの更新とともにローテーションするからです。
フィンガープリント一致と IP ローテーションは補完的であって、代替ではありません。両方使ってください:クリーンな residential IP 越しのブラウザ級のハンドシェイクこそ、実際に通り抜けるものです:
from curl_cffi import requests
PROXY = "socks5h://USERNAME:[email protected]:10001"
r = requests.get(
"https://example.com/protected",
impersonate="chrome131",
proxies={"http": PROXY, "https": PROXY},
timeout=30,
)
print(r.status_code)
tls-client(Go の uTLS 実装をラップした Python ラッパー)も、名前付きプロファイルの大きなライブラリを備えた、もう 1 つの堅実な選択肢です:
# pip install tls-client
import tls_client
session = tls_client.Session(
client_identifier="chrome_120",
random_tls_extension_order=True,
)
session.proxies = {
"http": "socks5h://USERNAME:[email protected]:10001",
"https": "socks5h://USERNAME:[email protected]:10001",
}
r = session.get("https://example.com/protected")
print(r.status_code)
random_tls_extension_order=True は拡張の順序をシャッフルして、静的で再利用可能なフィンガープリントを避けます——完全一致の JA3 を時系列で追跡するシステムに対して有効です。
一部のターゲットは、どんな HTTP クライアントも再現しない JavaScript 実行シグナル(canvas、WebGL、イベントのタイミング)をチェックします。その場合は、代わりに本物のブラウザを駆動してください——Playwright と Puppeteer でプロキシを使うを stealth とともに参照。トレードオフはコストと速度です:curl_cffi のような HTTP クライアントはリクエストあたりずっと安いので、足りる限りそれらを使い、最も手強いターゲットのためにフルブラウザを取っておきましょう。
curl_cffi(impersonate=)または tls-client でハンドシェイクを一致させる——ヘッダーだけでは不十分。TLS フィンガープリントは、ほとんどの「クリーンな IP なのにまだブロックされる」話で欠けている層です。ハンドシェイクを直し、residential IP を保てば、成功率は跳ね上がります。最も手強い WAF に対するフルスタックについては、2026 年版 Cloudflare 回避レシピをお読みください。
500MB の無料トラフィックと、ブラウザ級の TLS フィンガープリントと組み合わせる residential IP を手に入れましょう。
無料トライアルを開始新規ユーザーは登録時に500MBを獲得、さらに初回チャージにボーナスが付きます。期間限定オファーです。