本文へスキップ

Playwright & Puppeteer

Clearcote の中身はあくまで Chromium なので、いま使っている自動化ツールのブラウザとしてそのまま差し替えて使えます。

clearcote パッケージ(npm、PyPI、NuGet)は、アイデンティティ関連のオプションを名前付き引数として受け取り、通常の Playwright オブジェクトを返します。初回利用時にはブラウザをダウンロードして SHA-256 で検証し(ライセンスキーがなければオープンビルド、あれば最新のライセンスビルド。インストールを参照)、後述のデフォルト設定を適用します。

# pip install clearcote
from clearcote import launch

browser = launch(fingerprint="seed-123", platform="windows", brand="Chrome")
page = browser.new_page()
page.goto("https://example.com")
browser.close()

現在の SDK:0.31.1。0.23 以降、Python と Node の launch() はシークレットモードではなく、実際の使い捨てプロファイルディレクトリ(終了時に削除)上で動作します。そのため、プロファイルに由来する特徴が実際の Chrome と一致し、widevine: true で DRM モジュールも読み込めます。返されるのはブラウザに似たハンドルで、newPage() はこれまでどおり使えますが、newContext() は分離されたコンテキストではなく、同じプロファイルのコンテキストを返します。Cookie を分けたい場合はブラウザを別々に起動してください。従来のシークレットモードの Browser が必要なら ephemeralProfile: false / ephemeral_profile=False を、プロファイルを残したいなら userDataDir / user_data_dir を渡します。

async API(clearcote.async_api)は、asyncio ループの中で同じペルソナ・プロキシのオプションを受け取り、Playwright の非同期オブジェクトを返します。こちらの launch() はシークレットモードなので、プロファイルを使う場合(および widevine=True を使う場合)は launch_persistent_context() を使ってください。.NET SDK が対応しているのは、LaunchEphemeralProfileAsync(推奨。.NET の LaunchAsync はシークレットモードで、ヘッドレスのウィンドウを画面に合わせられません)、LaunchPersistentContextAsync、ServeAsync、検証付きダウンロード、ライセンス処理、Geoip、人間らしい入力(起動フラグではなく、HumanClickAsync / HumanTypeAsync / HumanSelectOptionAsync を明示的に呼び出す方式)です。保存済みプロファイル、profile: "auto"、レンダリングの整合性チェック、Widevine、エージェント用ヘルパーは、現時点では Python と Node のみです。コピペで使える一連のワークフローはサンプルを参照してください。

Puppeteer などの CDP クライアント(serve)

SDK には Puppeteer 用のランチャーはありません。代わりに serve() が、SDK の起動設定(ペルソナ、プロキシ、デフォルト設定)で Clearcote を起動し、ループバック上に CDP エンドポイントを開きます。そこには Puppeteer、Playwright の connectOverCDP、browser-use、Crawl4AI、Stagehand など、任意の CDP クライアントが接続できます。ライセンスビルドでも動作し、--enable-automation はどこからも付与されません。humanize は Playwright 側の機能なので、この方法で接続したクライアントには適用されません。

import { serve } from "clearcote";
import puppeteer from "puppeteer-core";

const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
const browser = await puppeteer.connect({ browserURL: srv.cdpUrl, defaultViewport: null });
const page = await browser.newPage();
await page.goto("https://example.com");
await browser.disconnect();
await srv.close();

ヘッドレスの場合、serve() はクライアントが接続する前に、ブラウザに実寸のディスプレイを与え、ウィンドウを作業領域に合わせます(0.31+)。ウィンドウを小さくしたい場合は windowSize / window_size を渡してください。シェルからは clearcote serve が同じことを常駐サービスとして行います。さらに、接続 URL から取ったアイデンティティ、プロキシ、タイムゾーン、言語で、接続ごとに専用のブラウザを割り当てることもできます。デプロイを参照してください。

バイナリを直接操作する(オープンビルド)

自前のランチャーで executablePath(Node)または executable_path(Python)をオープンビルドに向け、アイデンティティのオプションを args として渡すこともできます。ライセンスビルドはこの方法では起動しません。SDK が取得するライセンストークンが必要なので、前述の launch() か serve() を使ってください。--enable-automation は SDK と同じように外してください(Puppeteer や古いバージョンの Playwright はこれを付与し、Chromium を自動化モードに切り替えてしまいます)。この方法では、SDK のデフォルト設定(言語、WebRTC ポリシー、ウィンドウのジオメトリ)は一切適用されません。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        executable_path=r"C:\clearcote\chrome.exe",
        headless=False,
        ignore_default_args=["--enable-automation"],
        args=[
            "--fingerprint=seed-123",
            "--fingerprint-platform=windows",
            "--timezone=America/New_York",
        ],
    )
    page = browser.new_page()
    page.goto("https://abrahamjuliot.github.io/creepjs/")
    browser.close()

検証済みバイナリの解決とプリフェッチ

SDK は次の順でブラウザを決定します。明示的に指定した executablePath / executable_path、次に CLEARCOTE_BINARY、次に指定した version(または CLEARCOTE_BROWSER_VERSION)、次にライセンスキーが見つかればライセンスビルド(licenseKey オプション、CLEARCOTE_LICENSE_KEY、~/.clearcote/license.key)、最後にこの SDK バージョンで固定されたオープンビルドです。指定したパスは、起動前にファイルの欠落や途中で切れたファイルがないかチェックされます。起動せずにキャッシュを温めておきたい場合、独自のキャッシュディレクトリを使いたい場合、または実行時に GitHub 上の最新のオープンビルドを使うようにしたい場合は、download / executable_path を呼び出してください。

from clearcote import download, launch

chrome = download(cache_dir=r"C:\clearcote-cache", auto_update=True)
browser = launch(executable_path=chrome, fingerprint="seed-123")

固定モードでは、SDK に組み込まれた SHA-256 値で検証します。autoUpdate / auto_update はオプトインで、リリースのチェックサムマニフェストを検証します。gpg が使える場合は、署名済みマニフェストを、固定された Clearcote 署名鍵のフィンガープリントとも照合します。これはオープンビルドにのみ適用されます。ライセンスキーがある場合、download() は代わりに現行のライセンスビルドを取得します(ビルドは version または releaseChannel で選べます。ビルドの選び方を参照)。.NET の DownloadAsync が取得するのはオープンビルドのみです。ライセンスビルドをプリフェッチするには ExecutablePathAsync(new LaunchOptions { LicenseKey = … }) を使います。

実機の Chrome のプロファイルをインポートする

シードから合成したペルソナの代わりに、実機から取得した値を Clearcote に返させることもできます。プロファイルは、取得元となる Chrome で tools/fingerprint-collect のコレクターで取得できます(collect.html を開いて「Capture」をクリックすると、JSON プロファイルがダウンロードされます)。また、同梱の convert_dataset.py コンバーターを使えば、オープンソースの chrome-fingerprints データセット(10k レコード)から作ることもできます。取得対象は navigator、画面のジオメトリ、WebGL のベンダー/レンダラーと getParameter の上限値、Web Audio、音声合成のボイス、フォント、コーデック、CSS @media の特性です。

プロファイルは、ファイルパス、オブジェクト、JSON 文字列のいずれかで SDK に渡します。gzip + base64 へのパッキングは SDK が行います。プロファイルに存在するフィールドは、ブラウザが本来返す値を上書きし、存在しないフィールドはブラウザのデフォルトにフォールバックします。Accept-Language を明示的に指定しなかった場合、SDK はプロファイルの navigator.languages からそれを導出します。インポートしたプロファイルはどちらのビルドでも読み込めます。ライセンスビルドでは 151 r19 以降で完全に適用されます。

プロファイルと一緒に fingerprint シードを渡さないでください。シードを渡すと farbling レイヤーが有効になり、厳格なスコアリングではそれが canvas の改ざんとみなされます。しかも、プロファイルがすでに提供している以上のものは何も得られません。どちらか一方だけを使ってください。プロファイルが置き換えるのは報告される値だけで、ピクセルを描画する仕組みは一切変わりません。そのため、1 台のマシン上で 2 つのアカウントがそれぞれ別のプロファイルを使っても、canvas はまったく同じになります。アカウントごとに描画結果を分ける必要がある場合は、プロファイルを使わず、アカウントごとのシードを使ってください。

from clearcote import launch

browser = launch(fingerprint_profile="profile.json", disable_gpu_fingerprint=True, fingerprint_noise=False)
page = browser.new_page()
page.goto("https://example.com")
browser.close()

デフォルトで整合性を保つ(追加フラグ不要)

どのオプションで起動しても、エンジンは二次的なサーフェスを、選んだペルソナと一致させます。Windows ペルソナなら、実際の Windows 版 Chrome のデスクトップ環境が返す値に合わせます。ペルソナのプラットフォームはデフォルトでホスト OS になるため、Linux ホストでは platform を指定しない限り、これらは Linux ペルソナに従います。WebGL の getParameter で得られる上限値(WebGL1 + WebGL2)はペルソナの値になります。ただし、このマシンの GPU が実際に対応できる範囲に制限されます。UNMASKED_RENDERER / UNMASKED_VENDOR はセッション中一定です(ペルソナに従い、どのサイトでも同じ GPU)。Windows ペルソナでは、navigator.getBattery() は AC 電源で動くデスクトップを、navigator.connection は家庭用の回線を、AudioContext はそれに見合った Windows WASAPI のサンプルレートとレイテンシを返します。getScreenDetails() はモニター 1 台を返し、@media (pointer: fine) / (hover: hover) はマウスを使うデスクトップと一致します。

153 r26 を Windows 上の headed モードで確認した結果(2026 年 9 月):BrowserScan の判定は「ボットではない」、CreepJS の stealth は 0% でした。プロキシ経由の場合は geoip を追加して、タイムゾーンと WebRTC を出口に合わせてください。

コンソールとページエラーのイベント

エンジンはコンソールやページエラーのイベントを自動化クライアントに転送しないため、page.on("console") と page.on("pageerror") は何も受け取りません。これは意図した設計です。これらのイベントを転送すること自体が、自動化の存在を探るプローブの計測対象だからです。ページ内の window.onerror と unhandledrejection のハンドラーは通常どおり発火するので、コンソール出力を取得したい場合はページ内で収集し、page.evaluate() で読み出してください。Python と Node の SDK は、起動時にこの点について一度だけ注意を表示します。

プロキシの地域に自動で合わせる(geoip)

プロキシと一緒に geoip を渡すと、SDK はプロキシの出口 IP をオフラインの geoip-all-in-one データベースで調べ、その地域に合った整合性のあるタイムゾーン + navigator の主言語 + Accept-Language + WebRTC IP を設定します。プロキシごとにタイムゾーンを手作業で合わせる必要はもうありません。

from clearcote import launch

browser = launch(
    fingerprint="user-7423",
    proxy={"server": "http://host:8080", "username": "u", "password": "p"},
    geoip=True,  # timezone + language auto-matched to the proxy's region
)

その地域の位置情報と、navigator.languages の完全なリストも設定します。HTTP と SOCKS5 のプロキシ(認証情報付きも含む)で動作し、3 つの SDK すべてで使えます(.NET では Geoip = true)。初回実行時にデータベース(約 50 MB)をダウンロードします。地域を解決できない場合、このマシンの時計や言語のまま黙って起動するのではなく、GeoipError で起動を中止します。それでも起動したい場合は、timezone と acceptLanguage の両方を設定してください。ルックアップの制限時間は 20 秒(CLEARCOTE_GEOIP_TIMEOUT_SECONDS)で、.NET ではエラーは GeoipException になります。geoip も明示的な timezone もない場合、タイムゾーンは言語に従います。en-US なら、ドイツのプロキシ経由でもニューヨークになります。

自分で設定したい場合は、acceptLanguage(Node)/ accept_language(Python)を使います(例:"en-US,en")。これで Accept-Language ヘッダー、navigator.languages 配列全体、navigator.language が設定され、Intl / toLocaleString もそれに従います。

人間らしい入力(humanize と showCursor)

humanize を渡すと、移動、クリック、ドラッグ、スクロール、タイピングといったすべての入力が、ページレベル(page.click / hover / type / fill / mouse.* / keyboard.type)でもロケーターレベル(locator.click / type / fill / pressSequentially / dragTo / …)でも、統一された人間らしい動作で実行されます。移動は、直前のカーソル位置から組み立てた、わずかに弧を描く 3 次ベジェ曲線に沿って進みます。その進み方は min-jerk のサブムーブメント合成です(弾道的な主運動 + 修正運動。左右対称なベル型 1 つではなく、実際に手を伸ばす動作に見られる複数ピークの速度プロファイルです)。すべての入力は本物の、信頼された(trusted)イベントとしてディスパッチされます(isTrusted === true で、navigator.webdriver も false のままです)。Pro では、座標指定のクリック(mouse.click(x, y))は実際の人間から記録した動きに従います。それ以外の操作、およびオープンビルドと「GitHub で無料」でのすべてのクリックは、生成した軌跡を使います。showCursor を追加すると、動きに追従するドットが描画され、動作を目で確認できます。

移動にはネイティブ入力を使うため、mouse.down() で押したボタンは移動中も押されたままです。つまり down → move → up は、ボタンを押したままの本物のドラッグになり(スライダーのように目的の位置までドラッグするコントロールでも、実際に押した状態でドラッグされます)、locator.dragTo も人間らしい動作になります。タイピングは 1 キーずつ行い、キー間隔はランダムで、単語の区切りでは間を置き、ときどき打ち間違いを修正します。スクロールはイーズアウトの慣性を使い、ときどき読むための間を挟みます。fill はフィールドにフォーカスしてから入力します(約 200 文字を超える値は一度にまとめて入力されるので、大量の入力でも遅くなりません)。

from clearcote import launch

browser = launch(fingerprint="seed-123", humanize=True, show_cursor=True)
page = browser.new_page()
page.goto("https://example.com")

page.click("text=Sign in")               # eased curve, then a trusted click
page.fill("#email", "you@example.com")   # focus + key-by-key human typing
page.locator("#password").type("s3cr3t") # locators are humanized too

# held-button drag (e.g. a slider): the press stays held across the move
x0, y0, x1 = 100, 300, 400               # the handle's start, and where to release it
page.mouse.move(x0, y0); page.mouse.down()
page.mouse.move(x1, y0); page.mouse.up()
browser.close()

レンダリングバックエンドの整合性チェック(checkRenderCoherence)

ペルソナで GPU を名乗っていても、実際にはページがソフトウェアラスタライザー(SwiftShader / llvmpipe。GPU のないヘッドレス環境でよくあります)で描画されていれば、厳格な検出器には見分けられてしまいます。そこで、稼働中のページを調べます。このチェックは、ページから実際に見える(アンマスクされた)WebGL のベンダー/レンダラーを読み取り、ソフトウェアラスタライザーへのフォールバック(ヘッドレスであることを決定的に示す手がかりです。canvas ブリッジを有効にするか、実際の GPU 上で headed モードで実行してください)や、整合しないベンダー/レンダラーの組み合わせを検出して、構造化された判定結果を返します。名乗っている GPU を渡すと、描画された GPU ファミリーの検証も行います。同期版、非同期版、Node 版があります。

from clearcote import launch, check_render_coherence

browser = launch(fingerprint="seed-123")
page = browser.new_page(); page.goto("about:blank")

verdict = check_render_coherence(page)   # {'renderer', 'software_suspected', 'coherent', 'warnings'}
if not verdict["coherent"]:
    print(verdict["warnings"])            # e.g. software rasterizer / incoherent GPU family
browser.close()

プロファイルと永続化

同じ fingerprint シードを使い回せば、実行をまたいでアイデンティティを安定させられます。Cookie やストレージは、ユーザーデータディレクトリで永続化します。

from clearcote import launch_persistent_context

ctx = launch_persistent_context(r"C:\clearcote\profiles\acme", fingerprint="acme-tenant-7", headless=False)
page = ctx.pages[0] if ctx.pages else ctx.new_page()

プロファイルディレクトリの Cookie は、そのプロファイルを作成したマシンに紐づいたキーで暗号化されます。Cookie を保ったままプロファイルを別のマシンにコピーするには、portableProfile: true / portable_profile=True(キーがプロファイルと一緒に移動します)か、encryptionKey / encryption_key(キーは自分で決めたシークレットから導出され、機密情報はディスクに書き込まれません)を渡します。対象はライセンスビルドの Python と Node です。

SDK にはペルソナの保存機能もあります。Profile は、フィンガープリントのオプション、プロキシ設定、canvas ブリッジの設定、その他の起動オプションを、JSON として ~/.clearcote/profiles 以下に保存します(保存先は CLEARCOTE_PROFILE_DIR で変更できます)。

from clearcote import Profile, launch, launch_persistent_context

Profile("acct-1", {
    "fingerprint": "acct-1",
    "gpu_vendor": "Google Inc. (Intel)",
    "gpu_renderer": "ANGLE (Intel, Intel(R) UHD Graphics ... D3D11)",
    "canvas_bridge": {"url": "ws://127.0.0.1:8443", "auth": "user:secret"},
}).save()

ctx = launch_persistent_context(r"C:\clearcote\profiles\acct-1", profile="acct-1")
browser = launch(profile="acct-1", headless=False)
保存されたプロファイルは平文で、canvasBridge.auth などの認証情報を含むことがあります。プロファイルのファイルは信頼された入力として扱い、コミットしたり共有したりしないでください。

その他の起動オプション

  • extensions — 展開済み拡張機能のディレクトリパスのリスト(--load-extension + --disable-extensions-except を出力します)。
  • disablePrivacySandbox / disable_privacy_sandbox — true にすると Privacy Sandbox の API(Topics、FLEDGE / Protected Audience、Shared Storage、Private Aggregation、Fenced Frames)を無効にします。0.23 以降はデフォルトでオフです。デフォルトのペルソナは Google Chrome として振る舞い、Google Chrome はこれらの API をすべて搭載しているためです。このオプションを有効にするのは、ペルソナが Google 依存を取り除いた Chromium の場合だけにしてください。WebUSB には影響しません。
  • agentTyping / agent_typing — エージェントのキー入力のテンポ(human(デフォルト)/ fast / instant)。エージェントを参照してください。
  • tlsProfile — TLS ClientHello をペルソナが名乗る Chrome のバージョンと整合させ、ネットワーク層を(ビルド本来の TLS ではなく)UA に合わせます。デフォルトの "match-persona" は brandVersion に従い、"native" は手を加えず、"chrome-<major>" はメジャーバージョンを固定します。フィンガープリントフラグを参照してください。
  • platform: "android" — ベストエフォートのモバイルペルソナ(タッチ、coarse ポインター、モバイルの画面/DPR、Mali/Adreno の WebGL、スマートフォンのビューポート)。デスクトップのエンジンでは GPU の描画はデスクトップのままなので、描画の整合性を取るには canvas ブリッジと組み合わせてください。
  • storageQuota、fingerprintProfile、canvasBridge、webrtcIp、acceptLanguage、disableGpuFingerprint、fingerprintNoise — フィンガープリントフラグを参照してください。

新しいオプション(ライセンスビルド)

以下のオプションにはライセンスビルド(「GitHub で無料」または Pro)が必要です。それぞれに必要なエンジンのリビジョンを角かっこ内に示しています。古いエンジンでは、152 r22 のオプションは SDK が警告を出してスキップし、それ以外はエンジンが無視します。

  • allowThirdPartyCookies / allow_third_party_cookies — 標準の Chrome と同じようにサードパーティ Cookie を許可します。Google 依存を取り除いたベースはデフォルトでこれをブロックするため、サードパーティ Cookie に依存する埋め込みのサインイン、決済、チャレンジのフレームが動作しなくなります。[152 r22]
  • transparentProxy / transparent_proxy — リクエストヘッダーと接続タイミングからプロキシの存在を隠します(平文 HTTP のリクエストにはプロキシヘッダーが付かず、プロキシ経由の接続は再利用された接続のようなタイミングを報告します)。プロキシが必要です。[152 r22]
  • fingerprintVoices: false / fingerprint_voices=False — ペルソナのリストではなく、このマシン本来の音声合成ボイスを使います。[152 r22]
  • fingerprint: "off" — トラブルシューティング用に、ペルソナなしで起動します。[152 r22]
  • socks5Udp / socks5_udp — WebRTC の UDP を socks5:// プロキシ経由で流します。これにより音声、ビデオ、ピア接続が動作し、しかも通信はプロキシのアドレスから出ていきます。プロキシ側で許可されている必要があり、住宅用プロキシのプールの多くは許可していません。[151 r17]
  • portableProfile / encryptionKey — マシン間でコピーできるプロファイル(前述)。[151 r14; Python & Node]
  • personaSchema: 2 / persona_schema=2 — 画面とグラフィックスチップを、ペルソナが名乗るプロセッサーとメモリに見合ったものにする、オプションのアイデンティティモデルです。デフォルトではオフなので、既存のシードはどれも今のアイデンティティのままです。realGpuHost / real_gpu_host は、実際のグラフィックスカードを搭載したマシンでのみ追加してください。[151 r19; Python & Node]
  • shaderDialect: "hlsl" — シェーダー方言を参照してください。[151 r15]
  • profile: "auto" — シードの代わりに、このマシン向けに選んだ、実機から取得したフィンガープリントで起動します。profileSelect / profile_select で調整できます。Python & Node。Node では SDK 0.31.1 以降、デフォルトの launch()、launchPersistentContext()、serve() で動作します。0.31.0 以前は ephemeralProfile: false が必要で、serve() では失敗していました。

エンジンのビルドに依存しないもの:

  • version / releaseChannel — ビルドを選びます。ビルドの選び方を参照してください。
  • licenseKey / license_key / LicenseKey — ライセンスキー(CLEARCOTE_LICENSE_KEY にも ~/.clearcote/license.key にもない場合)。
  • licenseThroughProxy / license_through_proxy(または CLEARCOTE_LICENSE_THROUGH_PROXY=1)— ライセンス関連の通信を、このマシンから直接ではなく、起動時に指定したプロキシ経由で送ります。
  • launch() の ephemeralProfile / userDataDir — 前述の「SDK を使う方法」の説明を参照してください。
  • widevine: true — DRM コンテンツの再生(両ビルドとも対応)。Widevine & DRM を参照してください。
  • quiet — SDK の起動時の警告と進捗の出力を抑制します。

整合性のあるデフォルト設定(上書き可能)

SDK は、わかりやすい手がかりが漏れないよう、ステルスの観点で正しいデフォルト設定をいくつか適用します。

  • headed での起動では、デフォルトでビューポートをエミュレートしません(viewport: null / no_viewport=True)。そのため window.innerWidth は実際の OS ウィンドウに追従します。実際のウィンドウの上にエミュレートした 1280×720 が載っていると、ありえないウィンドウ構成という手がかりになります。上書きするには viewport を明示的に指定してください。
  • WebRTC のデフォルトは disable_non_proxied_udp です。プロキシを通らない UDP は送信されず、マシン自身のアドレスは外に出ません。これを上書きするのは、args に自分で指定した --webrtc-ip-handling-policy だけです。ただしオープンビルドでは webrtcIp / geoip も上書きし、WebRTC の UDP が再び自分の回線から送信されるようになります(ライセンスビルドはどの場合も WebRTC の UDP をブロックします)。このポリシーで webrtcIp がない場合、ページは ICE 候補をまったく取得できません。プロキシ経由なら、geoip(または webrtcIp)を渡して WebRTC がプロキシのアドレスを報告するようにするか、socks5Udp で実際の UDP を SOCKS5 プロキシ経由で流してください。
  • プロキシ経由では QUIC / HTTP-3 はオフです。プロキシ経由の実際の Chrome と同じで、プロキシを通らない UDP は試行されません。
  • ペルソナのプラットフォームはデフォルトでホスト OS、ブランドは Google Chrome です。timezone も geoip もない場合、タイムゾーンは言語に従います(en-US → ニューヨーク)。
  • エンジンが対応している場合、プロキシの認証情報は Playwright ではなくブラウザに渡されます。SOCKS5 では常に(Playwright は SOCKS5 の認証にまったく対応していません)、HTTP(S) では 151 r19+ でブラウザに渡され、ページキャッシュが有効のまま保たれます(Python & Node)。詳しくは後述します。
  • humanize は、trusted クリックの前に毎回操作可能性の事前チェック(表示されているか / 有効か / 安定しているか + elementFromPoint による被覆チェック)を行い、必要に応じてネイティブのクリックにフォールバックします。そのため、trusted クリックがオーバーレイの下やアニメーションの途中で発火することはありません。

認証付き SOCKS5

標準の Chromium は、SOCKS5 プロキシへの認証がまったくできません(ユーザー名/パスワードのサブネゴシエーションが実装されていません)。そのため、認証情報を保持するローカルリレーを挟むのが一般的な対処法です。ライセンスビルドはこれをエンジン内に実装している(RFC 1929)ので、リレーは不要です。ユーザー名とパスワードは、個別のフィールドとしてもアドレス内(socks5://user:pass@host:port)にも指定でき、どちらの場合も SDK がエンジンに渡します。アドレス内の認証情報には SDK 0.31.1 以降が必要です。それより古い SDK では Playwright が認証情報を落としてしまい、プロキシ側にはログインが届いていませんでした。

from clearcote import launch_persistent_context

ctx = launch_persistent_context(
    "./profile",
    proxy={"server": "socks5://proxy.example.net:1080", "username": "user", "password": "pass"},
)
page = ctx.pages[0] if ctx.pages else ctx.new_page()
page.goto("https://api.ipify.org?format=json")   # confirm the exit IP is the proxy's

ライセンスビルド(「GitHub で無料」または Pro、エンジン 151 r14 以降)が必要です。オープンビルドは SOCKS5 プロキシへの認証ができないため、ローカルリレーか HTTP プロキシと組み合わせて使ってください。

セッションを信頼する前に、必ず出口アドレスを確認してください。黙ってフェイルオープンするプロキシは自分の IP からトラフィックを送ってしまい、ほかのあらゆる対策が無意味になります。問題ないと決めつけず、起動時に一度、アクセス元のアドレスを返すサービスで確認してください。

ヒント:シードを自分のアカウント ID やテナント ID から導出すれば、各アイデンティティを再現できます。同じシードなら、いつでも同じブラウザフィンガープリントになります。スイッチの一覧はフィンガープリントフラグを参照してください。