ブログに戻る

Playwrightでのヘッドレステストとスクレイピングのためのプロキシ設定:完全ガイド

Playwrightでヘッドレステストとスクレイピングのためにプロキシを正しく接続する方法を解説します。コード例、IPのローテーション、アンチボット対策の回避についても説明します。

📅2026年5月8日
```html

Playwrightは、ブラウザの自動化、ヘッドレステスト、データのパースのための最も強力なツールの一つです。しかし、正しく設定されたプロキシがなければ、スクリプトはすぐにIPで禁止されてしまいます。ウェブサイトは自動化されたリクエストを認識し、それをブロックすることを学びました。このガイドでは、Playwrightにおけるプロキシの接続方法を、基本的な設定からIPのローテーション、Cloudflareの回避まで解説します。

Playwrightにおけるプロキシの必要性とその使用時期

Playwrightは、バックグラウンドで実際のブラウザ(Chromium、Firefox、またはWebKit)を起動します。これがヘッドレスです。ウェブサイトから見ると、あなたは普通のユーザーのように見えますが、特定の瞬間を過ぎるとそうではなくなります。1つのIPから毎時数百のリクエストが発生すると、保護アルゴリズムは即座に反応します:CAPTCHA、一時的なブロック、完全な禁止。

プロキシが必須となる具体的なシナリオは以下の通りです:

  • マーケットプレイスのパース — Wildberries、Ozon、Avito、Yandex.Marketは、1つのIPから50〜100リクエストの後にスクリプトをブロックします。
  • 競合の価格監視 — 15分ごとにチェックを実行すると、IPを変更しない限り数時間以内に禁止されます。
  • ジオロケーションのテスト — ドイツ、アメリカ、カザフスタンのユーザーに対してサイトがどのように見えるかを確認する必要があります。
  • フォームの記入とアカウントの登録 — プラットフォームはアカウントをIPに結びつけ、大量登録をブロックします。
  • SEO監視 — GoogleやYandexからのポジション収集には、IPの継続的な変更が必要です。さもなければ、検索エンジンはCAPTCHAを表示します。
  • A/B機能のテスト — 一部の機能は特定の国や地域のユーザーにのみ利用可能です。

重要な点は、Playwright自体はあなたを匿名にするわけではないということです。プロキシなしでは、すべてのリクエストはあなたの実際のIPアドレスから行われます。プロキシを追加することは、すべての自動化スクリプトの安定した動作への第一歩であり、最も重要なステップです。

💡 知っておくべきこと

Playwrightは、ブラウザ全体、個別のコンテキスト(BrowserContext)、さらには個別のページレベルでプロキシをサポートしています。これにより、異なるページが同時に異なるIPを使用して動作する柔軟性が得られます。

ヘッドレス自動化のために選ぶべきプロキシの種類

すべてのプロキシがPlaywrightに適しているわけではありません。選択はタスクによって異なります:何をパースしているのか、ウェブサイトの保護がどれほど厳しいのか、どのくらいのリクエストを計画しているのかによります。

プロキシの種類 信頼度 速度 適している用途
データセンター 低い 非常に高い 厳しい保護がないパース、テスト
レジデンシャル 高い 中程度 Cloudflareを使用しているサイト、マーケットプレイス、ソーシャルメディア
モバイル 最大 中程度 Facebook、TikTok、Instagram、厳しいアンチボット
SOCKS5 ソースによる 高い 汎用プロトコル、Playwrightでサポートされています

ほとんどのパースタスクにおいて、最適な選択はローテーションを持つレジデンシャルプロキシです。これらは実際の家庭ユーザーのIPを持っているため、ウェブサイトはそれをデータセンターとして認識せず、自動的にブロックしません。攻撃的な保護を持つサイト(Cloudflare Bot Management、Akamai)には、モバイルプロキシを使用するのが最適です。これらのIPは携帯電話会社に属しており、最大の信頼を得ることができます。

Playwrightは、httphttps、およびsocks5プロトコルをサポートしています。重要な点は、SOCKS5は一部のバージョンでusername:passwordによる認証を直接サポートしていないことです。この点についてはエラーのセクションで詳しく説明します。

Playwrightにおけるプロキシの基本設定(JavaScriptとPython)

Playwrightでは、ブラウザを起動する際にproxyパラメータを使用してプロキシを指定できます。これは最も簡単な方法であり、ブラウザのすべてのリクエストが指定されたプロキシサーバーを経由します。

JavaScript / Node.js

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://proxy.example.com:8080'
    }
  });

  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  
  const content = await page.textContent('body');
  console.log(content); // プロキシサーバーのIPを表示

  await browser.close();
})();

Python

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": "http://proxy.example.com:8080"
        }
    )
    
    page = browser.new_page()
    page.goto("https://httpbin.org/ip")
    
    print(page.text_content("body"))  # プロキシのIPを表示
    
    browser.close()

SOCKS5の場合は、サーバーのアドレスのスキームを変更するだけです:

# Python — SOCKS5プロキシ
browser = p.chromium.launch(
    proxy={
        "server": "socks5://proxy.example.com:1080"
    }
)

プロキシが機能しているかどうかを迅速に確認するには、https://httpbin.org/ipまたはhttps://api.ipify.orgを開いてください。応答にはプロキシサーバーのIPが表示されるはずで、実際のIPではありません。

ユーザー名とパスワードによる認証付きプロキシ

ほとんどの商用プロキシプロバイダーは、ユーザー名とパスワードによる認証を使用します。これは標準的な慣行です。Playwrightは、プロキシオブジェクト内のusernameおよびpasswordフィールドを介してこれをサポートしています。

JavaScript

const browser = await chromium.launch({
  proxy: {
    server: 'http://gate.proxyprovider.com:7777',
    username: 'your_login',
    password: 'your_password'
  }
});

Python

browser = p.chromium.launch(
    proxy={
        "server": "http://gate.proxyprovider.com:7777",
        "username": "your_login",
        "password": "your_password"
    }
)

また、ユーザー名とパスワードをプロキシサーバーのURLに直接渡すこともできます。これは、動的に文字列を生成する場合に便利です:

# URLでの認証(Python)
proxy_url = f"http://{login}:{password}@gate.proxyprovider.com:7777"

browser = p.chromium.launch(
    proxy={"server": proxy_url}
)

⚠️ 注意

プロキシのユーザー名とパスワードをコードに直接保存しないでください!環境変数(Pythonではos.environ、Node.jsではprocess.env)を使用するか、.envファイルをdotenvライブラリで使用してください。

安全な保存方法 .env(Python)

import os
from dotenv import load_dotenv
from playwright.sync_api import sync_playwright

load_dotenv()

PROXY_SERVER   = os.getenv("PROXY_SERVER")
PROXY_LOGIN    = os.getenv("PROXY_LOGIN")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server":   PROXY_SERVER,
            "username": PROXY_LOGIN,
            "password": PROXY_PASSWORD
        }
    )
    # ...

プロキシのローテーション:リクエストごとのIP変更

1つのプロキシだけでは、大量のリクエストに対して禁止を回避することはできません。真剣なパースにはIPのローテーションが必要です — 特定の間隔でプロキシサーバーを自動的に変更するか、新しいリクエストごとに変更します。

Playwrightにおけるローテーションには2つのアプローチがあります:

アプローチ1:ローテーションプロキシエンドポイント

ほとんどのレジデンシャルプロキシプロバイダーは、接続ごとに自動的にIPを変更する単一のゲートウェイアドレスを提供します。ローテーションのロジックを書く必要はありません — プロバイダー側に組み込まれています。

# 1つのエンドポイント — ブラウザ接続ごとに新しいIP
browser = p.chromium.launch(
    proxy={
        "server":   "http://rotating.proxyprovider.com:8888",
        "username": "your_login",
        "password": "your_password"
    }
)

アプローチ2:プロキシリストを使用した手動ローテーション

静的プロキシのリストがある場合は、各イテレーションごとに新しいブラウザまたはコンテキストを作成することで手動ローテーションを実装できます:

import random
from playwright.sync_api import sync_playwright

PROXY_LIST = [
    {"server": "http://proxy1.example.com:8080", "username": "user", "password": "pass"},
    {"server": "http://proxy2.example.com:8080", "username": "user", "password": "pass"},
    {"server": "http://proxy3.example.com:8080", "username": "user", "password": "pass"},
]

URLS_TO_SCRAPE = [
    "https://example.com/page1",
    "https://example.com/page2",
    "https://example.com/page3",
]

with sync_playwright() as p:
    for url in URLS_TO_SCRAPE:
        proxy = random.choice(PROXY_LIST)  # ランダムプロキシ
        
        browser = p.chromium.launch(proxy=proxy)
        page = browser.new_page()
        
        page.goto(url)
        # ... データのパース ...
        
        browser.close()  # ブラウザを閉じてIPを変更

アプローチ3:BrowserContextを使用したローテーション(ブラウザの再起動なし)

with sync_playwright() as p:
    browser = p.chromium.launch()  # プロキシなしのブラウザ
    
    for i, url in enumerate(URLS_TO_SCRAPE):
        proxy = PROXY_LIST[i % len(PROXY_LIST)]  # サイクル
        
        # 新しいプロキシで新しいコンテキスト — ブラウザの再起動よりも速い
        context = browser.new_context(proxy=proxy)
        page = context.new_page()
        
        page.goto(url)
        # ... パース ...
        
        context.close()  # ブラウザを閉じずにコンテキストを閉じる
    
    browser.close()

第三のアプローチは、大量のパースに最も効率的です。ブラウザの再起動には2〜4秒かかりますが、新しいコンテキストの作成には100ミリ秒未満です。

コンテキストおよびページレベルのプロキシ

Playwrightは柔軟なアーキテクチャをサポートしています:1つのブラウザは、各自のプロキシを持つ複数の隔離されたコンテキストを持つことができます。これにより、1つのプロセス内で複数のIPを同時に使用して作業できます。

異なるプロキシを持つ複数のコンテキスト(並行パース)

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();

  // コンテキスト1 — ドイツのプロキシ
  const context_de = await browser.newContext({
    proxy: {
      server: 'http://de-proxy.example.com:8080',
      username: 'user',
      password: 'pass'
    }
  });

  // コンテキスト2 — アメリカのプロキシ
  const context_us = await browser.newContext({
    proxy: {
      server: 'http://us-proxy.example.com:8080',
      username: 'user',
      password: 'pass'
    }
  });

  const page_de = await context_de.newPage();
  const page_us = await context_us.newPage();

  // 並行実行
  await Promise.all([
    page_de.goto('https://example.com'),
    page_us.goto('https://example.com')
  ]);

  // 両方のページが異なるIPを認識
  console.log('DE IP:', await page_de.textContent('body'));
  console.log('US IP:', await page_us.textContent('body'));

  await browser.close();
})();

このアプローチは、ジオロケーションのテストに最適です。異なる国のユーザーに対してサイトがどのように表示されるかを同時に確認でき、複数のブラウザインスタンスを起動する必要がありません。

💡 パフォーマンスのヒント

最大の並行性を得るために、Pythonではasyncio、Node.jsではPromise.allを使用してください。1つのブラウザは、メモリに大きな負荷をかけることなく10〜20の並行コンテキストを保持できます。

アンチボット保護の回避:Cloudflare、Akamai、DataDome

プロキシは解決策の一部に過ぎません。現代のアンチボットシステムは、ブラウザのフィンガープリンティング、マウスの動き、フォームの入力速度、HTTPヘッダーなど、数十の信号を同時に分析します。良いプロキシを使用していても、これらの要因を考慮しないとブロックされる可能性があります。

1. ヘッドレスモードのマスキング

Playwrightはヘッドレスモードで特有の特徴を持っており、簡単に特定できます:特定のnavigator.webdriverの値、プラグインの不在、非標準の画面サイズ。playwright-stealthライブラリを使用してマスキングを行ってください:

# Python: インストール
# pip install playwright-stealth

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server":   "http://residential.proxyprovider.com:8888",
            "username": "user",
            "password": "pass"
        }
    )
    page = browser.new_page()
    stealth_sync(page)  # マスキングを適用
    
    page.goto("https://bot.sannysoft.com")  # ボット判定テスト
    browser.close()

2. リアルなUser-Agentとビューポート

context = browser.new_context(
    proxy={
        "server":   "http://proxy.example.com:8080",
        "username": "user",
        "password": "pass"
    },
    user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    viewport={"width": 1920, "height": 1080},
    locale="ja-JP",
    timezone_id="Europe/Tokyo"  # プロキシのジオロケーションと一致する必要があります!
)

3. 人間の行動の模倣

import time
import random

# アクション間のランダムな遅延
def human_delay(min_ms=500, max_ms=2000):
    time.sleep(random.randint(min_ms, max_ms) / 1000)

page.goto("https://example.com")
human_delay()

# 瞬時ではなくスムーズなスクロール
page.evaluate("window.scrollBy({top: 500, behavior: 'smooth'})")
human_delay(300, 800)

# クリック前のマウスの動き
page.mouse.move(100, 200)
human_delay(100, 300)
page.mouse.move(300, 400)
human_delay(100, 200)
page.click("button#submit")

4. プロキシのジオロケーションに合わせたタイムゾーンの一致

これはしばしば無視されますが、アンチボットシステムは一致を確認します:もしあなたのプロキシがモスクワにあり、ブラウザがUTC-8(ロサンゼルス)を表示している場合 — これは赤信号です。常に使用するプロキシのジオロケーションに合わせてtimezone_idを設定してください。

一般的なエラーとその修正方法

Playwrightでプロキシを使用する際、開発者は定期的に同じ問題に直面します。それぞれの問題を具体的な解決策とともに解説します。

エラー1: ERR_PROXY_CONNECTION_FAILED

原因: プロキシのアドレスまたはポートが無効、プロキシが利用できない、認証情報が無効です。
解決策: Playwrightを起動する前にcurlを使用してプロキシの可用性を確認してください:

# curlを使用してプロキシを確認
curl -x http://user:[email protected]:8080 https://api.ipify.org

エラー2: SOCKS5が認証を受け付けない

原因: Playwright(Chromium)は、username/passwordによる認証を持つSOCKS5のサポートが制限されています。
解決策: 認証付きのHTTPプロキシを使用するか、ssh -Dを使用してパスワードなしのローカルSOCKS5トンネルを設定してください。

エラー3: プロキシは動作しているが、サイトがブロックする

原因: データセンターのプロキシがブラックリストに載っている;ヘッドレスモードがマスキングされていない;リクエストの頻度が高すぎる。
解決策: レジデンシャルまたはモバイルプロキシに切り替え、playwright-stealthを追加し、リクエスト間の遅延を増やしてください。

エラー4: 実際のIPの漏洩(DNSリーク)

原因: DNSリクエストがプロキシをバイパスする可能性があります。
解決策: Playwrightは、HTTPプロキシを使用する際にデフォルトでDNSをプロキシ経由でルーティングします。しかし、ヘッドレスブラウザでhttps://dnsleaktest.comを使用して確認してください。

エラー5: プロキシの動作が遅い

原因: レジデンシャルプロキシはデータセンターのものより遅く、プロキシサーバーまでの距離が大きい。
解決策: 地理的に近い場所にあるプロキシを選択してください。厳しい匿名性の要件がないタスクには、データセンターのプロキシを使用してください。これらははるかに速いです。

エラー 迅速な解決策
ERR_PROXY_CONNECTION_FAILED curl、ログイン/パスワード、ポートの可用性を確認
407 Proxy Auth Required プロキシ設定にusernameとpasswordを追加
サイトがCAPTCHAを表示 プロキシの種類をレジデンシャルに変更し、stealthを追加
IPがローテーション時に変更されない リクエスト間にコンテキスト/ブラウザを閉じる
接続タイムアウト goto()のタイムアウトを増やし、より近いプロキシを選択

結論と推奨事項

Playwrightにおけるプロキシの設定は、一度きりのタスクではなく、自動化ツールのアーキテクチャの一部です。適切に選択されたプロキシの種類、適切なIPのローテーション、ヘッドレスモードのマスキングは、攻撃的なアンチボット保護を持つサイトでも安定した動作を提供します。

特定のタスクに対するプロキシの種類の選択についてまとめます:

  • 厳しい保護がないオープンデータのパース — 高速なデータセンターのプロキシが適しています。
  • マーケットプレイス(Wildberries、Ozon)、ニュースアグリゲーター — ローテーションを持つレジデンシャルプロキシが必要です。
  • ソーシャルメディア(Instagram、Facebook、TikTok)およびCloudflareを使用しているサイト — モバイルまたはレジデンシャルプロキシのみ。
  • ジオロケーションのテスト — 必要な国にある任意のプロキシタイプ、重要なのはタイムゾーンの一致です。
  • 高頻度の大量パース — ゲートウェイエンドポイントを持つローテーションレジデンシャルプロキシ。

Playwrightでのパースシステムや自動化テストを構築しており、ブロックなしで安定した動作が必要な場合は、レジデンシャルプロキシを検討することをお勧めします。これらはウェブサイトからの高い信頼を提供し、単一のエンドポイントを介してIPのローテーションをサポートしているため、Playwrightとの統合が数行のコードで簡素化されます。

```
Playwrightにおけるプロキシ:ヘッドレステストの設定