プロキシを変更し、新しいIPアドレスプールを購入しても、パーサーが依然としてエラー429 Too Many Requestsで落ちることがありますか?これは典型的な状況です。ブロックの70%はIPアドレスではなく、リクエスト自体の見た目に関連しています。プロキシを変更した後でもサイトがあなたをブロックし続ける6つの実際の理由と、それぞれのケースで何をすべきかを解説します。
エラー429の意味とプロキシが万能ではない理由
HTTPステータスコード429 Too Many Requestsは、形式的には「リクエストの制限を超えました」という意味です。しかし、実際には、特にWildberries、Ozon、Avito、Yandex.Marketなどのサイトは、このコードを「あなたはボットだと考えています」という普遍的な信号として使用します。理由はリクエストの頻度にあるかもしれませんが、同じくらいの確率で、ヘッダー、ブラウザのフィンガープリント、クッキーセッションの欠如、またはIPではなくアカウントに関連付けられた制限にあるかもしれません。
そのため、プロキシを変更しても効果がないことがよくあります。システムがIPではなくリクエストパターン(フィンガープリント、ヘッダー、クリック速度)をブロックしている場合、新しいIPアドレスからも数分後に同じ429が返されます。それぞれの理由を詳しく解説し、新しいプロキシプールを購入せずにどのように確認し、解決するかを示します。
重要: プロキシは必要なツールであり続けますが、システムの一部として、唯一の解決策としてではありません。レジデンシャルおよびモバイルIPは、IPの評判によるブラックリストに載る可能性を減少させますが、行動やヘッダーによるブロックからは救われません。
理由1: リクエストの頻度が高すぎる
最も明白ですが、最も頻繁に誤診される理由です。多くの人は「リクエストごとにプロキシを変更しているので、頻度は重要ではない」と考えています。これは誤りです。現代のアンチボットシステム(たとえば、WildberriesやOzonではCloudflareレベルのソリューションや独自のWAFが使用されています)は、単一のIPからの頻度だけでなく、特定のAPIエンドポイントや商品ページへの全体的な負荷を、すべてのソースからの行動信号とともに分析します。
あなたのパーサーが同じカタログセクションに対して1秒間に50〜100リクエストを行う場合、システムは異常なトラフィックの急増を検出します。解決策はプロキシを変更することではなく、リクエスト間に人工的な遅延(スロットリング)を導入することです。固定間隔の代わりに1〜3秒のランダムな遅延を加え、429を受け取った場合は指数的バックオフ(各ブロック後に待機時間を2倍にする)を行います。
import time, random
def safe_request(session, url):
for attempt in range(5):
response = session.get(url)
if response.status_code == 429:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
continue
return response
return None
既製のパーサーを使用している場合(たとえば、価格監視のクラウドサービス)、リクエスト間の間隔設定を確認してください。ほとんどのツールには「スキャン速度」のスライダーがあります。速度を30〜40%減少させることで、プロキシを変更せずに429を完全に解消することがよくあります。
理由2: 不正確または欠落しているヘッダー
多くのパーサーは、最小限のヘッダーセットでリクエストを送信したり、デフォルトのUser-Agentライブラリ(たとえば、「python-requests/2.28.1」)を使用したりします。このようなヘッダーはボットを即座に示します。実際のブラウザは、Accept、Accept-Language、Accept-Encoding、Sec-Fetch-*、Refererなど、厳密に定義された順序で数十のヘッダーを送信します。
WildberriesやOzonは、ヘッダーセットを実際のChromeやSafariの「フィンガープリント」と照合します。ヘッダーが少なすぎる、順序が正しくない、またはUser-Agentが他のパラメータと一致しない場合(たとえば、Windows上のChromeと宣言されているが、TLSフィンガープリントがPythonに似ている場合)、リクエストはIPに関係なく429でブロックされます。
| ヘッダー | 一般的なエラー | 解決策 |
|---|---|---|
| User-Agent | 古いバージョンまたは明らかにライブラリの文字列 | 実際のChrome/Safariの最新UA、プールからのローテーション |
| Accept-Language | 欠落しているか、IPのジオロケーションと一致しない | ロシアのマーケットプレイス向けにru-RU |
| Referer | 空であるが、実際の遷移は常にRefererを持つ | カタログの前のページを指定する |
| Sec-Fetch-* | 完全に欠落している(ブラウザクライアントではない) | 実際のブラウザのDevToolsから完全なセットをコピーする |
最も簡単な方法は、実際のブラウザのDevToolsのNetworkタブから完全なヘッダーセットをコピーし、手動で必要なページを開いて、そのセットをパーサーで使用することです。ライブラリがそれを許可する場合、ヘッダーの順序を考慮してください(たとえば、curl_cffiやhttpxで明示的な順序を使用)。
理由3: セッションとクッキーのローテーションがない
よく見落とされるエラー: パーサーは各リクエストごとにIPを変更しますが、同じクッキーセッションを使用するか、クッキーを全く保存しません。実際のユーザーは、最初の訪問時にクッキーのセット(セッショントークン、デバイスID、Cloudflareの__cf_bmやOzon/WBの類似のアンチボット保護ラベル)を取得し、その後のリクエストでそれらを使用します。
クッキーを「ウォームアップ」ページで取得せずにリクエストを送信すると、アンチボットシステムは「ゼロ」セッションを検出します。これは特にAPIエンドポイントに直接アクセスする場合に疑わしく見えます。解決策は完全なシナリオをエミュレートすることです。最初にメインページまたはカテゴリページをロードし、クッキーを取得し、1〜2秒待ってから、必要なAPIまたは商品カードにアクセスし、リクエストのチェーン全体で同じセッションのクッキーを保持します。
import requests
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"Accept-Language": "ru-RU,ru;q=0.9"
})
# セッションのウォームアップ
session.get("https://www.wildberries.ru/catalog/0/search.aspx")
time.sleep(1.5)
# クッキーを使ったメインリクエスト
response = session.get(target_url)
Dolphin AntyやAdsPowerのようなアンチデテクトブラウザを使用して商品カードを手動で監視する場合、または組み込みの自動化を使用する場合、プロファイルがセッション間でクッキーを保存し、毎回「クリーンな状態」から始まらないことを確認してください。これもシステムの疑念を引き起こします。
理由4: ボットのような振る舞い
完璧なヘッダーとクッキーがあっても、パーサーは行動パターンによって自らを示すことがあります。商品へのアクセスが厳密に線形の順序(IDの昇順)、リクエスト間の間隔がミリ秒単位で同じ、通常のブラウザが自動的に読み込む静的リソース(画像、CSS、JS)への「ゴミ」リクエストがないなどです。
WildberriesやOzonの高度な保護システムは、HTTPリクエストだけでなく、ページ上でJavaScriptが実行されたかどうか(ヘッドレス検出を通じて)、マウスが動いたか、スクロールがあったかを分析します。あなたがJSをレンダリングせずにクリーンなHTTPリクエストを行っている場合、サイトがトークンを取得するためにスクリプトの実行を期待しているとき(たとえば、アンチボットJavaScriptチャレンジ)、そのスクリプトを実行しないリクエストは自動的に429または403を受け取ります。
解決策はスケールに依存します。小規模なボリュームには、マウスの動きやランダムな遅延をエミュレートするヘッドレスブラウザ(Playwright、Puppeteer)の使用が適しています。産業用パースには、商品の巡回順序のランダム化、二次リソースへのリクエストの「ノイズ」追加、固定ステップではなく正規分布に基づく時間間隔の変動が必要です。
理由5: TLS/JA3フィンガープリントとHTTP/2
これは最も「目立たない」技術的な理由であり、深い技術的な準備なしにパースを行っている90%の人々が知らないことです。各TLSクライアント(requestsライブラリ、curl、urllib)は、HTTPS接続を確立する際にユニークなフィンガープリントを残します。これは、サポートされている暗号、プロトコルのバージョン、TLS拡張のセットです。このフィンガープリントはJA3/JA4フィンガープリントと呼ばれます。
Cloudflare、Akamai、そして大手マーケットプレイスの独自のアンチボットシステムは、JA3フィンガープリントを既知のボットやライブラリのデータベースと照合します。標準のPython requestsやNode.jsのhttpsモジュールは、実際のChromeとは完全に異なる容易に検出可能なフィンガープリントを持っています。完璧なヘッダーとクッキーがあっても、リクエストはTLSハンドシェイクの段階でブロックされ、サーバーがHTTPヘッダーを見る前に接続が切断されます。
さらに、多くのマーケットプレイスは特定のパラメータ(SETTINGSフレームの順序、ストリームの優先順位)を持つHTTP/2を要求します。HTTP/1.1ベースのライブラリは自動的にこの背景で目立ちます。解決策は、実際のブラウザのフィンガープリントをエミュレートするライブラリを使用することです。curl_cffi(ChromeのTLSフィンガープリントをエミュレート)、tls-client、またはChromiumベースの完全なヘッドレスブラウザを使用すると、「本物の」フィンガープリントを得ることができます。
pip install curl_cffi
例: curl_cffi.requests.get(url, impersonate="chrome120") — ライブラリは自動的に実際のChrome 120に一致するTLSフィンガープリントを挿入します。
理由6: アカウントまたはAPIキーの制限
公式または準公式のマーケットプレイスAPI(たとえば、Wildberriesの販売者APIやOzon Seller API)を通じて作業している場合、429はIPではなく、販売者アカウントやAPIトークン自体に関連付けられている可能性があります。この場合、プロキシを変更しても無意味です。制限はサーバー側でアカウントIDに関連付けられて保存され、アカウントからの任意のIPは同じ制限を受けます。
この状況は、競合の価格を個人アカウントを通じて監視し、在庫をエクスポートするためにAPIを呼び出すセラーに典型的です。両方のリクエストの流れはアカウントの全体的な制限に合算されます。解決策は、時間に応じて負荷を分散し、APIの公式クォータをより経済的に使用すること(毎分変わらないデータをキャッシュする)です。また、競合の価格を純粋に監視するために、販売者アカウントに関連付けられていない別の非認証リクエストの流れを使用します。
確認は簡単です: 新しいクリーンIPからのリクエストでも429が続く場合、前のセッションからのクッキーが一切ない状態で、隣のタブで個人アカウントにログインしている場合 — おそらく制限はアカウントに関連しています。
実際の理由を診断する方法
インフラストラクチャを変更する前に、次のアルゴリズムに従って診断を行ってください。まず、通常のブラウザで手動でページを開き、ライブの振る舞いで429が発生しないことを確認します。これにより、問題がパーサー側にあることが確認され、地域のグローバルブロックではないことが確認されます。
次に、DevToolsを介して実際のブラウザのヘッダーとパーサーのヘッダーを比較します(Networkタブ → Copy as cURL)。差が最小限であれば、tls.peet.wsのようなサービスを介してTLSフィンガープリントを確認します。あなたのライブラリでリクエストを送信し、JA3ハッシュを基準のブラウザと比較します。リクエストがTLSハンドシェイクの段階で失敗する場合(HTTPレスポンスを受け取る前に接続が切れる) — 原因はフィンガープリントにあり、頻度やヘッダーではありません。
次に、制限がIPに関連しているのかアカウントに関連しているのかを確認します: 認証なしで新しいクリーンIPからリクエストを行います。429が消えた場合 — 問題は以前のIPの評判またはそのアドレスからの頻度にあります。429が残った場合 — ヘッダー、TLS、または行動に原因を探し、プロキシではありません。
プロキシを変更せずに429を解決するためのチェックリスト
- リクエスト間に1〜4秒のランダムな遅延を追加します。
- Sec-Fetch-*やAccept-Languageを含む実際のブラウザの完全なヘッダーセットをコピーします。
- メインページのウォームアップから始めて、同じセッション内でクッキーを保存し、渡します。
- ライブラリのTLSフィンガープリントを確認します — curl_cffiやヘッドレスブラウザを使用し、クリーンなHTTPクライアントの代わりにします。
- ページの巡回順序をランダム化し、静的リソースへの「ノイズ」リクエストを追加します。
- APIアカウントの負荷と匿名の価格監視を異なるストリームに分けます。
- 429を受け取った場合は指数的バックオフを導入し、即座にリクエストを再試行しないようにします。
- 上記のすべての項目を確認した後にのみ — プロキシを変更するか、IPプールを拡張します。
プロキシが必要な場合と選択方法
すべての6つの理由を解消した後、プロキシはインフラストラクチャの重要な要素として残りますが、もはや唯一のブロック回避手段ではなく、スケーリングの手段として機能します。あなたのタスクが、異なる「仮想ユーザー」からWildberriesやOzonの数千のカードを並行して監視することであれば、良好な評判を持つIPプールが必要です。これにより、1つのアドレスにブロック履歴が蓄積されることを避けることができます。
大量の価格監視やマーケットプレイスのカタログ監視には、レジデンシャルプロキシが最適です。これらは実際の家庭プロバイダーのIPを使用しているため、アンチボットシステムはリクエストを通常の購入者のトラフィックとして認識します。これは重要です。なぜなら、WildberriesやOzonはすでにデータセンターのIP範囲をブラックリストに登録しているからです。
サイトのモバイル版のチェック、マーケットプレイスアプリを通じた作業、または地理的に都市まで正確なTikTok AdsやFacebook Adsの広告テストに関連するタスクには、モバイルプロキシが適しています。これらは、実際の携帯通信事業者に属するIPを持っているため、ほとんどの保護システムで最大の信頼レベルを持っています。
それほど敏感でないタスク、たとえば、小規模なボリュームでの認証なしのオープンカタログのパースには、データセンタープロキシを使用できます。これらは大幅に安価で高速ですが、ヘッダーやTLSフィンガープリントの設定がより厳密に必要です。なぜなら、単独で疑念を引き起こすリスクが高いからです。
| プロキシの種類 | 429を解決する時 | 効果がない時 |
|---|---|---|
| レジデンシャル | IPがすでに評判でブラックリストに載っている | TLSフィンガープリントやヘッダーによるブロック |
| モバイル | 敏感なシナリオに対してIPの最大の信頼性が必要 | 制限がIPではなくアカウントに関連している |
| データセンター | 認証なしのオープンページの単純なパース | 評判の範囲をチェックする厳しいアンチボットシステム |
結論
パース時のエラー429は、単に「プロキシを変更する」ボタンを押すことで解決されることは稀です。ほとんどの場合、問題はリクエストの頻度、不完全なヘッダー、クッキーセッションの欠如、検出可能なTLSフィンガープリント、行動パターン、またはIPアドレスではなくアカウントに関連付けられた制限にあります。プロキシプールを拡張するために予算を使う前に、この記事の6つのポイントを診断してください。
技術的な部分が正しく設定されている場合 — ヘッダーが実際のブラウザに一致し、TLSフィンガープリントがライブラリを示さず、リクエストがユーザーの自然な振る舞いを模倣している場合 — プロキシは本当に効果的なスケーリングツールになります。WildberriesやOzonの価格監視を産業規模で行うには、レジデンシャルプロキシから始めることをお勧めします。これにより、コストとアンチボットシステムの信頼レベルの最良のバランスが得られます。