{
  "markdown": "<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/browser-gateway/browser-gateway/main/docs/assets/logo.png\" alt=\"browser-gateway\" width=\"120\" />\n</p>\n\n<h1 align=\"center\">browser-gateway</h1>\n\n<p align=\"center\">\n  <strong>OpenRouter for cloud browsers.</strong>\n  <br />\n  One endpoint that routes across every browser provider you use: automatic failover, persistent profiles, session replay, REST API, MCP server, dashboard.\n  <br />\n  Works unchanged with Puppeteer, Playwright, Stagehand, browser-use, and any MCP client.\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/browser-gateway\"><img src=\"https://img.shields.io/npm/v/browser-gateway?style=flat-square&logo=npm&logoColor=white\" alt=\"npm version\" /></a>\n  <a href=\"https://www.npmjs.com/package/browser-gateway\"><img src=\"https://img.shields.io/npm/dm/browser-gateway?style=flat-square&label=downloads\" alt=\"npm downloads\" /></a>\n  <a href=\"./LICENSE\"><img src=\"https://img.shields.io/npm/l/browser-gateway?style=flat-square\" alt=\"MIT license\" /></a>\n  <a href=\"https://nodejs.org\"><img src=\"https://img.shields.io/node/v/browser-gateway?style=flat-square&logo=nodedotjs&logoColor=white\" alt=\"Node.js\" /></a>\n  <a href=\"https://github.com/browser-gateway/browser-gateway\"><img src=\"https://img.shields.io/github/stars/browser-gateway/browser-gateway?style=flat-square&logo=github&logoColor=white\" alt=\"GitHub stars\" /></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://railway.com/new/template/browser-gateway?utm_medium=integration&amp;utm_source=button&amp;utm_campaign=browser-gateway\"><img src=\"https://railway.com/button.svg\" alt=\"Deploy on Railway\" height=\"32\" /></a>\n  &nbsp;\n  <a href=\"https://render.com/deploy?repo=https://github.com/browser-gateway/browser-gateway\"><img src=\"https://render.com/images/deploy-to-render-button.svg\" alt=\"Deploy to Render\" height=\"32\" /></a>\n  &nbsp;\n  <a href=\"https://cloud.digitalocean.com/apps/new?repo=https://github.com/browser-gateway/browser-gateway/tree/main\"><img src=\"https://www.deploytodo.com/do-btn-blue.svg\" alt=\"Deploy to DigitalOcean\" height=\"32\" /></a>\n  &nbsp;\n  <a href=\"https://app.koyeb.com/deploy?type=docker&amp;name=browser-gateway&amp;image=ghcr.io/browser-gateway/server:latest&amp;ports=9500;http;/&amp;env%5BBG_DATA_DIR%5D=/data\"><img src=\"https://www.koyeb.com/static/images/deploy/button.svg\" alt=\"Deploy to Koyeb\" height=\"32\" /></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://browsergateway.com\">Website</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/quickstart\">Quick start</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/mcp\">MCP</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/profiles\">Profiles</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/replays\">Replays</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/rest-api\">REST API</a>\n  &nbsp;·&nbsp;\n  <a href=\"https://docs.browsergateway.com/dashboard\">Dashboard</a>\n</p>\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/browser-gateway/browser-gateway/main/docs/assets/routing.gif\" alt=\"browser-gateway routes traffic across multiple browser providers, filling them by priority and failing over when one is saturated\" width=\"720\" />\n</p>\n\n---\n\n## Overview\n\nOne endpoint. Multiple providers. Automatic failover when one is saturated or goes down.\n\nYour 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.\n\n---\n\n## Dashboard\n\nA web dashboard ships with every install. Open `http://localhost:9500/web` after starting the gateway.\n\n**Overview.** Active sessions, queue depth, provider health, connection endpoint, and a copy-paste quickstart for Puppeteer, Playwright, Stagehand, browser-use, and raw CDP.\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/browser-gateway/browser-gateway/main/docs/assets/overview.png\" alt=\"Dashboard overview page showing active sessions, queue depth, provider health, masked connection endpoint, and a tabbed quickstart with Puppeteer code\" width=\"860\" />\n</p>\n\n**REST API.** Run screenshot, content extraction, and structured scraping endpoints from a form-driven UI, with profile selection and parameter reference inline.\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/browser-gateway/browser-gateway/main/docs/assets/api.png\" alt=\"REST API page in the dashboard with three tabs (screenshot, content, scrape) and a form to capture a screenshot of a target URL with format and profile options\" width=\"860\" />\n</p>\n\n**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.\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/browser-gateway/browser-gateway/main/docs/assets/playground.jpg\" alt=\"Live playground page streaming a remote Chrome session showing yahoo.com loaded inside the dashboard canvas\" width=\"860\" />\n</p>\n\n---\n\n## Features\n\n### Routing & reliability\n\n- **Automatic failover** - the next provider takes over the instant one fails, no client changes\n- **Five load-balancing strategies** - priority chain, round-robin, least-connections, latency-optimized, weighted\n- **Per-provider concurrency limits** - the gateway enforces `maxConcurrent` on every backend\n- **Request queue** - connections wait when every provider is saturated instead of failing immediately\n- **Cooldown** - failing providers are skipped and recover automatically after a TTL\n- **Health checks** - periodic connectivity probes mark providers unhealthy before clients hit them\n- **Graceful shutdown** - active sessions drain cleanly on SIGTERM and SIGINT\n- **Session reconnect** - dropped clients resume against the same provider with cookies and page state intact\n- **Webhooks** - fire on provider down, recover, and queue-overflow events\n\n### REST API\n\n- **Screenshot** - `POST /v1/screenshot` returns any URL as PNG or JPEG, full-page or scoped to a selector\n- **Content extraction** - `POST /v1/content` returns markdown, plain text, HTML, or a cleaned article\n- **Scrape** - `POST /v1/scrape` extracts structured data via CSS selectors or full-page formats\n- **Pooled sessions** - browser connections are reused across requests, like a database pool\n- **Automatic retry** - failed requests retry against a fresh page\n\n### Profiles — persistent browser state\n\n- **Survive across sessions** - cookies, `localStorage`, `sessionStorage`, and `IndexedDB` are captured on disconnect and replayed on the next connect with the same id\n- **One-line opt-in** - add `?profile=acme` to the WebSocket URL, the rest is automatic\n- **Encrypted at rest** - AES-256-GCM with envelope encryption, anti-swap binding, and a scrypt-derived KEK\n- **Provider-agnostic** - state is captured at the CDP level, so it replays against any provider\n- **Per-profile locking** - concurrent connects to the same id return HTTP 409 to prevent corruption\n- **Export and import** - encrypted `.bgp` blobs are portable between gateway installs\n- **One-click enable** - the dashboard wizard generates a strong key in your browser and writes it to config\n\nSee the [Profiles docs](https://docs.browsergateway.com/profiles) for the full guide, security model, REST endpoints, and limitations.\n\n### Session replay — see what the agent saw\n\n- **Frame-accurate visual record** of every routed session, captured via CDP `Page.startScreencast`\n- **Zero injection** - no script runs inside the customer page, capture is fully out-of-band\n- **Provider-agnostic** - works with any backend that supports page screencast\n- **Dashboard player** - scrub through the recorded frames, switch between captured browser targets\n- **Retention controls** - configurable horizon, per-session byte cap, daily cleanup\n\nSee the [Replays docs](https://docs.browsergateway.com/replays) for the storage layout, REST endpoints, and tuning knobs.\n\n### MCP server for AI agents\n\n- **Eight browser tools** - navigate, snapshot, screenshot, viewport, interact, evaluate, close, status\n- **Zero config** - auto-detects Chrome and launches it on first tool use\n- **Concurrent sessions** - every agent gets its own browser, no shared state\n- **Raw CDP** - no Playwright or Puppeteer dependency\n- **Compatible** - Claude Code, Cursor, and any MCP-compatible client\n\n### Management\n\n- **Dashboard** - manage providers, watch sessions, and edit config from the browser\n- **Provider CRUD** - add, edit, delete, and test providers from the dashboard or API\n- **Config editor** - edit `gateway.yml` in-browser with syntax highlighting and validation\n- **Auth** - token-based, with a secure HttpOnly cookie for the dashboard\n- **Protocol-agnostic** - works with Playwright, Puppeteer, and any WebSocket protocol\n\n---\n\n## Quick Start\n\n### As a WebSocket Proxy (for applications)\n\n```bash\nnpm install -g browser-gateway\n```\n\nCreate `gateway.yml`:\n\n```yaml\nversion: 1\n\nproviders:\n  primary:\n    url: wss://provider.example.com?token=${PROVIDER_TOKEN}\n    limits:\n      maxConcurrent: 5\n    priority: 1\n\n  fallback:\n    url: ws://my-playwright-server:4000\n    limits:\n      maxConcurrent: 10\n    priority: 2\n```\n\n```bash\nbrowser-gateway serve\n```\n\nConnect from your app:\n\n```typescript\n// For CDP providers\nconst browser = await chromium.connectOverCDP('ws://localhost:9500/v1/connect');\n\n// For Playwright run-server providers\nconst browser = await chromium.connect('ws://localhost:9500/v1/connect');\n```\n\nOr use the REST API — no WebSocket management needed:\n\n```bash\n# Screenshot\ncurl -X POST http://localhost:9500/v1/screenshot \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\"}' --output screenshot.png\n\n# Extract content as markdown\ncurl -X POST http://localhost:9500/v1/content \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"formats\": [\"markdown\"]}'\n```\n\nDashboard at `http://localhost:9500/web`.\n\n### As an MCP Server (for AI agents)\n\nAdd to your Claude Code or Cursor config:\n\n```json\n{\n  \"mcpServers\": {\n    \"browser-gateway\": {\n      \"command\": \"npx\",\n      \"args\": [\"browser-gateway\", \"mcp\"]\n    }\n  }\n}\n```\n\nNo config files needed. The agent gets navigate, snapshot, screenshot, click, type, and evaluate tools through the gateway's routing layer.\n\nSee the [MCP docs](https://docs.browsergateway.com/mcp) for all options.\n\n---\n\n## Authentication\n\nSet `BG_TOKEN` to require a token (or put it in a `.env` file):\n\n```bash\nBG_TOKEN=my-secret-token browser-gateway serve\n```\n\n- **WebSocket clients** pass the token as `?token=` query param\n- **API clients** use `Authorization: Bearer <token>` header\n- **Dashboard** shows a login form, sets a secure HttpOnly cookie\n- **Health endpoint** (`/health`) is always public\n\n---\n\n## CLI\n\n```bash\n# Proxy server\nbrowser-gateway serve                    # Start the gateway + dashboard\nbrowser-gateway serve --port 8080        # Custom port\nbrowser-gateway serve --config path.yml  # Custom config\n\n# MCP server for AI agents\nbrowser-gateway mcp                      # Auto-detect Chrome, zero config\nbrowser-gateway mcp --headless           # Headless mode (for CI/Docker)\nbrowser-gateway mcp --cdp-endpoint ws:// # Connect to existing browser\nbrowser-gateway mcp --config gateway.yml # Multi-provider with failover\n\n# Utilities\nbrowser-gateway check                    # Test provider connectivity\nbrowser-gateway version                  # Print version\nbrowser-gateway help                     # Show help\n```\n\n---\n\n## API\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/v1/connect` | WebSocket | Connect to a browser (the core feature) |\n| `/v1/screenshot` | POST | Take a screenshot of any URL ([docs](https://docs.browsergateway.com/rest-api)) |\n| `/v1/content` | POST | Extract page content as markdown, text, or HTML ([docs](https://docs.browsergateway.com/rest-api)) |\n| `/v1/scrape` | POST | Extract data via CSS selectors or full-page formats ([docs](https://docs.browsergateway.com/rest-api)) |\n| `/v1/status` | GET | Gateway health + provider status + pool status |\n| `/v1/sessions` | GET | Active sessions |\n| `/v1/providers` | GET/POST | List or add providers |\n| `/v1/providers/:id` | PUT/DELETE | Update or remove a provider |\n| `/v1/providers/:id/test` | POST | Test provider connectivity |\n| `/v1/config` | GET/PUT | Read or save config |\n| `/v1/config/validate` | POST | Validate YAML without saving |\n| `/mcp` | POST | MCP Streamable HTTP endpoint |\n| `/json/version` | GET | CDP discovery (for browser-use, Playwright, Stagehand) |\n| `/health` | GET | Health check |\n\n---\n\n## Docker\n\nRecommended: Docker Compose. The bundled `docker-compose.yml` mounts a named volume for state and a read-only `gateway.yml` from the host.\n\n```bash\n# Drop your gateway.yml next to docker-compose.yml, then:\ndocker compose up -d\n```\n\nPlain `docker run`:\n\n```bash\ndocker run -d \\\n  -p 9500:9500 \\\n  -v bg_data:/data \\\n  -v ./gateway.yml:/app/gateway.yml:ro \\\n  -e PROVIDER_TOKEN=xxx \\\n  ghcr.io/browser-gateway/server:latest\n```\n\n### Persistence\n\nEverything 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:\n\n- `profiles/` — encrypted profile blobs (when profiles are enabled)\n\nFuture 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.\n\n### Upgrades\n\nState lives in the volume, code lives in the image. Pull the new image, recreate the container — no data lost:\n\n```bash\ndocker compose pull\ndocker compose up -d\n```\n\nThe container reads the same `BG_DATA_DIR` and the same `gateway.yml`. Profile blobs are versioned and the gateway reads older formats transparently.\n\n### Image tags\n\n| Tag | Updated on |\n|---|---|\n| `:0.3.0` (and every subsequent version) | published manually after a release |\n| `:latest` | always points at the newest version |\n\nImages are multi-arch (`linux/amd64`, `linux/arm64`), signed with [Sigstore](https://www.sigstore.dev/) build provenance, and ship an SBOM. Verify with the [GitHub CLI](https://cli.github.com/):\n\n```bash\ngh attestation verify oci://ghcr.io/browser-gateway/server:0.3.0 \\\n  --repo browser-gateway/browser-gateway\n```\n\n---\n\n## How It Works\n\n**Sessions without profile / recording / observability** (the default) take the byte-pipe fast lane:\n\n1. Client connects to `ws://gateway:9500/v1/connect`\n2. Gateway selects a provider using your [routing strategy](https://docs.browsergateway.com/operating/load-balancing)\n3. Gateway opens a raw TCP connection to the provider\n4. HTTP upgrade forwarded, provider responds with `101 Switching Protocols`\n5. Bidirectional TCP pipe: `client <-> gateway <-> provider`\n6. All WebSocket messages forwarded transparently (never parsed or modified)\n7. On disconnect: session cleaned up, slot released, metrics updated\n8. If all providers full: connection [waits in a queue](https://docs.browsergateway.com/operating/queue) until a slot opens\n\n**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`](./docs/PIPELINE.md).\n\n---\n\n## Self-hosted provider: browserserve\n\n[browserserve](https://github.com/browser-gateway/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:\n\n```yaml\nproviders:\n  browserserve:\n    url: ws://your-host:9222\n  cloud-provider:\n    url: <websocket-url-with-auth>\n    priority: 2\n```\n\nBecause the gateway controls that runtime, a browserserve provider is **auto-detected** and unlocks two things no external provider gets:\n\n- **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)`.\n- **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.\n\nA common shape: browserserve as the primary provider on your own hardware, with a cloud provider at a lower priority for failover.\n\n---\n\n## Works With\n\nbrowser-gateway is compatible with existing browser tools. Just pass the gateway URL — it auto-resolves via `/json/version`.\n\n**AI Agent Frameworks:**\n\n```python\n# browser-use (Python) — HTTP URL auto-resolves\nBrowserSession(cdp_url=\"http://localhost:9500\")\n```\n\n```typescript\n// Stagehand (TypeScript)\nnew Stagehand({ env: \"LOCAL\", localBrowserLaunchOptions: { cdpUrl: \"http://localhost:9500\" } })\n```\n\n**Playwright MCP** (all 70 Playwright tools through gateway routing):\n\n```json\n{\n  \"mcpServers\": {\n    \"playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\"@playwright/mcp@latest\", \"--cdp-endpoint\", \"http://localhost:9500\"]\n    }\n  }\n}\n```\n\n**Puppeteer / Playwright:**\n\n```typescript\n// Playwright — HTTP or WebSocket\nconst browser = await chromium.connectOverCDP(\"http://localhost:9500\");\n\n// Puppeteer — WebSocket\nconst browser = await puppeteer.connect({ browserWSEndpoint: \"ws://localhost:9500/v1/connect\" });\n```\n\n---\n\n## Documentation\n\nFull docs live at **[docs.browsergateway.com](https://docs.browsergateway.com)**.\n\n- [Getting Started](https://docs.browsergateway.com/quickstart)\n- [Configuration Reference](https://docs.browsergateway.com/configuration)\n- [Supported Providers](https://docs.browsergateway.com/providers)\n- [Profiles — Persistent Browser State](https://docs.browsergateway.com/profiles)\n- [Session Replays](https://docs.browsergateway.com/replays)\n- [Session Lifecycle](https://docs.browsergateway.com/sessions)\n- [REST API](https://docs.browsergateway.com/rest-api)\n- [MCP Server for AI Agents](https://docs.browsergateway.com/mcp)\n- [CLI Reference](https://docs.browsergateway.com/cli)\n- [Web Dashboard](https://docs.browsergateway.com/dashboard)\n- [How Failover Works](https://docs.browsergateway.com/operating/failover)\n- [Load Balancing Strategies](https://docs.browsergateway.com/operating/load-balancing)\n- [Request Queue](https://docs.browsergateway.com/operating/queue)\n- [Webhooks](https://docs.browsergateway.com/operating/webhooks)\n- [Docker Deployment](https://docs.browsergateway.com/operating/docker)\n- [Integrations](https://docs.browsergateway.com/operating/integrations) — Playwright, Puppeteer, browser-use, Stagehand, Playwright MCP\n\n---\n\n## Contributing\n\nContributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## License\n\nMIT - see [LICENSE](LICENSE).\n\n## Links\n\n- [browsergateway.com](https://browsergateway.com)\n- [docs.browsergateway.com](https://docs.browsergateway.com)\n- [GitHub](https://github.com/browser-gateway/browser-gateway)\n- [npm](https://www.npmjs.com/package/browser-gateway)\n\n## Contact\n\nQuestions, security reports, or partnership inquiries: `hello@browsergateway.com`.\n\n---\n\n<sub>Maintained by <a href=\"https://monostellar.com\">Monostellar Labs</a>.</sub>\n",
  "bytes": 19674,
  "sha": "b9e2a429768b459f74a0b9b3ed7e7e2b17c629075f8b3cc30bac35c459d01faa",
  "repo_slug": "browser-gateway/browser-gateway",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_browser_gateway_browser_gatewa_a6db6d9d/readme"
}