browser-gateway

Supported Providers

browser-gateway works with any WebSocket endpoint. If your browser provider exposes a WebSocket URL, it works with the gateway.

browser-gateway works with any WebSocket endpoint. If your browser provider exposes a WebSocket URL, it works with the gateway.

How Providers Work

Each provider is a WebSocket URL. The gateway forwards bytes transparently and doesn't parse what's behind it. You configure the URL (with any auth params baked in), set connection limits, and assign a priority.

providers:
  my-provider:
    url: <websocket-url-with-auth>
    limits:
      maxConcurrent: <number>
    priority: <number>

Provider Types

Remote browser services (cloud)

Cloud providers typically give you a WebSocket URL with an API key:

providers:
  cloud-provider:
    url: wss://provider.example.com?token=${API_TOKEN}
    limits:
      maxConcurrent: 5
    priority: 1

Self-hosted Playwright

Run your own Playwright server:

npx playwright run-server --port 4000 --host 0.0.0.0

Or via Docker:

docker run -d -p 4000:3000 --shm-size=1gb \
  mcr.microsoft.com/playwright:v1.50.1-noble \
  /bin/sh -c "npx -y playwright@1.50.1 run-server --port 3000 --host 0.0.0.0"

Config:

providers:
  my-playwright:
    url: ws://playwright-host:4000
    limits:
      maxConcurrent: 10
    priority: 1

Important: Playwright client and server versions must match exactly.

Raw Chrome (--remote-debugging-port)

Chrome/Chromium with remote debugging enabled:

google-chrome --remote-debugging-port=9222 --headless --no-sandbox

Get the WebSocket URL:

curl http://localhost:9222/json/version
# Look for "webSocketDebuggerUrl"

Config:

providers:
  my-chrome:
    url: http://chrome-host:9222       # Auto-discovers the WebSocket endpoint
    limits:
      maxConcurrent: 1
    priority: 1

Use http:// for Chrome CDP, the gateway auto-discovers the full WebSocket path via /json/version. You can also use the full ws:// URL if you already have it.

Connection Modes

The gateway is protocol-agnostic - it forwards raw bytes without parsing. However, your client needs to use the correct connection method for the provider type:

Provider TypeClient Method
Playwright run-serverchromium.connect(wsEndpoint)
Chrome CDP endpointschromium.connectOverCDP(wsEndpoint)
Puppeteer (any)puppeteer.connect({ browserWSEndpoint })

Multiple Providers

Mix any number of providers with different priorities:

providers:
  primary:
    url: wss://provider-a.example.com?key=${KEY_A}
    limits:
      maxConcurrent: 5
    priority: 1

  overflow:
    url: ws://my-playwright-server:4000
    limits:
      maxConcurrent: 20
    priority: 2

  emergency:
    url: wss://provider-b.example.com?key=${KEY_B}
    limits:
      maxConcurrent: 50
    priority: 3

The gateway tries them in priority order. If the primary is full or down, traffic routes to the next available provider automatically.

Tips

  • Auth goes in the URL - Most providers use query params for auth (?token=xxx, ?apiKey=xxx). Put these directly in the URL. Use ${ENV_VAR} references for secrets.
  • Set realistic limits - Check your provider's actual concurrency limits and set maxConcurrent accordingly. The gateway enforces these locally to avoid hitting provider rate limits.
  • Chrome CDP needs the full path - Chrome's CDP URL includes a UUID that changes on restart. You'll need to update the config or fetch it dynamically.

On this page