Socks5Proxy

Playwrightプロキシ設定、ブラウザとコンテキストごとに異なるIPを接続する方法

このガイドではPlaywrightのproxyオプションにSocks5ProxyのHTTPプロキシとSOCKS5プロキシをserver、username、passwordで接続する方法と、1つのブラウザでコンテキストごとに異なるIPを使用する方法をNode.jsとPythonコードで説明します。

Playwrightのプロキシ設定は何が便利ですか?

Playwrightはプロキシアドレスとユーザー名、パスワードを一つのproxyオプションで受け取るので、認証ウィンドウの処理を別途行う必要がありません。Chromium、Firefox、WebKitの三つのブラウザすべてで同じオプションを使用します。

また、ブラウザを1つだけ起動し、その中に複数のコンテキストを作成する際、コンテキストごとに異なるプロキシを割り当てられます。コンテキストはクッキーとストレージが分離された別プロファイルのため、1つのブラウザで複数IPと複数セッションを同時に扱え、メモリを節約できます。

例ではIP 198.51.100.23、HTTPポート8000、SOCKS5ポート1080、ユーザー名spx_user、パスワードspx_passを使用します。

npm install playwright
npx playwright install chromium

ブラウザ全体にHTTPプロキシを接続するにはどうすればいいですか?

launchのproxyオプションにserver、username、passwordを入れると、そのブラウザのすべてのページが同じプロキシを使用します。HTTPSサイトはCONNECTトンネルで暗号化されて転送されます。

import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "http://198.51.100.23:8000", username: "spx_user", password: "spx_pass" },
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.textContent("body")); // proxy IP
await browser.close();

コンテキストごとに異なるIPを使うにはどうする?

newContextにproxyオプションを入れると、そのコンテキストのみそのプロキシを使用します。以下のコードはAPIでリストを取得し、3つのコンテキストを異なるIPで作成し、各コンテキストで表示されるIPを出力します。複数のアカウントを同時に扱う作業では、1つのコンテキストに1つのアカウントと1つのIPをペアリングすると便利です。

Chromiumの一部のバージョンとWindows環境では、コンテキストごとのプロキシを使用するためにlaunchにもproxyオプションが必要な場合がありました。その場合はlaunchに最初のプロキシを設定し、コンテキストごとに上書きします。

import { chromium } from "playwright";

const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies/download?format=ip:port:user:pass&protocol=http", {
  headers: { Authorization: "Bearer " + KEY },
});
const lines = (await res.text()).trim().split("\n").slice(0, 3);

const browser = await chromium.launch();
for (const line of lines) {
  const [ip, port, user, pass] = line.trim().split(":");
  const context = await browser.newContext({
    proxy: { server: "http://" + ip + ":" + port, username: user, password: pass },
    locale: "en-US",
  });
  const page = await context.newPage();
  await page.goto("https://api.ipify.org");
  console.log(ip, await page.textContent("body"));
  await context.close();
}
await browser.close();

SOCKS5プロキシはどのように使用しますか?

serverにsocks5://アドレスを入れます。ChromiumはSOCKS5プロキシのユーザー名・パスワード認証をサポートしていないため、SOCKS5はIP認証で接続することをお勧めします。ダッシュボードに実行サーバーのIPv4を登録し、username、passwordなしでserverのみを入れてください。

ユーザー名とパスワードで接続する必要がある場合は同じIPのHTTPポートを使用します。対象サイトから見えるIPと位置は同じです。

import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "socks5://198.51.100.23:1080" }, // server IP is authorized in the dashboard
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.textContent("body"));
await browser.close();

Pythonではどのように使用しますか?

Python用Playwrightも同じ構造です。proxy辞書にserver, username, passwordを設定します。同期方式の例を以下に示します。非同期方式もオプション名は同じです。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://198.51.100.23:8000",
        "username": "spx_user",
        "password": "spx_pass",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.text_content("body"))
    browser.close()

結果をその国のユーザーのように見せるには何を合わせればよいですか?

IP国に合わせてコンテキストのlocaleとtimezoneIdを一緒に設定すると、ページがその国のユーザーに見える言語と時間で描画されます。例えばドイツIPの場合、locale de-DE、timezoneId Europe/Berlinを使用します。

画像と動画が不要な場合、page.routeで該当リクエストをブロックすると帯域幅と時間を節約できます。共有プランは月間帯域幅が決まっているため特に有効です。

  • localeとtimezoneIdをIPの国に合わせる
  • 1コンテキストに1アカウント、1IP
  • 不要な画像・動画リクエストはpage.routeでブロック
  • SOCKS5はIP認証、ユーザー名・パスワードはHTTPポート

リストを自動取得し、作業ごとに分割して使うにはどうすればいいですか?

APIのGET /proxiesはJSONで行ごとにIP、ポート、国を返します。国条件を指定して受け取ると、国ごとの作業に適したリストをすぐに作成できます。以下のコードは米国プロキシのみを受け取り、作業数分のコンテキストを作成する例です。レスポンスのフィールド名はAPIドキュメントで確認できます。

作業が多い場合は、コンテキストを最後まで開いたままにせず、作業が終わるたびに閉じてメモリを解放してください。

import { chromium } from "playwright";

const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies?country=us&protocol=http", {
  headers: { Authorization: "Bearer " + KEY },
});
const { proxies } = await res.json();

const browser = await chromium.launch();
for (const p of proxies.slice(0, 5)) {
  const context = await browser.newContext({
    proxy: { server: "http://" + p.host + ":" + p.http_port, username: p.username, password: p.password },
    locale: "en-US",
    timezoneId: "America/New_York",
  });
  const page = await context.newPage();
  await page.goto("https://api.ipify.org");
  console.log(await page.textContent("body"));
  await context.close();
}
await browser.close();

不要なリクエストをブロックして帯域幅を節約するにはどうすればいいですか?

page.routeやcontext.routeで画像、フォント、動画のリクエストをブロックすると、ページが速く開き、プロキシの帯域幅も節約できます。データのみ必要な収集作業で特に効果的です。

await context.route("**/*", (route) => {
  const type = route.request().resourceType();
  return ["image", "font", "media"].includes(type) ? route.abort() : route.continue();
});

FirefoxとWebKitでも同じプロキシを使いますか?

はい。Playwrightは3つのブラウザすべて同じproxyオプションを受け付けます。テストチームであれば、同じプロキシでChromium、Firefox、WebKitを順に起動し、国別画面がブラウザごとに同じか確認できます。

FirefoxはSOCKS5のユーザー名・パスワード認証がブラウザでサポートされていない点がChromiumと同じで、SOCKS5はIP認証で接続してください。HTTPポートは3つのブラウザすべてでユーザー名とパスワードで接続されます。

Playwright Testを使用する場合、playwright.configのuse項目にproxyを設定してすべてのテストに適用するか、プロジェクトを国別に分けてそれぞれ異なるプロキシを設定できます。

import { defineConfig } from "@playwright/test";

export default defineConfig({
  projects: [
    { name: "us", use: { locale: "en-US", proxy: { server: "http://198.51.100.23:8000", username: "spx_user", password: "spx_pass" } } },
    { name: "de", use: { locale: "de-DE", proxy: { server: "http://198.51.100.24:8000", username: "spx_user", password: "spx_pass" } } },
  ],
});

よくあるエラーはどう解決しますか?

net::ERR_PROXY_CONNECTION_FAILEDはserverのアドレスやポートが間違っている場合です。407または認証関連のエラーはusernameとpasswordの値を確認してください。Browser does not support socks5 proxy authenticationエラーはSOCKS5にユーザー名とパスワードを入れたときに発生します。IP認証に変更するか、HTTPポートを使用してください。

Playwrightプロキシ設定、ブラウザ・コンテキスト別IP | Socks5Proxy