Stealthy Auto Browse について
Stealthy Auto Browse は、Docker 上の Camoufox を基盤とするセルフホスト可能なブラウザー自動化サービスで、OS レベルの入力と HTTP API を備えています。リモート操作、スクリプト実行、noVNC によるライブ表示を必要とするエージェントや自動化ワークフロー向けです。
主な機能
- 01Docker 上の Camoufox ブラウザー
- 02OS レベルのマウスとキーボード入力
- 03JSON HTTP API と YAML スクリプト
- 04noVNC によるブラウザーのライブ表示
- 05リクエストキューとクラスター実行
活用シーン
- 01CI や定期ジョブでのブラウザー自動化
- 02リモートでの複数ステップ操作
- 03noVNC を使った自動化セッションの確認
- 04カメラやマイクへのアクセスを要求するページのテスト
MCP 対応
MCP サーバーはポート 8080 の `/mcp` で Streamable HTTP を提供します。ナビゲーション、スクリーンショット、クリック、入力、JavaScript 評価、Cookie 管理などをツールとして公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
docker-stealthy-auto-browse
実際に動作するステルスブラウザー自動化ツールです。Camoufox(カスタム Firefox)を Docker 上で実行し、Chrome DevTools Protocol の露出をゼロに抑えながら、PyAutoGUI を通じて OS レベルの実際のマウス・キーボード入力を行います。JSON HTTP API と MCP サーバーを使って、すべてをリモートから操作できます。noVNC で動作をライブで確認できます。単一インスタンスで実行することも、Redis による Cookie 同期、リクエストキュー、スティッキーセッションを備えた HAProxy の背後にクラスターを構築することもできます。curl で操作したり、YAML スクリプトを標準入力経由で渡したり、API 経由で複数ステップのスクリプトを送信したり、ページローダーを使用してポップアップやペイウォールを自動処理したり、MCP 経由で AI エージェントを直接接続したりできます。AUTH_TOKEN による Bearer トークン認証も任意で利用できます。
このイメージは Chromium CDP のシグナルを回避し、生成される Linux のフォントと WebGL のフィンガープリントの一貫性を保ちます。検出結果はサイト、ネットワークの出口、タイムゾーン、ブラウザービルド、テスト日によって異なります。
目次
- 内容
- クイックスタート
- 2 つの入力モード
- クリップボード
- 仮想カメラとマイク
- MCP サーバー
- エージェント連携
- スクリプトモード
- ページローダー
- 画面録画
- クラスター��ード
- 認証
- 設定
- 開発
- ボット検出の結果
- 行動検出の結果
- ライセンス
内容
| コンポーネント | 機能 |
|---|---|
| Camoufox | Chrome DevTools Protocol を一切公開しない、カスタムビルド版の Firefox です。ボット検出ツールは CDP のシグナルを探しますが、このブラウザーにはありません。自動化スクリプトは、ページから見えない JavaScript ワールドで実行されます。 |
| Xvfb | コンテナー内でブラウザーを完全なグラフィカルディスプレイで実行できる仮想フレームバッファーです。物理モニターは必要ありません。ヘッドレスモードは別の検出シグナルとなるため、これは重要です。 |
| PyAutoGUI | OS レベルの実際のマウス操作とキーストロークを生成します。ページには、ユーザーによる信頼された入力として、人間のようなタイミングで届きます。2 つの入力モードを参照してください。 |
| noVNC | Web ベースの VNC クライアントです。自分のブラウザーからブラウザーの動作をリアルタイムで確認できます。ビューアーには、デフォルトで自動操作中のポインターが実際の位置に表示されます。非表示にするには、VNC_SHOW_CURSOR=false を設定してください。 |
| Openbox | 軽量なウィンドウマネージャーです。ポップアップウィンドウ(OAuth ダイアログなど)にタイトルバーとサイズ変更用ハンドルを追加し、通常は小さすぎて操作できないウィンドウを操作できるようにします。メインウィンドウはタイトルバーの下に収まるサイズです。ステルス性への影響はありません。 |
| HTTP API | ポート 8080 で動作する JSON API です。ページの移動、要素のクリック、テキストの入力、スクリーンショットの撮影、タブの管理、Cookie の処理など、あらゆる操作ができます。 |
| MCP サーバー | 同じポートの /mcp で動作する Model Context Protocol サーバーです。AI エージェント(Claude など)は、Streamable HTTP を使用して MCP 経由でブラウザーを直接操作できます。 |
| ffmpeg | Xvfb に対する x11grab で画面を録画します。OS レベルのマウスカーソルを含む、実際にレンダリングされたピクセルをキャプチャします。画面録画を参照してください。 |
インストール済みの拡張機能:uBlock Origin(広告/トラッカー対策)、LocalCDN(CDN によるトラッキングを防止)、ClearURLs(トラッキング用パラメーターを削除)、Consent-O-Matic(Cookie ポップアップを自動処理)。
クイックスタート
docker run -d --name browser \
-p 8080:8080 \
-p 5900:5900 \
psyb0t/stealthy-auto-browse
ポート 8080 は HTTP API、ポート 5900 は VNC ビューアー(http://localhost:5900/)です。
# Navigate
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "goto", "url": "https://example.com"}'
# Get page text
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "get_text"}'
# Click by CSS selector (preferred: fast and reliable)
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "click", "selector": "button#submit"}'
# Screenshot (last resort; prefer get_text and always resize to save tokens)
curl "http://localhost:8080/screenshot/browser?whLargest=512" -o screenshot.png
複数ステップのスクリプトを 1 つのリクエストで実行するには:
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{
"action": "run_script",
"steps": [
{"action": "goto", "url": "https://example.com", "wait_until": "domcontentloaded"},
{"action": "sleep", "duration": 2},
{"action": "get_text", "output_id": "text"},
{"action": "eval", "expression": "document.title", "output_id": "title"}
]
}'
スクリプトモードで使用するものと同じ YAML 形式の "yaml": "..." も指定できます。シングルインスタンスモードでは、サーバーがリクエストを自動的に順番に処理します。複数のスクリプトを並列に送信すると、キューに入ります。
すべてのアクションと API リファレンスについては、docs/api.mdを参照してください。
ナビゲーションには、非表示のブラウザーライブラリーのタイムアウトではなく、アプリケーションが管理する制御を使用します。各試行のデフォルトのタイムアウトは 30 秒で、タイムアウト時に 1 回再試行し、再試行まで 1 秒待機します。ワークフローで別の制限が必要な場合は、goto、refresh、または new_tab に timeout、retry_count、retry_delay を渡してください。retry_count: 0 にすると、再試行は無効になります。制限と再試行の動作については、ナビゲーション制御を参照してください。
2 種類の入力モード
ページとやり取りする方法は 2 つあります。システム入力では PyAutoGUI を使って OS レベルの実際のマウスイベントとキーボードイベントを生成するため、ページには注入の痕跡がない信頼済みイベントが、人間のようなタイミングで届きます。Playwright 入力では CSS セレクターと DOM イベントの注入を使います。こちらのほうが簡単ですが、理論上は行動分析によって検出される可能性があります。ボット対策があるサイトでは、システム入力を使ってください。
システム入力では、人間の操作と同じようにマウスを動かし、文字を入力します。デフォルト値は、公開されている人間の行動データセット(マウスの軌跡には SapiMouse、クリックには Balabit、タイピングには Aalto のキーストローク研究)に合わせて調整されています。
- マウス: Fitts の法則に基づくタイミングのシグマ・ログノーマル曲線軌道を使います。移動の早い段階で速度がピークに達し、約 3 分の 1 の移動ではオーバーシュートと修正が発生し、125 Hz のマウスレートで送信されます。また、手の震えも再現します。
- クリック: 押す前に短い間を置き、ボタンを約 100 ms 押したままにし、ターゲットの内部に着地するようにします。着地点はばらつきがあり、ターゲットの中心そのものにはなりません。
- タイピング: キーの組み合わせに応じたリズムで入力し、すべてのキーを押したままにします。速いタイピストではキーを重ねて押し、大文字の前には Shift を押します。必要に応じてタイプミスを加えますが、必ず修正します。
- スクロール: ホイール操作を 1 ノッチずつ送信します。読書中の間、ポインターの揺れ、ときおりスクロールを戻す動作も再現します。
各コンテナは一貫した 1 人の人物のように動作し、すべてのタイミングはリクエストごとに変更できます。モデルとオプションについては、人間らしい入力を参照してください。行動検出器に対するスコアは、行動検出の結果を参照してください。
詳しい解説と使い方のガイド:docs/stealth.md
クリップボード
set_clipboard と get_clipboard は、Camoufox と noVNC で共有される実際の X11 テキストクリップボードを使用します。ブラウザーでコピーしたテキストは API から読み取ることができ、API で設定したテキストは Ctrl+V で貼り付けられます。値は有効な UTF-8 である必要があり、最大サイズは 1 MiB です。
curl -X POST http://localhost:8080 -H "Content-Type: application/json" \
-d '{"action":"set_clipboard","text":"paste me"}'
curl -X POST http://localhost:8080 -H "Content-Type: application/json" \
-d '{"action":"get_clipboard"}'
どちらの操作も専用の MCP ツールです。クラスター モードでは、1 つのブラウザーインスタンスで両方の操作を実行できるよう、1 回の run_script 呼び出し内で使用してください。API リファレンスを参照してください。
仮想カメラとマイク
テストメディアを読み取り専用で /media にマウントし、VIRTUAL_CAMERA_FILE および/または VIRTUAL_MICROPHONE_FILE を設定します。navigator.mediaDevices.getUserMedia() を呼び出すページには、これらのファイルからキャプチャされたトラックが渡されるため、ホストのハードウェアがなくてもカメラとマイクのテストを実行できます。
docker run -d -p 8080:8080 \
-v ./media:/media:ro \
-e VIRTUAL_CAMERA_FILE=camera.webm \
-e VIRTUAL_MICROPHONE_FILE=microphone.wav \
psyb0t/stealthy-auto-browse
ソースは /media 内に置く必要があります。変更後はブラウザーを再起動してください。仮想ソースが設定されていない種類のリクエストは、ハードウェアにフォールバックせず NotFoundError になります。仮想トラックはソースファイルのネイティブ形式を使用するため、ページ側で互換性のない厳密なメディア制約を要求しないようにしてください。仮想化されるのは getUserMedia() のみで、enumerateDevices() は対象外です。
認可されたテスト中に、取得済みのカメラまたはマイクのトラックを置き換えずにソースを切り替えるには、VIRTUAL_MEDIA_DYNAMIC=true を有効にします。動的モードはデフォルトでオフです。set_virtual_media_source で VIRTUAL_MEDIA_DIR 内にある既存の相対ファイル名を選択するか、upload_virtual_media でサイズ制限内の base64 コンテンツを追加し、必要に応じて有効化します。アップロードのファイル名は、安全で種類に一致するメディア名に限られます。サービスは衝突しない保存用ベース名を生成して返し、既存の名前付きソースを上書きすることはありません。保存または有効化する前に、サービスは ffprobe を使ってデコード済みのアップロードを検査し、要求されたカメラまたはマイクの種類に一致するストリームがあることを確認します。アップロードにはメディアディレクトリへの書き込み権限が必要です。VIRTUAL_MEDIA_UPLOAD_MAX_BYTES のデフォルトは 50 MiB です。ソースの変更中も、既存のページストリームのトラック ID は維持されます。
動的モードで受け付けるのは、設定済みのメディアディレクトリ内にあるファイルのみです。任意のホストパス、リモート URL、WebSocket ストリーム、その他のライブ入力は受け付けません。どちらのアクションにも通常の API 認証が適用されます。AUTH_TOKEN が設定されている場合は、通常どおり Authorization: Bearer <token> ヘッダーを送信してください。アクションの仕様と書き込み可能なボリュームの設定については、docs/api.md#virtual-camera-and-microphone および docs/configuration.md を参照してください。
MCP サーバー
AI エージェントは、同じポート 8080 の /mcp にある Streamable HTTP を介し、Model Context Protocol 経由でブラウザーを操作できます。サーバーは、ナビゲーション、スクリーンショット、クリック、入力、JavaScript の評価、Cookie など、すべてのブラウザーアクションを MCP ツールとして公開します。
認可されたテストフローで、検証ウィジェットが表示された際に人による確認が必要な場合は、detect_challenge を使用してください。このツールは読み取り専用です。ベンダーや場所に関する限定的な証拠とともに、ベストエフォートで absent、present、または unknown の状態を報告しますが、クリック、フレームへの進入、チャレンジの解決は行いません。scroll_into_view: true を渡すと、最初に検出された表示可能なフレームまたはウィジェットがビューポート内に表示され、VNC による引き継ぎができます。ただし、クリックもフォーカスも行いません。クラスター モードでは、run_script のステップとして含めてください。API リファレンスを参照してください。
MCP 互換クライアント(Claude Desktop、Claude Code、カスタムエージェント)を http://localhost:8080/mcp/ に接続して、ブラウジングを開始します。
スタンドアロンモードとクラスター モードの両方で動作します。
エージェント連携
スキルは、.agents/skills/ を読み込むあらゆるエージェント(peen など)で利用でき、以下のクライアントにはネイティブにインストールできます。
Claude Code
claude plugin marketplace add psyb0t/agents
claude plugin install stealthy-auto-browse@psyb0t
Claude Code は stealthy-auto-browse の URL と、認証が有効な場合はトークンの入力を求めます。入力した情報は OS のキーチェーンに保存されます。
Codex
codex plugin marketplace add psyb0t/agents
codex plugin add stealthy-auto-browse@psyb0t
マーケットプレイスからインストールすると、このスキルは $stealthy-auto-browse:stealthy-auto-browse として呼び出されます。また、Codex は .agents/skills/ を含むリポジトリであれば、インストールなしでもスキルを自動的に検出し、単に $stealthy-auto-browse として呼び出します。
OpenClaw
このスキルはリリースのたびに ClawHub に公開されます:
openclaw skills install @psyb0t/stealthy-auto-browse
ローカル stdio で通信する MCP クライアント向けに、@psyb0t/stealthy-auto-browse プラグインがサービスの /mcp エンドポイントへのブリッジとして機能します:
openclaw plugins install clawhub:@psyb0t/stealthy-auto-browse
次に、STEALTHY_AUTO_BROWSE_URL を設定します(サーバーで認証が必要な場合は AUTH_TOKEN も設定します)。
スクリプトモード
YAML スクリプトをコンテナにパイプで渡すと、標準出力に JSON の結果が出力され、コンテナが終了します。HTTP サーバーは不要です。CI、cron ジョブ、単発のスクレイピングに適しています。
cat my-script.yaml | docker run --rm -i \
-e TARGET_URL=https://example.com \
psyb0t/stealthy-auto-browse --script > results.json
詳細なドキュメント:docs/script-mode.md
スクリプトモードでは、明示的な if 分岐と、回数に上限のある repeat および while ループにも対応しています。条件では、要素、表示テキスト、URL、JavaScript のブール値、以前の output_id 値を確認できます。詳しくは制御フローのリファレンスをご覧ください。
ページローダー
YAML ファイルで URL パターンとアクションシーケンスを定義します。/loaders にマウントすると、goto がパターンに一致するたびにローダーが自動的に実行されます。ポップアップを削除し、コンテンツの読み込みを待ち、ページをクリーンアップします。HTTP API 向けの Greasemonkey です。
詳細なドキュメント:docs/page-loaders.md
画面録画
マウスカーソルを表示したまま、ブラウザーを MP4 形式で録画します。ffmpeg の x11grab で Xvfb を録画し、マウントされた /recordings ボリュームに書き込みます。モードは 3 種類です:window(Camoufox ウィンドウ全体)、viewport(録画開始時に測定した mozInnerScreenX/Y に基づき、ページ位置で切り抜いたブラウザー表示領域)、desktop(Xvfb 画面全体)。停止時にスラッグを指定するため、実行完了後にファイル名を付けられます。パストラバーサル、ファイル名の衝突、クラッシュへの対策も施されています。
mkdir -p ./recordings
docker run -d -p 8080:8080 -v ./recordings:/recordings psyb0t/stealthy-auto-browse
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "start_recording", "mode": "viewport", "fps": 20}'
# … do stuff …
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "stop_recording", "slug": "my-flow"}'
# → ./recordings/my-flow.mp4
run_script 内でも使用できます(クラスター�ードに対応:開始と停止は同じインスタンスに届くよう、同じ run_script 内に記述する必要があります)。アクション一覧、スクリプトモードの例、補足については、docs/api.md#screen-recordingをご覧ください。
クラスターモード
リクエストキュー、スティッキーセッション、Redis による Cookie 同期を備えた HAProxy の背後で、複数のブラウザーインスタンスを実行します(デフォルトは 5。NUM_REPLICAS で設定可能)。compose ファイルと HAProxy 設定をダウンロードして、起動します:
curl -LO https://raw.githubusercontent.com/psyb0t/docker-stealthy-auto-browse/main/docker-compose.cluster.yml
docker compose -f docker-compose.cluster.yml up -d
どのインスタンスで設定した Cookie も、Redis PubSub を介して即座にほかのすべてのインスタンスに反映されます。一度ログインすれば、フリート全体で認証済みになります。
各ブラウザーのメモリ上限はデフォルトで 5GB です。フリートやディスプレイ解像度に応じて別の上限が必要な場合は、BROWSER_MEMORY_LIMIT と BROWSER_MEMORY_RESERVATION を設定してください。詳しくはクラスターモードをご覧ください。
スクリプトのみの実行制限(v1.0.0 以降): NUM_REPLICAS > 1 の場合、HTTP API と MCP サーバーは run_script のみ(および ping と sleep)に制限されます。インスタンス間のルーティングによる古いコンテンツの不具合を防ぐため、個別のアクションは拒否されます。すべてのアクションは引き続き run_script 内のステップとして使用できます。
詳細なドキュメント:docs/cluster-mode.md
認証
AUTH_TOKEN を設定すると、/health を除くすべてのリクエストで Bearer トークンが必須になります:
docker run -d -p 8080:8080 -e AUTH_TOKEN=your-token-here psyb0t/stealthy-auto-browse
Authorization ヘッダーでトークンを渡します:
# Header
curl -H "Authorization: Bearer your-token-here" http://localhost:8080 ...
例
すぐに使えるスクリプトについては、.agents/skills/stealthy-auto-browse/scripts/をご覧ください:
websearch.py:構造化された結果と AI による概要抽出に対応した、複数エンジン(Brave、Google、Bing)による並列ウェブ検索です。各検索結果のタイトル、URL、スニペットを含む JSON を出力します。
設定
環境変数の一覧、プロキシ設定(動作するプライベートな pr0xteus HTTP プロキシの例を含む)、永続プロファイル、ブラウザー拡張機能、VNC アクセスについては、docs/configuration.mdをご覧ください。
開発
Docker のみが開発時の依存関係です。Makefile はローカルのブラウザベースイメージをビルドした後、使い捨ての開発用コンテナ内でリンティング、テスト、セキュリティツールを実行します。Docker ソケットを受け取るのは、独自のブラウザコンテナとフィクスチャコンテナを起動する完全なテストターゲットのみです。
make build
make lint
make test
make test-real
make sec
make sec は GitHub Security 用の sec.sarif を書き出します。リリースをブロックすることなく、検出結果を報告します。コマンド一覧は make help で確認できます。
make test-real は公開サイトに対してオプトインのライブチェックを実行するため、外部ネットワークへのアクセスが必要で、決定論的なデフォルトのテストスイートでは実行されません。liarjs.dev ではフィンガープリントの一貫性を、deviceandbrowserinfo.com のログインテスト と FCaptcha のデモ では、チェックボックスモードと非表示モードで入力動作をチェックします。各動作チェックでは、同じ IP から人間化された入力、Playwright の DOM 入力、PyAutoGUI による生の入力を使って同じタスクを実行します。人間化された入力は合格し、両方のロボット入力は不合格になるか、スコアが低くなる必要があります。これにより、サービスが実際に動作を評価していることを確認できます。
ボット検出の結果
以下は実際に観測された結果であり、各サービスのすべてのバージョンで 同じ結果になることを保証するものではありません。使用する予定の正確なイメージ、プロキシ、タイムゾーン、 対象のフローでテストしてください。
| サービス | 観測結果 | チェック項目 |
|---|---|---|
| CreepJS | 合格 | Canvas/WebGL フィンガープリントの一貫性、偽装の検出、ワーカーの比較 |
| liarjs.dev | 82/100、重大な検出結果なし | フォント、Canvas、ワーカー、GPU、ネットワーク、動作の一貫性 |
| BrowserScan | 合格 | WebDriver フラグ、CDP シグナル、navigator プロパティ |
| Pixelscan | 合格 | フィンガープリントの整合性、タイムゾーンと IP の一致、WebRTC リーク |
| Cloudflare | 合格 | チャレンジページ、Turnstile、ボット管理 |
| SannySoft | 合格 | Intoli とフィンガープリントスキャナーのテスト |
| Incolumitas | 合格 | 最新の検出手法 |
| Rebrowser | 合格 | CDP リーク検出、webdriver、ビューポート分析 |
| BrowserLeaks WebRTC | 合格 | WebRTC IP リーク検出 |
| DeviceAndBrowserInfo | 合格 | 19 項目のチェックがすべて緑色、「あなたは人間です!」 |
| IpHey | 合格 | 「信頼できる」評価 |
| Fingerprint.com | 合格 | 通常の Firefox として識別され、ボットのフラグなし |
動作する理由:docs/stealth.md
行動検知の結果
クリーンなフィンガープリントは、ブラウザーが何であるかを示します。行動検知器は、ポインターの移動、キーやボタンを押し続ける時間、ホイールの回転など、ブラウザーの動作を監視します。以下の各チェックでは、同じコンテナーと同じ IP から同じタスクを3通りの方法で実行するため、フィンガープリントとネットワークは同一で、入力だけが異なります。
| チェック | 人間らしくしたシステム入力 | Playwright の DOM 入力 | 生の PyAutoGUI |
|---|---|---|---|
| DeviceAndBrowserInfo のログインテスト | 人間 | ボット | ボット |
| FCaptcha のチェックボックス | 認証済み | 失敗 | 失敗 |
| FCaptcha の不可視リスクスコア(低いほど良好) | 0.06、許可 | 0.60、ブロック | 0.22、許可 |
| motion-attestation と Gaitcha:マウス、タイピング、スクロール | 合格 | 未実行 | 検知 |
生の PyAutoGUI は同じ信頼された OS レベルのイベントを送信しますが、移動は直線的で瞬時に行われ、押し続ける時間はゼロです。ホスト型チェックのうち2つはこれを明確に検知し、残る1つもリスクを約4倍高く評価します。信頼されたイベントだけでは不十分です。合格するのは、人間らしいタイミングです。
ホスト型の結果は make test-real で確認されています。このテストは毎回このパターンを検証します。人間らしくした実行は合格し、2つのロボット的な実行はいずれも失敗するか、明らかに悪いスコアになる必要があります。オフラインの検知器はローカルのプローブページに対して make test のたびに実行され、各チェックでも検知されるべきロボット的なセッションを実行します。フィンガープリントの結果と同様に、ホスト型のスコアはサービスのバージョン、ネットワークの出口、タイムゾーンによって異なります。
ライセンス
WTFPL(Do What The Fuck You Want To Public License)
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。