browser-gateway
Allows the gateway to route and manage browser sessions hosted in Docker containers, providing a scalable infrastructure for browser automation with health monitoring and failover.
Provides a compatible WebSocket gateway for Puppeteer, allowing AI agents to connect to and control browser instances via a centralized proxy with load balancing.
Overview
One endpoint. Multiple providers. Automatic failover when one is saturated or goes down.
Your app connects to ws://gateway:9500/v1/connect. The gateway picks the best available provider based on health, capacity, and your routing strategy. Providers can be cloud CDP services, Docker containers, or local Chrome instances.
Related MCP server: BrowserMCP
Dashboard
A web dashboard ships with every install. Open http://localhost:9500/web after starting the gateway.
Overview. Active sessions, queue depth, provider health, connection endpoint, and a copy-paste quickstart for Puppeteer, Playwright, Stagehand, browser-use, and raw CDP.
REST API. Run screenshot, content extraction, and structured scraping endpoints from a form-driven UI, with profile selection and parameter reference inline.
Playground. Drive any provider live from the browser. Pick a provider and profile, type into the canvas as if it were a local browser, and watch the remote session in real time.
Features
Routing & reliability
Automatic failover - the next provider takes over the instant one fails, no client changes
Five load-balancing strategies - priority chain, round-robin, least-connections, latency-optimized, weighted
Per-provider concurrency limits - the gateway enforces
maxConcurrenton every backendRequest queue - connections wait when every provider is saturated instead of failing immediately
Cooldown - failing providers are skipped and recover automatically after a TTL
Health checks - periodic connectivity probes mark providers unhealthy before clients hit them
Graceful shutdown - active sessions drain cleanly on SIGTERM and SIGINT
Session reconnect - dropped clients resume against the same provider with cookies and page state intact
Webhooks - fire on provider down, recover, and queue-overflow events
REST API
Screenshot -
POST /v1/screenshotreturns any URL as PNG or JPEG, full-page or scoped to a selectorContent extraction -
POST /v1/contentreturns markdown, plain text, HTML, or a cleaned articleScrape -
POST /v1/scrapeextracts structured data via CSS selectors or full-page formatsPooled sessions - browser connections are reused across requests, like a database pool
Automatic retry - failed requests retry against a fresh page
Profiles — persistent browser state
Survive across sessions - cookies,
localStorage,sessionStorage, andIndexedDBare captured on disconnect and replayed on the next connect with the same idOne-line opt-in - add
?profile=acmeto the WebSocket URL, the rest is automaticEncrypted at rest - AES-256-GCM with envelope encryption, anti-swap binding, and a scrypt-derived KEK
Provider-agnostic - state is captured at the CDP level, so it replays against any provider
Per-profile locking - concurrent connects to the same id return HTTP 409 to prevent corruption
Export and import - encrypted
.bgpblobs are portable between gateway installsOne-click enable - the dashboard wizard generates a strong key in your browser and writes it to config
See the Profiles docs for the full guide, security model, REST endpoints, and limitations.
Session replay — see what the agent saw
Frame-accurate visual record of every routed session, captured via CDP
Page.startScreencastZero injection - no script runs inside the customer page, capture is fully out-of-band
Provider-agnostic - works with any backend that supports page screencast
Dashboard player - scrub through the recorded frames, switch between captured browser targets
Retention controls - configurable horizon, per-session byte cap, daily cleanup
See the Replays docs for the storage layout, REST endpoints, and tuning knobs.
MCP server for AI agents
Eight browser tools - navigate, snapshot, screenshot, viewport, interact, evaluate, close, status
Zero config - auto-detects Chrome and launches it on first tool use
Concurrent sessions - every agent gets its own browser, no shared state
Raw CDP - no Playwright or Puppeteer dependency
Compatible - Claude Code, Cursor, and any MCP-compatible client
Management
Dashboard - manage providers, watch sessions, and edit config from the browser
Provider CRUD - add, edit, delete, and test providers from the dashboard or API
Config editor - edit
gateway.ymlin-browser with syntax highlighting and validationAuth - token-based, with a secure HttpOnly cookie for the dashboard
Protocol-agnostic - works with Playwright, Puppeteer, and any WebSocket protocol
Quick Start
As a WebSocket Proxy (for applications)
npm install -g browser-gatewayCreate gateway.yml:
version: 1
providers:
primary:
url: wss://provider.example.com?token=${PROVIDER_TOKEN}
limits:
maxConcurrent: 5
priority: 1
fallback:
url: ws://my-playwright-server:4000
limits:
maxConcurrent: 10
priority: 2browser-gateway serveConnect from your app:
// For CDP providers
const browser = await chromium.connectOverCDP('ws://localhost:9500/v1/connect');
// For Playwright run-server providers
const browser = await chromium.connect('ws://localhost:9500/v1/connect');Or use the REST API — no WebSocket management needed:
# Screenshot
curl -X POST http://localhost:9500/v1/screenshot \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}' --output screenshot.png
# Extract content as markdown
curl -X POST http://localhost:9500/v1/content \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "formats": ["markdown"]}'Dashboard at http://localhost:9500/web.
As an MCP Server (for AI agents)
Add to your Claude Code or Cursor config:
{
"mcpServers": {
"browser-gateway": {
"command": "npx",
"args": ["browser-gateway", "mcp"]
}
}
}No config files needed. The agent gets navigate, snapshot, screenshot, click, type, and evaluate tools through the gateway's routing layer.
See the MCP docs for all options.
Authentication
Set BG_TOKEN to require a token (or put it in a .env file):
BG_TOKEN=my-secret-token browser-gateway serveWebSocket clients pass the token as
?token=query paramAPI clients use
Authorization: Bearer <token>headerDashboard shows a login form, sets a secure HttpOnly cookie
Health endpoint (
/health) is always public
CLI
# Proxy server
browser-gateway serve # Start the gateway + dashboard
browser-gateway serve --port 8080 # Custom port
browser-gateway serve --config path.yml # Custom config
# MCP server for AI agents
browser-gateway mcp # Auto-detect Chrome, zero config
browser-gateway mcp --headless # Headless mode (for CI/Docker)
browser-gateway mcp --cdp-endpoint ws:// # Connect to existing browser
browser-gateway mcp --config gateway.yml # Multi-provider with failover
# Utilities
browser-gateway check # Test provider connectivity
browser-gateway version # Print version
browser-gateway help # Show helpAPI
Endpoint | Method | Description |
| WebSocket | Connect to a browser (the core feature) |
| POST | Take a screenshot of any URL (docs) |
| POST | Extract page content as markdown, text, or HTML (docs) |
| POST | Extract data via CSS selectors or full-page formats (docs) |
| GET | Gateway health + provider status + pool status |
| GET | Active sessions |
| GET/POST | List or add providers |
| PUT/DELETE | Update or remove a provider |
| POST | Test provider connectivity |
| GET/PUT | Read or save config |
| POST | Validate YAML without saving |
| POST | MCP Streamable HTTP endpoint |
| GET | CDP discovery (for browser-use, Playwright, Stagehand) |
| GET | Health check |
Docker
Recommended: Docker Compose. The bundled docker-compose.yml mounts a named volume for state and a read-only gateway.yml from the host.
# Drop your gateway.yml next to docker-compose.yml, then:
docker compose up -dPlain docker run:
docker run -d \
-p 9500:9500 \
-v bg_data:/data \
-v ./gateway.yml:/app/gateway.yml:ro \
-e PROVIDER_TOKEN=xxx \
ghcr.io/browser-gateway/server:latestPersistence
Everything the gateway writes to disk lives under a single directory, BG_DATA_DIR (defaults to /data inside the image). Mount that as a named volume or a bind mount and all state survives container restarts and image upgrades. Today it contains:
profiles/— encrypted profile blobs (when profiles are enabled)
Future versions may add more subdirectories under the same root (cooldown state, session snapshots, captures). Mounting BG_DATA_DIR as one volume keeps every subsystem persistent without follow-up config changes.
Upgrades
State lives in the volume, code lives in the image. Pull the new image, recreate the container — no data lost:
docker compose pull
docker compose up -dThe container reads the same BG_DATA_DIR and the same gateway.yml. Profile blobs are versioned and the gateway reads older formats transparently.
Image tags
Tag | Updated on |
| published manually after a release |
| always points at the newest version |
Images are multi-arch (linux/amd64, linux/arm64), signed with Sigstore build provenance, and ship an SBOM. Verify with the GitHub CLI:
gh attestation verify oci://ghcr.io/browser-gateway/server:0.3.0 \
--repo browser-gateway/browser-gatewayHow It Works
Sessions without profile / recording / observability (the default) take the byte-pipe fast lane:
Client connects to
ws://gateway:9500/v1/connectGateway selects a provider using your routing strategy
Gateway opens a raw TCP connection to the provider
HTTP upgrade forwarded, provider responds with
101 Switching ProtocolsBidirectional TCP pipe:
client <-> gateway <-> providerAll WebSocket messages forwarded transparently (never parsed or modified)
On disconnect: session cleaned up, slot released, metrics updated
If all providers full: connection waits in a queue until a slot opens
Sessions with profile inject, session recording, live view, or observability (e.g. ?profile=X, ?session_record=true, /v1/live) run through a CDP-aware pipeline instead — one WebSocket per session, N plugins observing the wire. Same routing + failover, byte-perfect passthrough at rest, plugins only fire when their feature is requested. Architecture + plugin-authoring guide: docs/PIPELINE.md.
Self-hosted provider: browserserve
browserserve is the stack's own self-hosted browser server: one container that hands out isolated Chrome sessions over CDP. Add it like any other provider:
providers:
browserserve:
url: ws://your-host:9222
cloud-provider:
url: <websocket-url-with-auth>
priority: 2Because the gateway controls that runtime, a browserserve provider is auto-detected and unlocks two things no external provider gets:
Auto capacity. You do not set
maxConcurrent. browserserve measures its host (memory, thread, and CPU limits) and advertises a safe ceiling, which the gateway adopts. The dashboard shows it as(auto).Multiple profiles from one slot. A browserserve provider can serve any profile, switching safely because every session is a fresh browser with no shared state. External providers stay single-profile-pinned, since reusing a browser leaks cookies and storage between profiles.
A common shape: browserserve as the primary provider on your own hardware, with a cloud provider at a lower priority for failover.
Works With
browser-gateway is compatible with existing browser tools. Just pass the gateway URL — it auto-resolves via /json/version.
AI Agent Frameworks:
# browser-use (Python) — HTTP URL auto-resolves
BrowserSession(cdp_url="http://localhost:9500")// Stagehand (TypeScript)
new Stagehand({ env: "LOCAL", localBrowserLaunchOptions: { cdpUrl: "http://localhost:9500" } })Playwright MCP (all 70 Playwright tools through gateway routing):
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--cdp-endpoint", "http://localhost:9500"]
}
}
}Puppeteer / Playwright:
// Playwright — HTTP or WebSocket
const browser = await chromium.connectOverCDP("http://localhost:9500");
// Puppeteer — WebSocket
const browser = await puppeteer.connect({ browserWSEndpoint: "ws://localhost:9500/v1/connect" });Documentation
Full docs live at docs.browsergateway.com.
Integrations — Playwright, Puppeteer, browser-use, Stagehand, Playwright MCP
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
License
MIT - see LICENSE.
Links
Contact
Questions, security reports, or partnership inquiries: hello@browsergateway.com.
Maintained by Monostellar Labs.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityFmaintenanceA server that leverages Playwright for automated browser testing and integrates with Cloudflare Workers, enabling AI assistants to control web browsers for navigation, interaction, and screenshots.224,588,713256Apache 2.0
- AlicenseNot gradedqualityDmaintenanceRemote browser instances for your AI agents. Reliably complete any browser-based task at scale. Fully-control agentic browsers that spin up in seconds.1340Apache 2.0
- AlicenseAqualityNot gradedmaintenanceEnables browser automation through Playwright using accessibility tree snapshots instead of screenshots. Supports web scraping, form interactions, testing, and connecting to existing browser sessions with logged-in accounts.14237,6235
- AlicenseCqualityDmaintenanceHosted Playwright browser automation for AI agents. Returns accessibility trees instead of screenshots, cutting token usage by 77%. Navigate, interact, extract structured data, and take screenshots — all via MCP. Zero infrastructure, credit-based pricing.6108MIT
Related MCP Connectors
AI-powered browser automation — navigate, click, fill forms, and extract data from any website.
Reliable web access for AI agents: smart HTTP, rotating proxies, and full-browser rendering.
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/browser-gateway/browser-gateway'
If you have feedback or need assistance with the MCP directory API, please join our Discord server