すべての記事

Unblockerフラグの内部: `unblocker: true`の実際の動作

1つのフラグで3つの機能(実際のブラウザのheader、一致する接続シグネチャ、gzipとbrotliの自動展開)が有効になります。その機能と理由を説明します。

ほとんどのスクレイパーは、1つのheaderが読み取られる前に失敗します。

サーバーは、クライアントがネットワーク上に送信する接続レベルのシグネチャを確認し、それがブラウザであるか、ブラウザを装ったクライアントライブラリであるかを判断します。Pythonのrequests、Goのnet/http、通常のcURLはすべて、接続開始時に特有のフィンガープリントを渡します。対策を行っているサイト(Datadome、Akamai、Imperva、Cloudflareのマネージドサービス)は、User-Agent文字列が意味を持つ前に接続を切断するか、チャレンジページを返します。

これがFourAでunblocker: trueが解決する問題です。先月、この機能を確実に動作させるための要素を特定しました。

新機能

unblocker: trueは、すべての/api/single呼び出しに対する単一のフラグです。これを有効にすると、3つの処理(ブラウザのheaderセットの挿入、実際のブラウザがネットワーク上に送信するものと一致するトランスポートを経由したrequestの送信、サーバーが返すデータ(gzip、brotli、deflate)の展開)が実行されます。最初の2つはベータ版から利用可能でした。3つ目(brotliの自動展開)は3月25日にリリースされ、headerとトランスポートの同期を保つためのバージョンの固定化は翌日に反映されました。

仕組み

requestは次のようになります。

curl -X POST "https://api.foura.ai/api/single" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "url": "https://example.com/products",
    "method": "GET",
    "unblocker": true
  }'

内部では3つのレイヤーが動作しています。

Headerの挿入。 すべてのブラウザのheaderバンドル(User-Agent、Sec-Ch-Ua、Sec-Ch-Ua-Platform、Sec-Fetch-Site、Sec-Fetch-Mode、Sec-Fetch-Dest、Accept、Accept-Language、Accept-Encoding)を設定します。順序が重要です。実際のブラウザはこれらを特定の順序で送信し、検出ライブラリはそれをチェックします。

接続シグネチャ。 当社のトランスポートは、最新のブラウザセッションのバイトレベルの形状と一致します。つまり、同じ拡張機能の順序、同じ暗号化設定、同じハンドシェイクの特性を持ちます。標準のcURL、Pythonのrequests、Goのnet/httpは、保護されたインフラストラクチャ上で数ミリ秒以内に機械的にフラグ付けされるシグネチャを生成します。

自動展開。 unblockerが有効な場合、Accept-Encodingをgzip, deflate, brに設定し、トランスポートが本文を展開します。デコードされた文字列(またはreturnBuffer: trueを渡した場合はBuffer)が返されます。手動でのbrotli処理は不要であり、サイトがgzipではなくdeflateを選択した場合でも、headerと本文の不一致は発生しません。

バージョンの固定化が重要な理由

接続シグネチャはバージョンに依存します。今月のブラウザのネットワークレベルの詳細は先月のものとは異なり、詳細にフィンガープリントを行うサイトはその差異に気付きます。header、navigatorオブジェクト、接続シグネチャがすべて同じブラウザバージョンを報告するように、関連するコンポーネントを固定しています。

面倒に聞こえるかもしれませんが、実際に面倒です。3月のモノレポ移行時に、1つのコンポーネントが自動更新され、残りが同期されなくなったため、不一致による問題が発生しました。修正は2つのコミットで行われました。変更されるコンポーネントを固定し、パッケージマネージャーが整合性を保つことを決して信頼しないことです。

影響

厳密にフィンガープリントを行うターゲット(金融、旅行、保護されたeコマース)に対する内部テストでは、unblocker: falseunblocker: trueの違いは、チャレンジページと200の違いになります。通常のcURLでマネージドCloudflareにアクセスすると、初回で403になります。同じURLでもunblocker: trueを使用すると、接続がネットワークレベルでブラウザセッションのように見えるため、通過できます。

ただし、フィンガープリントを行わないサイト(ほとんどのパブリックAPI、古いCMSテンプレート、IPのrate limitのみで制限されているもの)の場合は、unblockerを無効にしたままで問題なく、ネゴシエーションの数ミリ秒を節約できます。必要な場所で使用してください。

パワーユーザー向け

知っておくべきいくつかのパターンがあります。

ターゲットがIPレピュテーションもチェックする場合は、unblockerとレジデンシャルproxyを組み合わせてください。データセンターIPと完璧な接続シグネチャの組み合わせでも、サイトがブラックリストに登録しているASNではフラグが付けられます。当社のproxyのendpoint(/api/proxy)はターゲットドメインごとにローテーションされるため、通常はrequestに"proxy": "residential"を追加するだけで十分です。

ブラウザを気にしないJSON APIを呼び出す場合は、unblockerをスキップしてください。追加のheaderは、プログラムによるクライアントを想定しているAPI(たとえば、独自のマイクロサービスを呼び出すバックエンド)には怪しく見える可能性があります。

サイトがJavaScriptのアンチボット(Turnstileのインタラクティブなチャレンジ、最も厳格な設定のPerimeterX、ヒューリスティックを強化したAkamai Bot Managerなど)を実行している場合、unblockerだけでは不十分です。フルブラウザでチャレンジを実行するブラウザのendpointが必要です。これは異なるクレジット価格設定の異なる製品であり、詳細についてはブラウザタスク: JavaScriptを多用するサイトをスクレイピングする方法に記載しています。

また、unblockervalidateブロックと組み合わせて、技術的には200を返すがチャレンジページが含まれるresponseを拒否することができます。

{
  "url": "https://example.com/products",
  "method": "GET",
  "unblocker": true,
  "validate": {
    "data": { "fail": ["captcha", "Access Denied"] }
  }
}

これにより、サイレントなエラーが分類されたエラーに変わり、ダッシュボードでの成功率の追跡に重要になります。

今後の展開

ブラウザは4週間ごとに新しい安定版をリリースします。当社のスタックもそれに合わせて更新します。ユーザー側で変更する必要はありません。unblocker: trueは、エンドツーエンドで検証されたブラウザバージョンを常に指し示します。

さらに困難な作業が控えています。マネージドアンチボットではすでにHTTP/3フィンガープリントが確認されており、QUICトランスポートの適合は古いトランスポートよりも複雑であり、静的なheaderバンドルから真に動的なエミュレーションへの移行が始まっています。保護されたサイトはHTTP/2フレームの順序チェックに移行しており、「ブラウザのように見えるライブラリ」と「ブラウザ」の間のギャップは両端から縮小していくでしょう。リリース時に詳細をお伝えします。