Cloudflare防御を突破するスクレイピング環境の構築【2026年・検知レイヤー別】
TL;DR
Cloudflareに弾かれるのは「ツールが弱い」からではなく、検知が複数レイヤーで多段構成になっているから。python-requests 一発で通そうとするから止まる。
突破は層ごとに対策を積む。IP評判(住宅用プロキシ)→ TLS指紋(curl_cffi)→ JS指紋・Turnstile(nodriver / Camoufox) の順で、必要な層だけ重ねるのが2026年の現実解。最初からブラウザを起動するのは遅くて高い。HTTPで通るならHTTPで通すのが鉄則。
本記事は技術解説です。スクレイピング対象の利用規約・robots.txt・著作権・個人情報保護法を遵守し、自社サイトの検証や許諾済みデータ取得など適法な範囲で利用してください。攻撃的・規約違反の用途は想定していません。防御側の設定はCloudflare WAFで悪質Botをブロックする設定を参照。
なぜ「層」で考えるのか
Cloudflareは単一のチェックでBotを判定していない。リクエストが届いてから、複数の独立した検知を順に通過させ、各層のスコアを合算して Trust Score(信頼スコア) を出す。スコアが閾値を割るとブロック・チャレンジに落とされる。
重要なのは、この閾値がドメインごとに学習で動的に変わること(per-domain Trust Score)。同じツールでもサイトAは通ってサイトBは弾かれる。だから「これを使えば必ず通る」という万能ツールは存在しない。通らなかった層を特定して、その層だけ対策を足すのが正しい進め方になる。
Cloudflareの検知レイヤーと突破手段(2026年版)
| 層 | 検知内容 | 突破手段 | 主なツール | 弾かれた時のコード |
|---|---|---|---|---|
| L1 IP評判 | データセンターIP・リクエスト頻度を識別 | 住宅用/モバイルプロキシをローテーション・遅延挿入 | 住宅用プロキシSaaS | 1020 / 1015 |
| L2 TLS指紋(JA3/JA4) | TLSハンドシェイクの構成から自動クライアントを識別 | 実ブラウザのTLS署名を偽装 | curl_cffi / curl-impersonate | 403 / 1020 |
| L3 HTTP/2指紋 | HTTP/1.1利用や不自然なフレーム順を検出 | HTTP/2(一部HTTP/3)を有効化 | curl_cffi / httpx(http2=True) | 403 |
| L4 JS指紋 | JS実行でハードウェア・OS・headless属性を探る | 実ブラウザを起動しnavigator.webdriver等を秘匿 |
nodriver / Camoufox / SeleniumBase UC | 1010 |
| L5 Turnstile | スコア低下時にチャレンジを出す | ブラウザで解く・本番はマネージド解決 | nodriver / Camoufox / 解決API | 403 |
| L6 行動分析 | リクエスト順序・タイミング分散・リソース読込をML判定 | ランダム遅延・自然な遷移・CSS/フォント読込・マウス操作 | nodriver(非同期ネイティブ秘匿) | 1015 / 429 |
L1: IP評判 — ここを外すと何をしても無駄
最初の関門。データセンターIP(AWS・GCP・主要VPS)からのアクセスは、それだけで信頼スコアが大きく下がる。TLSやJSをどれだけ完璧に偽装しても、IPが安いVPSのままなら積み上げが台無しになる。
必要なのは住宅用(Residential)プロキシ
- データセンタープロキシ: 安いが、Cloudflareは既知レンジを把握済み。短期・低防御サイト向け
- 住宅用プロキシ: 実在の家庭回線のIPを経由。信頼スコアが高い。本記事の主対象
- モバイルプロキシ: キャリアIP。最も信頼が高いが高価。最終手段
住宅用プロキシは従量課金(GB単位)が主流。画像・CSS・フォントまで全部プロキシ経由で取ると課金が一気に膨らむので、不要リソースの読込を切る設計が運用コストを左右する。
ローテーションの基本
同一IPで連続リクエストを打つと L6(行動分析)で頻度異常として捕まる。
- セッション維持が不要なら: リクエストごとにIPを変える(rotating endpoint)
- ログイン状態が必要なら: スティッキーセッション(一定時間同一IP)を使い、Cookieとセッションを紐付ける
- リクエスト間に 2〜5秒のランダム遅延 を挟む。等間隔は機械的でかえって目立つ
L2 / L3: TLS指紋とHTTP/2指紋 — curl_cffi で大半が片付く
python-requests や標準の urllib は、TLSハンドシェイクの構成(暗号スイートの順序・拡張)が実ブラウザと明確に違う。この JA3 / JA4 フィンガープリント だけでBotと判定される。
解決策が curl_cffi(curl-impersonateのPythonバインディング)。実ブラウザのTLS署名とHTTP/2フレームを丸ごと模倣する。
# pip install curl_cffi
from curl_cffi import requests
resp = requests.get(
"https://example.com",
impersonate="chrome124", # 最新に近いプロファイルを使う
proxies={"https": "http://user:pass@residential-proxy:port"},
)
print(resp.status_code)
2026年の注意点:プロファイルは「新しいもの」を使う
curl_cffi には chrome99 chrome110 chrome116 chrome120 chrome123 chrome124 firefox safari15_3 などのプロファイルがある。
古いプロファイルを使うと逆に怪しい。 2026年に chrome99 を名乗るブラウザは実在しない。指紋とUser-Agentの「バージョンのつじつま」が合っていないと、それ自体が検知シグナルになる。常に最新に近いプロファイルへ追従する。
この層の限界
curl_cffi は TLS・ヘッダ・HTTP/2のチェックまでしか通せない。対象が JavaScriptチャレンジやTurnstileを出してきたら、HTTPクライアントでは突破できない。ここで初めてブラウザを起動する判断になる。
L4 / L5: JS指紋とTurnstile — ブラウザを「起動する」段階
HTTPで弾かれた(JSチャレンジが返ってきた)ら、実ブラウザを動かす。ただし 2026年は「どのツールを使うか」が大きく変わった。
古い定番はもう効かない
puppeteer-extra-plugin-stealth: 2025年2月時点で実質deprecated。現行のCloudflareは素通しできないundetected-chromedriver: メンテが鈍化。後継に置き換わった
2026年の現行ツール
| ツール | 特徴 |
|---|---|
| nodriver | undetected-chromedriverの後継。非同期ネイティブ・CDP痕跡を抑えた秘匿が標準。第一候補 |
| Camoufox | Firefoxベースの秘匿ブラウザ。指紋偽装を深い層で実装 |
| SeleniumBase UC Mode | Selenium資産を活かしつつUC(秘匿)モードで運用 |
# nodriver の最小例(pip install nodriver)
import nodriver as uc
async def main():
browser = await uc.start(
browser_args=["--proxy-server=residential-proxy:port"],
)
page = await browser.get("https://example.com")
await page.sleep(3) # チャレンジ通過を待つ
html = await page.get_content()
print(html[:200])
uc.loop().run_until_complete(main())
CDP(Chrome DevTools Protocol)の罠
通常のヘッドレス自動化はCDPコマンド処理に特有のミリ秒単位の遅延が出る。Cloudflareはこのタイミングの不自然さまで見る。nodriverのような秘匿ツールはCDP痕跡の抑制を組み込んでいるが、それでもヘッドレス(--headless)は検出されやすい。本番は仮想ディスプレイ(Xvfb)でヘッドフルを動かす構成が安定する。
Turnstileは「解く」より「出させない」
Turnstileは信頼スコアが落ちたときに出る。Turnstileが頻発する=その手前(L1〜L4)が弱いサイン。解決APIに頼る前に、プロキシ品質・TLS整合・行動パターンを見直すほうが安く安定する。どうしても必要な本番運用ではマネージドの解決サービスを使う。
L6: 行動分析 — 「人間に見えるか」
最終層。リクエストの順序・間隔のばらつき・リソース読込・マウス/キーボード操作をML(per-customerモデル)で判定する。
- 遷移を自然に: いきなり深いURLを叩かず、トップ→カテゴリ→詳細と辿る
- リソースを読む: 人間のブラウザはCSS・フォント・画像も取得する。HTMLだけ取ると不自然(ただしプロキシ課金とトレードオフ)
- タイミングを散らす: 固定の
sleep(3)は機械的。範囲乱数にする - 同じ指紋を使い回さない: 同一canvasハッシュを数百リクエストで再利用すると即フラグ
環境構成の現実解:段階的エスカレーション
全部入りのブラウザ自動化から始めるのは遅くて高くて壊れやすい。安い層から試して、弾かれた層だけ重ねる。
1. curl_cffi + 住宅用プロキシ で叩く(速い・安い)
↓ 403 / JSチャレンジが返る
2. nodriver(ヘッドフル + Xvfb)+ 同じ住宅用プロキシ に切替
↓ Turnstile が頻発する
3. プロキシ品質・遅延・遷移を見直す(解決APIは最後)
コスト感の目安:
- Chromeインスタンスは1つあたり約500MBのメモリを食う。並列スケールにはKubernetes/ECS等のオーケストレーションが要る
- 住宅用プロキシはGB課金。ブラウザ起動=全リソース取得=課金増。HTTPで済む対象をブラウザで取るのは二重の無駄
エラーコードの読み方
弾かれたとき、Cloudflareの返すコードでどの層に落ちたか当たりがつく。
| コード | 意味 | 疑うべき層 |
|---|---|---|
| 1020 | Access Denied(ルール/IP) | L1 IP評判・WAFカスタムルール |
| 1015 | Rate Limited | L1頻度・L6行動 |
| 1010 | ブラウザ署名拒否(自動化検出) | L4 JS指紋 |
| 403 | Forbidden(チャレンジ失敗含む) | L2 TLS・L5 Turnstile |
| 429 | Too Many Requests | L1頻度・L6行動 |
| 503 | チャレンジページ提示中 | L4/L5(JS未実行) |
1010が出たらHTTPクライアントでは無理=ブラウザ層へ。403がTLS整合済みでも出るならプロキシIPの評判(L1)を疑う。
合法ラインと運用上の注意
技術的に通せることと、通してよいことは別。
- robots.txt・利用規約を確認する。明示的に禁止された収集は規約違反・場合により不正アクセス禁止法の論点になる
- 個人情報・著作物の収集は国内法(個人情報保護法・著作権法)の範囲で
- サーバーに負荷をかけない。遅延・並列数を抑えるのは検知回避だけでなくマナー
- 自社サイトの防御検証やAPI提供のない公開データの取得など、適法な用途に限定する
まとめ
| 層 | 対策 | 2026年の主ツール |
|---|---|---|
| L1 IP評判 | 住宅用プロキシ・ローテーション・遅延 | 住宅用プロキシSaaS |
| L2 TLS指紋 | 実ブラウザTLS偽装・新しいプロファイル | curl_cffi |
| L3 HTTP/2 | HTTP/2有効化 | curl_cffi / httpx |
| L4 JS指紋 | 秘匿ブラウザ・ヘッドフル+Xvfb | nodriver / Camoufox |
| L5 Turnstile | 手前を固めて出させない | nodriver / 解決API |
| L6 行動分析 | 自然な遷移・乱数遅延・指紋を使い回さない | nodriver |
万能ツールはない。弾かれた層を特定し、安い層から積む。curl_cffiで通るなら一番安い。それで止まったら初めてブラウザ。コストとメンテはこの順で跳ね上がる。
会員限定:プロキシローテーション設定 + 段階エスカレーション・シェルスクリプト
curl_cffi での住宅用プロキシ・ローテーション実装(スティッキー/ロータリー切替・リトライ・指数バックオフ込み)と、「まずHTTPで叩いて、403/JSチャレンジを検出したら自動でnodriverに切り替える」段階エスカレーションのシェルスクリプト一式を会員限定で公開しています。住宅用プロキシの課金を抑えるリソース読込フィルタ設定も同梱。
この続きはメンバー限定です
メールアドレスを登録すると、本記事の設定ファイル・コードと全 10 本の実践記事が読めます。無料・いつでも解除可。