Nodriverプロキシ認証:効果的な3つの修正方法
nodriverプロキシ認証のトップ結果はGitHubのディスカッションであり、ガイドではありません。nodriverにはネイティブなユーザー:パスサポートがありません。ここでは効果的な3つの修正方法と、多くの人が見逃しているワンラインショートカットを紹介します。
nodriverプロキシ認証を検索すると、トップ10の結果はGitHubのディスカッション、デモリポジトリ、別のライブラリに関するStack Overflowのスレッド、そしてRedditの投稿です。実際のガイドはありません。その理由は簡単です:nodriverは非同期CDPであり、undetected-chromedriverの後継です(このプロジェクトは12.8kのGitHubスターと1.3kのフォークがあります)。プロキシにuser:passを渡すネイティブな方法がありません。Chromeはコマンドラインフラグに埋め込まれた資格情報を無視し、nodriverはそれを補完しません。このガイドは、そのディスカッションスレッドがなるべきページです:何が効果的で、何が効果的でないか、そして認証されたプロキシを動作させる3つの修正方法です。
プレーンプロキシは動作しますが、認証プロキシは動作しません
未認証のプロキシはワンライナーです。アドレスをbrowser_argsに渡すと、すべてのリクエストがプロキシIPから出ます:
import nodriver as uc
async def main():
browser = await uc.start(
browser_args=["--proxy-server=gate.quantumproxies.io:PORT"],
)
page = await browser.get("https://httpbin.org/ip")
print(await page.get_content()) # shows the proxy exit IP
uc.loop().run_until_complete(main())
今、資格情報を追加します — --proxy-server=http://USER:PASS@host:port — すると壊れます。Chromiumはフラグ形式に資格情報スロットがないためUSER:PASS@セグメントを削除し、プロキシは407 Proxy Authentication Requiredで応答し、ChromeはDOM外に存在するネイティブログインダイアログを表示します。nodriverはそれを見たり埋めたりできません。その407は、407エラー修正ガイドでカバーされているのと同じ壁です:プロキシがあなたを拒否しているのであって、ブラウザではありません。したがって、すべての実際の修正は、別の方法でこのチャレンジに答える必要があります。
修正1:IPホワイトリスト化 — 資格情報なし、ダイアログなし
これはGitHubスレッドが決して言及しないショートカットであり、最も簡単な方法です。スクレイパーが安定したパブリックIPを持つマシンから実行される場合、そのIPをプロバイダーダッシュボードに登録し、資格情報を完全に削除します — ゲートウェイがソースアドレスで認証します。nodriverコードは上記のプレーンな--proxy-serverスニペットのままで、認証コードはまったくありません。すべてのQuantumProxiesプランは、ユーザー:パスと並んでIPホワイトリスト化をサポートしているので、出口IPが固定されている場合はこの方法が推奨されます。その唯一の制限はトポロジーです:それはスクリプトではなくマシンを認証するので、一時的なクラウドランナー、NATの背後にあるコンテナ、IPが変わるCIボックスには次の2つの修正が必要です。

修正2:CDP Fetchハンドラーでチャレンジに答える
nodriverはChrome DevTools Protocolを直接使用するので、プロセス内で認証チャレンジをインターセプトできます — 拡張ファイルは必要ありません。Fetchドメインをhandle_auth_requests=Trueで有効にし、各AuthRequiredイベントにcontinue_with_authで応答します。2つの詳細、どちらもディスカッション#1798の回答から、動作するかハングするかの違いです:
- ドメインを有効にする前にハンドラーを登録します。 nodriverの内部
enable呼び出しはあなたのハンドラー登録を上書きするので、後で追加するとイベントは全く発生しません — 人々が「何も起こらない」と報告する理由の第一位です。 - 応答を発火して忘れます。 ハンドラー内で応答を待つと、イベントループがブロックされ、ブラウザ全体がデッドロックします。各送信を
asyncio.create_taskでラップし、ブロックせずに実行されるようにします。
import asyncio
import nodriver as uc
PROXY = "gate.quantumproxies.io:PORT" # host:port for --proxy-server
USER, PASS = "USER", "PASS"
class Scraper:
def __init__(self):
uc.loop().run_until_complete(self.run())
async def run(self):
browser = await uc.start(browser_args=[f"--proxy-server={PROXY}"])
self.tab = await browser.get("draft:,") # blank tab first
# 1) handlers BEFORE enabling the Fetch domain
self.tab.add_handler(uc.cdp.fetch.RequestPaused, self.on_request)
self.tab.add_handler(uc.cdp.fetch.AuthRequired, self.on_auth)
# 2) only now turn on interception with auth handling
await self.tab.send(uc.cdp.fetch.enable(handle_auth_requests=True))
page = await browser.get("https://httpbin.org/ip")
await asyncio.sleep(3)
print(await page.get_content())
async def on_auth(self, event):
# fire-and-forget: awaiting here deadlocks the loop
asyncio.create_task(self.tab.send(uc.cdp.fetch.continue_with_auth(
request_id=event.request_id,
auth_challenge_response=uc.cdp.fetch.AuthChallengeResponse(
response="ProvideCredentials", username=USER, password=PASS,
),
)))
async def on_request(self, event):
asyncio.create_task(self.tab.send(
uc.cdp.fetch.continue_request(request_id=event.request_id)))
if __name__ == "__main__":
Scraper()
同じスレッドで浮上した1つの注意点:あるユーザーは、これがプレーンなHTTPページでは動作したがHTTPSでは失敗したことを発見しました。原因は低品質のプロキシであり、コードではありませんでした — より良い出口に切り替えることで解決しました。これはステルススクレイピングの繰り返しの教訓です:ハンドラーはチャレンジに答えますが、IPの評判がサイトがあなたを受け入れるかどうかを決定します。
修正3:生成されたChrome拡張機能
他のコミュニティパターンは、プロキシを設定し、chrome.webRequest.onAuthRequiredを通じて資格情報チャレンジに答える小さなChrome拡張機能を起動時に構築します — SeleniumやPuppeteerで動作するのと同じトリックです。小さなマニフェストとバックグラウンドワーカーを一時ディレクトリに書き込み、--load-extensionでロードします:
import nodriver as uc
async def main():
# ext_dir holds a Manifest V3 extension: manifest.json + worker.js that
# calls chrome.proxy.settings.set(...) and returns authCredentials from
# chrome.webRequest.onAuthRequired. Generate it once, then load it:
browser = await uc.start(browser_args=[
"--load-extension=" + ext_dir,
"--headless=new", # extensions only load in the NEW headless mode
])
page = await browser.get("https://httpbin.org/ip")
print(await page.get_content())
uc.loop().run_until_complete(main())
完全なマニフェストとワーカーは、Seleniumプロキシ認証ガイドのManifest V3ファイルと同一です — それらをそのままコピーし、起動呼び出しだけが変わります。2つの注意点がどこでも繰り返されます:拡張機能は--headless=newの下でのみロードされます(プレーンな--headlessは失敗します)、そして未パックのディレクトリはChromeバージョン間でパックされたzipよりも信頼性があります。拡張機能は任意のプロキシタイプを処理するため、CDPルートがあなたと戦っているときのフォールバックとなります。
第4のオプション:ローカルリレー
nodriverにまったく触れたくない場合、資格情報を保持し、127.0.0.1で認証なしのエンドポイントを提示する小さなローカルリレーを実行します。nodriverはループバックアドレスをプレーンフラグで指し、チャレンジを全く見ません。これはSOCKS5に最もクリーンなルートです。Chromiumは認証されたプロキシを完全に拒否します(Chromiumバグ40829748として追跡されています)。最小限のリレー、既製のツール、そしてそれが過剰である場合については、プロキシリレーガイドでカバーしています。
SOCKS5に関する注意
未認証のSOCKS5はフラグを通じて動作します — --proxy-server=socks5://host:port — しかし、認証されたSOCKS5は動作せず、CDPハンドラーは助けになりません。ChromiumはSOCKS5のユーザー名/パスワードサポートを一度も提供していません。実用的な答えは同じ3つです:IPをホワイトリスト化し、リレーを実行し、またはプロバイダーのHTTPエンドポイントを使用します。すべてのQuantumProxiesプランは、同じゲートウェイでHTTPとSOCKS5プロキシの両方を公開しているので、HTTPエンドポイントに切り替えることが最も速いSOCKS5修正となることがよくあります。アンチディテクトブラウザのファミリーとして、認証プロキシマップはnodriver、zendriver、その他を並べて比較しています。

よくある質問
nodriverは認証されたプロキシをサポートしていますか?
ネイティブにはサポートしていません。未認証のプロキシをbrowser_args=["--proxy-server=host:port"]で渡すことはできますが、Chromiumによってそのフラグ内のuser:passは削除されます。認証するには、プロバイダーでIPをホワイトリスト化するか、CDP Fetch.AuthRequiredハンドラーでチャレンジに答えるか、プロキシ認証Chrome拡張機能を生成するか、資格情報を保持するローカルリレーを実行します。
なぜ私のnodriver認証ハンドラーはイベントを受信しないのですか?
ほとんどの場合、ハンドラーを登録する前にFetchドメインを有効にしたためです。nodriverの内部enableは登録を上書きするので、イベントはコールバックに届きません。RequestPausedとAuthRequiredハンドラーを最初に追加し、次にfetch.enable(handle_auth_requests=True)を呼び出します。また、応答をasyncio.create_taskでラップし、待機がループをブロックしないようにします。
nodriverはユーザー名とパスワードでSOCKS5プロキシを使用できますか?
いいえ。Chromiumは認証されたSOCKS5をサポートしておらず(Chromiumバグ40829748)、nodriverはその制限を引き継いでいます。未認証のSOCKS5は--proxy-server=socks5://host:portで動作します。認証されたSOCKS5の場合、IPをホワイトリスト化するか、資格情報を追加するローカルリレーを実行するか、基本認証をクリーンに処理するプロバイダーのHTTPエンドポイントに切り替えます。
認証されたプロキシにはnodriverかzendriverか?
どちらも同じギャップと同じ修正方法を共有しています。zendriverはnodriverのコミュニティフォークです。zendriverは認証の問題が公然と議論されているより活発な問題トラッカーを持っていますが、動作する方法は同一です。フォークを使用している場合、フォーク固有のセットアップはここでのすべてを反映しています — CDPハンドラーとホワイトリスト化は同じように動作します。
正直な要約:nodriverはプロキシ認証を自動で行いませんが、地図を知っていれば問題ありません。IPが安定している場合はホワイトリスト化し、そうでない場合はCDPハンドラーまたは拡張機能を使用し、SOCKS5のためにリレーをバックポケットに入れておきます。上記のコードはチャレンジに答えますが、クリーンな住宅用出口が実際にドアを通過させます。