npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

browser-gateway

v0.3.5

Published

Reliable, scalable browser infrastructure for AI agents.

Downloads

1,757

Readme


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.


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 maxConcurrent on every backend
  • Request 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/screenshot returns any URL as PNG or JPEG, full-page or scoped to a selector
  • Content extraction - POST /v1/content returns markdown, plain text, HTML, or a cleaned article
  • Scrape - POST /v1/scrape extracts structured data via CSS selectors or full-page formats
  • Pooled 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, and IndexedDB are captured on disconnect and replayed on the next connect with the same id
  • One-line opt-in - add ?profile=acme to the WebSocket URL, the rest is automatic
  • Encrypted 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 .bgp blobs are portable between gateway installs
  • One-click enable - the dashboard wizard generates a strong key in your browser and writes it to config

See docs/profiles.md 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.startScreencast
  • Zero 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 docs/replays.md 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.yml in-browser with syntax highlighting and validation
  • Auth - 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-gateway

Create 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: 2
browser-gateway serve

Connect 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 docs/mcp.md 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 serve
  • WebSocket clients pass the token as ?token= query param
  • API clients use Authorization: Bearer <token> header
  • Dashboard 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 help

API

| Endpoint | Method | Description | |----------|--------|-------------| | /v1/connect | WebSocket | Connect to a browser (the core feature) | | /v1/screenshot | POST | Take a screenshot of any URL (docs) | | /v1/content | POST | Extract page content as markdown, text, or HTML (docs) | | /v1/scrape | POST | Extract data via CSS selectors or full-page formats (docs) | | /v1/status | GET | Gateway health + provider status + pool status | | /v1/sessions | GET | Active sessions | | /v1/providers | GET/POST | List or add providers | | /v1/providers/:id | PUT/DELETE | Update or remove a provider | | /v1/providers/:id/test | POST | Test provider connectivity | | /v1/config | GET/PUT | Read or save config | | /v1/config/validate | POST | Validate YAML without saving | | /mcp | POST | MCP Streamable HTTP endpoint | | /json/version | GET | CDP discovery (for browser-use, Playwright, Stagehand) | | /health | 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 -d

Plain 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:latest

Persistence

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 -d

The 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 | |---|---| | :0.3.0 (and every subsequent version) | published manually after a release | | :latest | 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-gateway

How It Works

  1. Client connects to ws://gateway:9500/v1/connect
  2. Gateway selects a provider using your routing strategy
  3. Gateway opens a raw TCP connection to the provider
  4. HTTP upgrade forwarded, provider responds with 101 Switching Protocols
  5. Bidirectional TCP pipe: client <-> gateway <-> provider
  6. All WebSocket messages forwarded transparently (never parsed or modified)
  7. On disconnect: session cleaned up, slot released, metrics updated
  8. If all providers full: connection waits in a queue until a slot opens

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


Contributing

Contributions welcome. See CONTRIBUTING.md for guidelines.

License

MIT - see LICENSE.

Links