スクレイピング時のCAPTCHA対処法

CAPTCHA 型, 解決よりも効果的である予防戦略, CAPTCHA 回避におけるプロキシの重要な役割. 検出とルーティングのコード例.

スクレイピング時のCAPTCHA対処法

なぜCAPTCHAs スクレーパーの最大の障害

CAPTCHAsはボットから人間を区別するために存在しており、それらはますます効果的です。 スクレーパーがCAPTCHAに遭遇すると、ターゲットサイトが自動動作を検出したことを意味します。リクエストの頻度が高すぎ、IPは低い信頼、またはブラウザの指紋が疑わしいと見ました。 CAPTCHAの最高の戦略は、解決ではなく、予防です。

このガイドは、あなたが遭遇するCAPTCHAのタイプをカバーします, なぜ予防は、解決よりも効果的で安く、, そして、どのようにプロキシは、CAPTCHAsを完全に回避するために重要な役割を果たしています.

この記事は私たちの一部です ウェブスクレイピングプロキシの完全なガイド シリーズ。 検出システムを理解するには、 アンチボットシステムがプロキシを検出する方法. .

2026年にCAPTCHAsの種類

2026年にCAPTCHAsの種類
タイプ:仕組みバイパスへの難易度
reCAPTCHA v2 (チェックボックス)「ロボットじゃない」をクリック+オプション画像チャレンジメディア
reCAPTCHA v3 (見えない)ユーザーインタラクションなしで動作 0.0-1.0 をスコアハード
hカプチャ画像選択課題(reCAPTCHA v2と類似)メディア
Cloudflareの回転木戸ブラウザの課題、通常は見えないハード
カスタムイメージCAPTCHAsサイト固有の課題(歪んだテキスト、パズル)変数
仕事の証拠ブラウザはハッシュを計算する必要があります (攻撃の下でCloudflare)メディア

見えない帽子 リアルな脅威

スクレーパーにとって最も危険なCAPTCHAは、決して見られないものです。 reCAPTCHAのv3 そして、 Cloudflareの回転木戸 バックグラウンドで実行し、マウスの動きを分析し、動作をスクロールし、パターンをタイプし、ブラウザ環境を分析します。 どのチャレンジも表示せずに信頼スコアを割り当て、スコアが低すぎると、リクエストはサイレントブロックまたはリダイレクトされます。

予防対ソルビング:予防が勝つ理由

予防対ソルビング:予防が勝つ理由
アプローチCAPTCHAあたりのコストスピード信頼性スケーラビリティ
予防(CAPTCHAsトリガーなし)ドルログイン最も高いよくある質問
CAPTCHAソリューションサービス$ 1-3 / 1,00010-60秒85-95%モデレート
AIベースの自動解決$ 2-5 / 1,0005-30秒70-90%のお問い合わせ
スケールで、予防はお金と時間を節約します。 1日あたりの100,000 CAPTCHAs を解決すると $100-500 とレイテンシの時間を追加します。 それらが適切なプロキシおよび要求管理を越えて余分費用を全く防いで下さい。

予防戦略1:高品質の住宅用プロキシを使用する

単一の最も効果的なCAPTCHA予防措置は、高い信頼スコアを持つ住宅用プロキシを使用しています。 住宅用IPは、ISPによって実際の世帯に割り当てられます。そのため、Webサイトは純正のユーザートラフィックからリクエストを簡単に区別することはできません。

import requests
# Residential proxy — high trust score, fewer CAPTCHAs
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def scrape_with_residential(url: str) -> str:
    """Use residential proxies to avoid triggering CAPTCHAs."""
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/120.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
    })
    resp = session.get(url, timeout=30)
    return resp.text

ProxyHatの住宅プールは、実際のISPからIPを提供します 190カ国以上、各要求に最も高い信頼性のスコアを与えて下さい。 お問い合わせ Scrapingのための住宅対データセンターのプロキシ 詳細な比較のため。

予防戦略2:現実的な要求パターン

CAPTCHAは、多くの場合、ロボットの動作パターンによってトリガーされます, だけでなく、IPの評判. あなたのスクレーパーは人間を見させます:

Pythonの実装

import requests
import random
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15",
]
REFERRERS = [
    "https://www.google.com/",
    "https://www.bing.com/",
    "https://duckduckgo.com/",
    None,  # Direct visit
]
def human_like_scrape(urls: list[str]) -> list[str]:
    """Scrape with realistic human behavior patterns."""
    results = []
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    for url in urls:
        # Randomize headers per request
        headers = {
            "User-Agent": random.choice(USER_AGENTS),
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "en-US,en;q=0.9",
            "Accept-Encoding": "gzip, deflate, br",
            "Connection": "keep-alive",
            "Upgrade-Insecure-Requests": "1",
        }
        referrer = random.choice(REFERRERS)
        if referrer:
            headers["Referer"] = referrer
        try:
            resp = session.get(url, headers=headers, timeout=30)
            results.append(resp.text)
        except requests.RequestException:
            results.append(None)
        # Human-like delays: 1-5 seconds with occasional longer pauses
        if random.random() < 0.1:
            time.sleep(random.uniform(5, 15))  # 10% chance of long pause
        else:
            time.sleep(random.uniform(1, 4))
    return results

Node.js 実装

const HttpsProxyAgent = require('https-proxy-agent');
const fetch = require('node-fetch');
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
const USER_AGENTS = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
];
function randomDelay() {
  const isLongPause = Math.random() < 0.1;
  const ms = isLongPause
    ? 5000 + Math.random() * 10000
    : 1000 + Math.random() * 3000;
  return new Promise(r => setTimeout(r, ms));
}
async function humanLikeScrape(urls) {
  const results = [];
  for (const url of urls) {
    const headers = {
      'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Accept-Language': 'en-US,en;q=0.9',
    };
    try {
      const res = await fetch(url, { agent, headers, timeout: 30000 });
      results.push(await res.text());
    } catch {
      results.push(null);
    }
    await randomDelay();
  }
  return results;
}

防止戦略3:スマートなIPの回転

IP を回転させる方法は、CAPTCHA レートに直接影響します。 攻撃的な回転(新しいIPリクエスト)は、同じセッションパスにアクセスするさまざまなIPからのリクエストのシリーズが疑わしいように、実際にいくつかのサイトにCAPTCHAsを増やすことができます。

import requests
import uuid
def create_session_for_site(site_id: str):
    """Create a sticky session that maintains the same IP per site.
    This avoids the suspicious pattern of different IPs accessing the same flow."""
    session_id = uuid.uuid5(uuid.NAMESPACE_URL, site_id).hex[:8]
    proxy = f"http://USERNAME-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
    session = requests.Session()
    session.proxies = {"http": proxy, "https": proxy}
    return session
# Same IP for all requests to a specific product section
session = create_session_for_site("example.com-electronics")
page1 = session.get("https://example.com/electronics?page=1")
page2 = session.get("https://example.com/electronics?page=2")
page3 = session.get("https://example.com/electronics?page=3")
# Different IP for a different section
session2 = create_session_for_site("example.com-clothing")
clothes1 = session2.get("https://example.com/clothing?page=1")

より多くの回転パターンについては、 大規模なスクレイピングのためのプロキシ回転戦略. .

予防戦略4:リスペクト率制限

CAPTCHAは、多くの場合、レート制限後のエスカレーションです。 レート制限信号を適切に処理する場合、CAPTCHAs はほとんど表示されません。

import requests
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
CAPTCHA_INDICATORS = [
    "captcha",
    "recaptcha",
    "hcaptcha",
    "challenge",
    "verify you are human",
    "please complete the security check",
]
def is_captcha_page(html: str) -> bool:
    """Detect if the response is a CAPTCHA challenge page."""
    html_lower = html.lower()
    return any(indicator in html_lower for indicator in CAPTCHA_INDICATORS)
def scrape_with_captcha_detection(urls: list[str]) -> list[dict]:
    results = []
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    captcha_count = 0
    backoff = 2.0
    for url in urls:
        try:
            resp = session.get(url, timeout=30)
            if resp.status_code == 200 and not is_captcha_page(resp.text):
                results.append({"url": url, "status": "success", "body": resp.text})
                captcha_count = 0
                backoff = max(backoff * 0.9, 1.0)  # Reduce backoff on success
            elif is_captcha_page(resp.text) or resp.status_code == 403:
                captcha_count += 1
                results.append({"url": url, "status": "captcha"})
                if captcha_count >= 3:
                    # Too many CAPTCHAs — increase backoff significantly
                    backoff = min(backoff * 3, 60)
                    print(f"CAPTCHA streak: {captcha_count}. Backing off to {backoff:.0f}s")
                else:
                    backoff = min(backoff * 1.5, 30)
        except requests.RequestException as e:
            results.append({"url": url, "status": "error", "error": str(e)})
        time.sleep(backoff)
    return results

包括的なレート制限戦略については、 スクレイピング率は説明を制限します. .

CAPTCHA:検出とルーティング

完璧な予防であっても、CAPTCHAは無効です。 特別な処理のためにCAPTCHAページをルートできるように、パイプラインに検出をビルドします。

import requests
from enum import Enum
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
class ResponseType(Enum):
    SUCCESS = "success"
    CAPTCHA = "captcha"
    BLOCKED = "blocked"
    ERROR = "error"
def classify_response(resp: requests.Response) -> ResponseType:
    """Classify a response to determine next action."""
    if resp.status_code == 403:
        return ResponseType.BLOCKED
    if resp.status_code == 429:
        return ResponseType.BLOCKED
    if resp.status_code == 200:
        html = resp.text.lower()
        captcha_signals = ["captcha", "recaptcha", "hcaptcha", "cf-challenge"]
        if any(s in html for s in captcha_signals):
            return ResponseType.CAPTCHA
        return ResponseType.SUCCESS
    return ResponseType.ERROR
def scrape_with_routing(urls: list[str]) -> dict:
    """Scrape URLs and route based on response classification."""
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    results = {"success": [], "captcha": [], "blocked": [], "error": []}
    for url in urls:
        try:
            resp = session.get(url, timeout=30)
            response_type = classify_response(resp)
            results[response_type.value].append(url)
            if response_type == ResponseType.CAPTCHA:
                # Route to CAPTCHA queue for manual or service-based solving
                print(f"CAPTCHA detected: {url}")
            elif response_type == ResponseType.BLOCKED:
                # Rotate IP and retry
                print(f"Blocked: {url}")
        except requests.RequestException:
            results["error"].append(url)
    print(f"Success: {len(results['success'])}, "
          f"CAPTCHAs: {len(results['captcha'])}, "
          f"Blocked: {len(results['blocked'])}")
    return results

CAPTCHA 予防チェックリスト

  • 住宅用プロキシを使用してください。 最も高い信頼スコアを持ち、最も少ないCAPTCHAをトリガーします。 ProxyHat住宅プロキシ クリーンIPを数百万台供給
  • 実際のヘッダーを設定します。 常にユーザーエージェント、アクセプト、アクセプト言語、およびその他の標準ブラウザヘッダーを送信します。
  • 人間のような遅延を追加します。 ランダム 1-5 秒 リクエスト間の遅延 時々 長い一時停止.
  • セッションを適切に維持します。 付随するセッションでクッキーと一貫性のあるIPを使用。
  • Robots.txt のリスペクト robots.txt が escalate を CAPTCHAs に違反するサイトをより速く検出します。
  • CAPTCHA レートを監視します。 CAPTCHA率が5%を超えた場合、あなたのアプローチで何かが修正する必要があります。
  • ピーク時間にスクレイピングしないでください。 抗ボットシステムは、高トラフィック期間中により攻撃的です。
  • ユーザーエージェントを適切に回転させます。 最近、現実的なブラウザ文字列を使用します。 同じセッションでモバイルとデスクトップUAsを混在させないでください。

ご希望の言語でのプロキシ設定については、 Pythonでプロキシを使用する, Node.js でプロキシを使用するまたは Goのプロキシの使用. 探検する ウェブスクレイピング用のProxyHat はじめに。

よくある質問

プロキシはCAPTCHAsを避けることができますか?

はい、かなり。 高品質の住宅用プロキシには、CAPTCHA をトリガーするような、きれいな IP の評判があります。 データセンターIPは、自動ソースが知られているため、より頻繁にフラグが付けられます。 住宅用プロキシと適切なパターン要求の組み合わせは、ほとんどターゲットのCAPTCHAをほぼ排除します。

スケールでCAPTCHAsを処理する最も安い方法は?

予防策 住宅用プロキシや適切なスクレイピングパターンへの投資は、規模でCAPTCHAソリューションサービスよりもはるかに少ないです。 CAPTCHAsを解決する必要がある場合は、サードパーティサービスは1,000ドルから1〜3ドルかかりますが、リクエストごとに10〜60秒のレイテンシを追加します。

ヘッドレスブラウザはCAPTCHAに役立ちますか?

彼らは、JavaScriptの実行と実際のブラウザ環境を提供することで、見えないCAPTCHA(reCAPTCHA v3、回転木戸)を支援します。 しかし、彼らはより遅く、より多くのリソース集中的です。 特にブラウザレベルの検証を必要とするターゲットにのみ使用してください。

CAPTCHAページを取得する場合はどうすればよいですか?

CAPTCHA インジケーターのレスポンス HTML をチェック: "captcha", "recaptcha", "hcaptcha", "challenge", "verify you are Human". また、予期しない 403 応答を監視し、チャレンジ URL にリダイレクトします。 スクレイピングパイプラインに自動検出を構築します。

なぜ私はまだ住宅のプロキシでCAPTCHAsを取得するのですか?

通常はパターン要求のため、IPの質ではなく。 一般的な原因: 1分あたりのあまりにも多くの要求, ブラウザのヘッダーを欠落, クッキーの処理の問題, またはあまりにも体系的であるパターンをスクレイピング. スローダウンし、ジッタを追加し、関連リクエストのスティッキーセッションを使用します。

始める準備はできましたか?

AIフィルタリングで148か国以上、5,000万以上のレジデンシャルIPにアクセス。

料金を見るレジデンシャルプロキシ
← ブログに戻る