# Puppeteerプロキシ設定: フラグ、認証、ローテーションと現実

起動フラグは簡単ですが、その後の407で多くのPuppeteerプロキシ設定がつまずきます。ここに完全なパターンがあります — page.authenticate、コンテキストローテーション、proxy-chain — そしてページごとのプロキシとヘッドレス検出の真実です。

Puppeteerプロキシ設定は1つの起動フラグで始まり、多くの人にとっては次のステップで壁にぶつかります: プロキシが`407 Proxy Authentication Required`と応答するのは、`--proxy-server`が資格情報を運ぶ方法がないからです。解決策は組み込まれています — `page.authenticate()` — しかしその周りには半分しか機能しないアドバイスの地雷原があります: npmパッケージがあなたのトラフィックをNode.jsを通じて静かに再ルーティングし、Chromiumが認証しないSOCKSスキーム、そして動作するプロキシを死んでいるように見せるローカルホストバイパス。このガイドは、本番環境で持続する設定を紹介します: フラグ、認証、ブラウザコンテキストでのローテーション、厄介なケースに対するproxy-chain、そしてヘッドレス検出に関する正直なセクションです。

## Puppeteerプロキシ設定: 基本パターン

プロキシはChromiumの起動引数であり、ブラウザ全体に適用されます。資格情報は`page.authenticate()`を通じて送信され、DevToolsプロトコルを介してプロキシの407チャレンジに応答します — ナビゲーションの前に呼び出してください:

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: ['--proxy-server=http://residentialpremium.quantumproxies.io:8080'],
  });
  const page = await browser.newPage();
  await page.authenticate({ username: 'USER', password: 'PASS' });

  await page.goto('https://httpbin.org/ip', { waitUntil: 'domcontentloaded' });
  console.log(await page.evaluate(() => document.body.innerText)); // exit IP
  await browser.close();
})();
```

4つの詳細がデバッグの時間を節約します:

- **フラグをテンプレートリテラルまたは連結で構築し、単純な引用符を使用しないでください。** 古典的なStack Overflowのバグ: 変数を代入しない二重引用符の`"--proxy-server =..."` — そして余分なスペースが解析を壊します。
- **スキームを含めてください。** SOCKSの場合は`--proxy-server=socks5://host:port`、それ以外はChromiumがHTTPを想定します。
- **フラグに`user:pass@`を埋め込まないでください。** Chromiumは無視します; 認証は`page.authenticate()`（またはIPホワイトリスト）だけが行います。
- **ローカルホストはプロキシをバイパスします。** ChromiumはループバックURLのプロキシをスキップします — Puppeteerの問題#3711で文書化されたパズルです。ローカルトラフィックを本当にプロキシする必要がある場合は`--proxy-bypass-list=<-loopback>`を追加してください; それ以外の場合は外部URLでテストするだけです。

![4ステップのPuppeteerプロキシ認証フロー：--proxy-serverフラグでアドレスを設定し、page.authenticate()がDevToolsプロトコルで認証情報を登録し、ゲートウェイが407チャレンジを送り、Chromiumがダイアログなしで応答するため、ページは住宅用出口IPから読み込まれる。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335144/blog/generated/qp-b9-005-diag1.png)
*page.authenticateはDevToolsプロトコルで資格情報を登録します; ゲートウェイが407を送信すると、Chromiumはダイアログを表示せずに応答します。*

## ブラウザコンテキストでのプロキシのローテーション

IPごとにChromeを再起動するのは毎回数秒と数百MBを要します。ブラウザコンテキストがそれを解決します: Puppeteer v22以降、APIは`browser.createBrowserContext()`（古いインコグニートバリアントを置き換える）で、`proxyServer`オプションを受け入れ、独自のクッキーとストレージを持つコンテキストがミリ秒で作成されます:

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const jobs = ['https://example.com/a', 'https://example.com/b'];

  for (const url of jobs) {
    const context = await browser.createBrowserContext({
      proxyServer: 'http://residentialpremium.quantumproxies.io:8080',
    });
    const page = await context.newPage();
    await page.authenticate({ username: 'USER', password: 'PASS' });
    try {
      await page.goto(url, { timeout: 30000 });
      // ...extract...
    } finally {
      await context.close();
    }
  }
  await browser.close();
})();
```

ローテーションゲートウェイに対して、各コンテキストは自然にプール内の異なるアドレスから出力されます — [ローテーション住宅プロキシ](https://quantumproxies.io/rotating-proxies)では、1つのホスト名の背後に90M以上のIPが200以上の国にわたってあり、マルチページフローが継続性を必要とする場合、スティッキーセッションのユーザー名パラメータが出口を固定します。これは[Playwright](https://quantumproxies.io/blog/playwright-proxy-integration)にお勧めするジョブごとのコンテキストアーキテクチャと同じです; Puppeteerは認証ステップを明示的に記述するだけです。

ローテーションを正直に保つための2つの習慣。開発中にコンテキストごとに出口IPを記録します — コンテキスト開始時にIPエコーエンドポイントをヒットし、スクレイピングした行と一緒に保存します。ターゲットがソフトブロックを開始したとき、どの出口またはどのフィンガープリントが原因かを判断できます。そして、同時実行性を制限します: 各コンテキストは安価ですが、開いているページはレンダラーメモリを保持するため、コンテキスト作成の周りにセマフォを置くことは、ジョブリストが数千のURLに成長したときに無制限ループを打ち負かします。

## proxy-chain: 厄介な認証のためのローカルブリッジ

2つのケースがフラグプラス認証パターンを壊します: 認証されたSOCKS5（ChromiumはSOCKS資格情報サポートを全く持っていません）と、認証ステップなしでプロキシURLのみを受け入れるツール。`proxy-chain` npmパッケージは、認証された上流に転送する資格情報なしのローカルプロキシを開始することで両方を解決します:

```js
const puppeteer = require('puppeteer');
const proxyChain = require('proxy-chain');

(async () => {
  const upstream = 'http://USER:PASS@residentialpremium.quantumproxies.io:8080';
  const localUrl = await proxyChain.anonymizeProxy(upstream);
  // localUrl is something like http://127.0.0.1:54321 — no credentials needed

  const browser = await puppeteer.launch({
    args: ['--proxy-server=' + localUrl],
  });
  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');

  await browser.close();
  await proxyChain.closeAnonymizedProxy(localUrl, true);
})();
```

重要なのは、ページのリクエストがChrome自体から出ることです — proxy-chainはバイトを中継するだけなので、TLSフィンガープリントは本物のブラウザのままです。その区別が次のセクションです。

## ページごとのプロキシ: 正直な答え

Puppeteerにはネイティブなページごとのプロキシがなく、人気のある回避策 — `puppeteer-page-proxy`、`puppeteer-proxy` — はすべてのリクエストをインターセプトし、HTTPライブラリでNode.jsから再発行し、その応答をブラウザにフィードします。3つの結果: ターゲットは今やNodeのTLSハンドシェイクをChromeの代わりに見ることになり、[JA3/JA4フィンガープリント](https://quantumproxies.io/blog/tls-ja3-fingerprinting-scraping)が保護されたサイトで即座にフラグを立てます; 各リクエストはNodeを通じて往復します; そして両方のパッケージは事実上メンテナンスされておらず、インストールが自分の問題トラッカーによって箱から壊れています。異なるページに異なるIPが必要な場合は、上記のように1プロキシごとに1コンテキストを使用してください — 同じ効果、実際のChromeトラフィック、サポートされたAPI。

![Puppeteerでプロキシをローテーションする3つの方法が1つのターゲットに向かう図：IPごとにChromeを再起動すると数秒と数百MBがかかり、プロキシごとのブラウザコンテキストは本物のChromeのトラフィックのまま数ミリ秒で作成でき、Nodeのリルートパッケージはフィンガープリント検知ですぐにフラグが立つNodeのTLSハンドシェイクに置き換えてしまう。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335144/blog/generated/qp-b9-005-diag2.png)
*コンテキストは本物のChromeトラフィックでローテーションを提供します。Node再ルートパッケージはTLSフィンガープリントをボットのものに交換します — プロキシの目的とは逆です。*

## ヘッドレス検出の現実

プロキシはネットワーク層を修正しますが、ヘッドレスChromeを見えなくすることはできません。古いヘッドレスモードはHeadlessChrome User-Agentトークンで自らを発表しました; 新しいヘッドレス（Puppeteerのデフォルトはv22以降）は実際のブラウザのアーキテクチャを共有し、そのギャップを大きく閉じますが、検出器は依然として`navigator.webdriver`、CDPの副作用、レンダリングの癖を探ります — ステルスプラグインは昨日のチェックをパッチしますが、明日のチェックはパッチしません。労力に対するリターンで修正を順序付けてください: 最初にクリーンな[住宅IP](https://quantumproxies.io/residential-proxies)を使用してください、なぜなら評判はサイトが実行する最も安価なフィルターであり、あなたのコードが偽装できないものだからです; 次に適切なヘッダーとペーシング（[CAPTCHAを回避する](https://quantumproxies.io/blog/avoid-captcha-while-scraping)ためのトリガー信号をカバーするガイドがあります）; そして、強化されたターゲットがまだ勝つ場合、そのドメインをレンダリング、フィンガープリント、リトライを処理し、クリーンなHTML、markdownまたはJSONを返す[Scraper API](https://quantumproxies.io/scraper-api)を通じてルートします — パッチされたブラウザの艦隊の代わりに1つのHTTPコールです。

## よくある質問

### Puppeteerでプロキシをどのように認証しますか？

起動時に`args: ['--proxy-server=http://host:port']`でアドレスを設定し、ナビゲーションの前に各ページで`await page.authenticate({ username, password })`を呼び出します。フラグURLに埋め込まれた資格情報はChromiumによって無視されます。認証付きのSOCKS5の場合、ChromiumはSOCKS資格情報を送信できないため、代わりにproxy-chainを通じてブリッジします。

### Puppeteerはページごとに異なるプロキシを使用できますか？

ネイティブにはできません — 起動フラグはブラウザ全体に適用されます。サポートされている同等の方法は、`browser.createBrowserContext({ proxyServer })`を使用して1プロキシごとに1ブラウザコンテキストを作成し、各コンテキスト内にページを配置することです。ページごとのプロキシを約束するパッケージは、リクエストをNode.jsを通じて再ルートし、TLSフィンガープリントを変更し、厳しいアンチボットシステムによってフラグを立てられます。

### PuppeteerはSOCKS5プロキシをサポートしていますか？

認証されていないエンドポイントの場合ははい: `--proxy-server=socks5://host:port`を渡します。認証されたSOCKS5は失敗します、なぜならChromiumはSOCKS資格情報メカニズムを持っておらず、`page.authenticate()`はHTTP 407チャレンジにのみ応答するからです。回避策: ゲートウェイのHTTPポートを認証付きで使用する、IPをホワイトリストに登録する、またはローカルブリッジとしてproxy-chainを実行する。

### Puppeteerでプロキシをどのようにローテーションしますか？

ジョブごとに新しいブラウザコンテキストを`createBrowserContext({ proxyServer })`で作成し、ローテーションゲートウェイを指します — その後、各コンテキストは自動的に新しいIPから出力され、管理するプロキシリストは不要です。IPごとにブラウザ全体を再起動することも可能ですが、各ローテーションで数秒と数百MBのRAMを要します。

### なぜ私のPuppeteerプロキシはローカルホストで動作しないのですか？

Chromiumは設計上ループバックアドレスのプロキシをバイパスするため、ローカルホストや127.0.0.1へのリクエストは直接行われます — これは多くの人を驚かせ、番号付きのPuppeteer問題になりました。プロキシを強制するには`--proxy-bypass-list=<-loopback>`を追加するか、単に外部IPエコーエンドポイントでプロキシを検証してください。

耐久性のあるパターンは小さいです: アドレス用のフラグ、資格情報用の`page.authenticate()`、ローテーション用のコンテキスト、コーナーケース用のproxy-chain — そしてブラウザ外でリクエストを移動するパッケージに対する懐疑心。このスタックにクリーンな住宅用出口を与えれば、Puppeteerは退屈になりますが、それはインフラストラクチャが得られる最高の賛辞です。

[住宅プロキシでPuppeteerを実行する](https://quantumproxies.io/residential-proxies)
