Skip to main content

MCP server for Browserious — browser-as-a-service for AI agents

Project description

Browserious - Browser API Wrapper

Self-hosted, API-controlled browser-as-a-service for automation, testing, and web scraping.

Tests Python Docker

Overview

Browserious provides a REST API + WebSocket interface to control Chromium browsers running in Docker containers. Each browser session runs in an isolated container with:

  • Persistent Profiles - Maintain cookies, localStorage, and session state
  • Proxy Support - Configure HTTP/HTTPS/SOCKS5 proxies per session
  • Extensions - Load custom Chrome extensions
  • Request Interception - Block, redirect, or mock network requests
  • Remote Viewing - Watch browser sessions via VNC
  • CDP Access - Direct Chrome DevTools Protocol control

Primary Use Cases:

  • Browser automation and E2E testing
  • Web scraping and data extraction
  • Remote browser service

Quick Start

Prerequisites

  • Docker and Docker Compose
  • Python 3.11+ (for development)

Installation

# Clone repository
git clone https://github.com/muzhig/browserious.git
cd browserious

# Generate API key
export API_KEYS=$(openssl rand -base64 32)

# Start service
docker-compose up -d

# Verify
curl -H "X-API-Key: $API_KEYS" http://localhost:8100/sessions

Create Your First Session

# Create browser session
SESSION_ID=$(curl -X POST http://localhost:8100/sessions \
  -H "X-API-Key: $API_KEYS" \
  -H "Content-Type: application/json" \
  -d '{"timeout": 600}' \
  | jq -r '.session_id')

# Navigate to a page
curl -X POST http://localhost:8100/sessions/$SESSION_ID/pages/page-0/goto \
  -H "X-API-Key: $API_KEYS" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

# Take screenshot
curl -H "X-API-Key: $API_KEYS" \
  http://localhost:8100/sessions/$SESSION_ID/pages/page-0/screenshot \
  > screenshot.png

# Watch in browser (VNC)
# Open the web_vnc_url from the session response, e.g.:
# http://localhost:8100/vnc.html?session=$SESSION_ID

# Cleanup
curl -X DELETE http://localhost:8100/sessions/$SESSION_ID \
  -H "X-API-Key: $API_KEYS"

Architecture

┌─────────────────────────────────────────────────────────┐
│  API Container (browserious-api)                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │  FastAPI Application :8100                        │  │
│  │  - REST API + WebSocket                           │  │
│  │  - VNC WebSocket proxy /sessions/{id}/vnc         │  │
│  │  - Web VNC viewer /vnc.html?session={id}          │  │
│  │  - Docker API (creates/manages browser nodes)     │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
           │
           │ Docker Network: browserious
           ▼
┌─────────────────────────────────────────────────────────┐
│  Browser Node Containers (one per session)              │
│                                                         │
│  ┌─────────────────┐    ┌─────────────────┐            │
│  │ session-abc123  │    │ session-xyz789  │   ...      │
│  │                 │    │                 │            │
│  │  Xvfb :99       │    │  Xvfb :99       │            │
│  │  x11vnc :5900   │    │  x11vnc :5900   │            │
│  │  Chromium       │    │  Chromium       │            │
│  │  CDP :9222      │    │  CDP :9222      │            │
│  └─────────────────┘    └─────────────────┘            │
│                                                         │
│  (No port conflicts - each node uses same internal     │
│   ports, addressed by container hostname/IP)           │
└─────────────────────────────────────────────────────────┘

Features

✅ Session Management

  • Create isolated browser sessions
  • Configure proxy, viewport, user agent
  • Persistent profiles with cookie/storage management
  • Automatic timeout and cleanup

✅ Page Operations

  • Navigate, click, type, fill forms
  • Multiple selector strategies (CSS, XPath, Playwright, JS)
  • Wait for elements (visibility, loading states)
  • Execute JavaScript in page context
  • Screenshots (full page or viewport)
  • HTML content extraction

✅ Request Interception

  • Block requests (ads, trackers, images)
  • Redirect URLs (mock APIs, override media)
  • Override responses (status, headers, body)
  • Inspect and capture requests

✅ Extensions

  • Upload custom Chrome extensions
  • Load extensions per session
  • Support for .zip and .crx formats

✅ Remote Access

  • VNC server with web client (noVNC)
  • Per-session password protection
  • Real-time browser viewing

✅ CDP WebSocket

  • Direct Chrome DevTools Protocol access
  • Compatible with Puppeteer/Playwright
  • Full browser control for advanced use cases

Documentation

Document Description
PRD Product Requirements Document - features, use cases, MVP scope
ADR Architecture Decision Records - key technical decisions and rationale
API Complete API Reference - endpoints, examples, error codes
EXAMPLES Code examples - form interaction, content extraction, visual debugging
SECURITY Security Analysis - threat model, hardening, best practices
Project Brief Original project specification

MCP Server for Claude Code

Browserious includes an MCP (Model Context Protocol) server for integration with Claude Code and other AI assistants.

Setup

Install:

pip install browserious
# or run without installing:
uvx browserious

Add to your Claude Code, Cursor, or Claude Desktop config:

{
  "mcpServers": {
    "browserious": {
      "command": "uvx",
      "args": ["browserious"],
      "env": {
        "BROWSERIOUS_API_URL": "https://api.browserious.com",
        "BROWSERIOUS_API_KEY": "<your-api-token>"
      }
    }
  }
}

The MCP server runs locally on your machine. It uses the API for session lifecycle (create/delete) and connects directly to browser containers for all operations — no proxy overhead.

Available Tools

The MCP server exposes 20 tools:

Tool Description
create_session Create browser session, returns session_id and URLs
delete_session Close and cleanup session
list_sessions List all active sessions
create_page Open new tab, optionally navigate to URL
page_goto Navigate to URL
page_click Click element (CSS, XPath, text, role, JS selectors)
page_type Type text with keyboard events
page_fill Fill input instantly
page_eval Execute JavaScript, return result
page_wait_for_selector Wait for element state
page_content Get full HTML
page_screenshot Capture page, save to file, return path
display_screenshot Capture X11 display with cursor
play_input Hardware-level mouse/keyboard via X11
get_cursor_position Get current cursor screen coordinates

Screenshot Handling

Screenshots are saved to files and the path is returned, allowing multimodal AI to view them:

# MCP tool returns: {"file_path": "/tmp/screenshot_abc123.png", "size_bytes": 45678}
# AI can then read the image file directly

Coordinate System

For play_input, convert viewport coordinates to screen coordinates:

screen_x = viewport_x + screenX
screen_y = viewport_y + screenY + chromeHeight

Get these values from window_info in the session response or via page_eval:

({
    screenX: window.screenX,
    screenY: window.screenY,
    chromeHeight: window.outerHeight - window.innerHeight
})

API Examples

Web Scraping with Proxy

import requests

API_KEY = "your-api-key"
BASE_URL = "http://localhost:8100"
headers = {"X-API-Key": API_KEY}

# Create session with proxy
session = requests.post(
    f"{BASE_URL}/sessions",
    headers=headers,
    json={
        "profile_id": "scraper-001",
        "proxy": {"server": "http://proxy.example.com:8080"},
        "timeout": 3600
    }
).json()
session_id = session["session_id"]

# Block images to speed up scraping
requests.post(
    f"{BASE_URL}/sessions/{session_id}/routes",
    headers=headers,
    json={
        "pattern": "**/*.{png,jpg,jpeg,gif}",
        "action": {"type": "block"}
    }
)

# Navigate and extract data
requests.post(
    f"{BASE_URL}/sessions/{session_id}/pages/page-0/goto",
    headers=headers,
    json={"url": "https://example.com"}
)

data = requests.post(
    f"{BASE_URL}/sessions/{session_id}/pages/page-0/eval",
    headers=headers,
    json={"script": "return document.querySelectorAll('.item').length"}
).json()

print(f"Found {data['result']} items")

# Cleanup
requests.delete(f"{BASE_URL}/sessions/{session_id}", headers=headers)

E2E Testing with Mocked API

# Create test session
session = requests.post(
    f"{BASE_URL}/sessions",
    headers=headers,
    json={"profile_id": "test-user"}
).json()
session_id = session["session_id"]

# Mock API response
requests.post(
    f"{BASE_URL}/sessions/{session_id}/routes",
    headers=headers,
    json={
        "pattern": "**/api/user",
        "action": {
            "type": "override",
            "status": 200,
            "body": '{"id": 123, "name": "Test User"}'
        }
    }
)

# Run test
requests.post(
    f"{BASE_URL}/sessions/{session_id}/pages/page-0/goto",
    headers=headers,
    json={"url": "https://app.example.com"}
)

# Interact with page
requests.post(
    f"{BASE_URL}/sessions/{session_id}/pages/page-0/click",
    headers=headers,
    json={"selector": {"strategy": "css", "value": "#login-button"}}
)

# Capture screenshot on failure
screenshot = requests.get(
    f"{BASE_URL}/sessions/{session_id}/pages/page-0/screenshot",
    headers=headers,
    params={"full_page": True}
).content

with open("test-failure.png", "wb") as f:
    f.write(screenshot)

Using Puppeteer via CDP

const puppeteer = require('puppeteer-core');

// Connect to existing session via CDP
const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://localhost:8100/sessions/{session_id}/cdp'
});

const page = await browser.newPage();
await page.goto('https://example.com');

const title = await page.title();
console.log('Page title:', title);

await page.screenshot({path: 'screenshot.png'});

Configuration

Environment Variables

Variable Default Description
API_KEYS - Comma-separated API keys (required)
PROFILES_DIR /data/profiles Profile storage directory
EXTENSIONS_DIR /data/extensions Extensions storage directory
MAX_SESSIONS 10 Maximum concurrent sessions
DEFAULT_TIMEOUT 3600 Default session timeout (seconds)
RESOLUTION 1920x1080x24 Virtual display resolution

Docker Compose

services:
  api:
    build: .
    container_name: browserious-api
    ports:
      - "8100:8100"   # API + VNC viewer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./profiles:/data/profiles
      - ./extensions:/data/extensions
    environment:
      - API_KEYS=${API_KEYS}
      - API_HOST=localhost
      - API_PORT=8100
      - PROFILES_DIR=/data/profiles
      - EXTENSIONS_DIR=/data/extensions
      - HOST_PROFILES_DIR=${HOST_PROFILES_DIR}
      - HOST_EXTENSIONS_DIR=${HOST_EXTENSIONS_DIR}
      - DOCKER_NETWORK=browserious
      - DOCKER_IMAGE=browserious-node:latest
      - MAX_SESSIONS=10
      - DEFAULT_TIMEOUT=3600
    networks:
      - browserious
    restart: unless-stopped

networks:
  browserious:
    name: browserious
    driver: bridge

Note: The API container requires access to Docker socket to spawn browser node containers. Set HOST_PROFILES_DIR and HOST_EXTENSIONS_DIR to the absolute paths on your host machine for volume mounts to work correctly in browser nodes.

Development

Setup

# Clone repository
git clone https://github.com/muzhig/browserious.git
cd browserious

# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt

# Install Playwright browsers
playwright install chromium

# Run tests
pytest

# Run locally (without Docker)
export API_KEYS=test-key
export DISPLAY=:99
Xvfb :99 -screen 0 1920x1080x24 &
python -m uvicorn src.main:app --reload

Rebuilding After Code Changes

Different parts of the codebase require different rebuild steps:

Changed Rebuild Command Notes
src/*.py docker-compose build api Python API code
node/api/*.go docker build -t browserious-node:latest ./node Go node API (input simulation)
node/Dockerfile docker build -t browserious-node:latest ./node Node container config
node/entrypoint.sh docker build -t browserious-node:latest ./node Node startup script
Dockerfile docker-compose build api API container config
docker-compose.yml docker-compose up -d Just restart, no rebuild

Quick reference:

# After changing Python code (src/)
docker-compose build api && docker-compose up -d

# After changing Go code (node/api/)
docker build -t browserious-node:latest ./node

# After changing both
docker build -t browserious-node:latest ./node && docker-compose build api && docker-compose up -d

# Full rebuild from scratch
docker build -t browserious-node:latest ./node && docker-compose build --no-cache && docker-compose up -d

Note: Existing browser sessions use the node image that was current when they were created. New sessions will use the updated image.

Project Structure

browserious/
├── docs/               # Documentation
│   ├── PRD.md
│   ├── ADR.md
│   ├── API.md
│   └── SECURITY.md
├── src/                # Source code
│   ├── main.py
│   ├── browser_manager.py
│   ├── page_operations.py
│   ├── route_manager.py
│   └── ...
├── tests/              # Test suite
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── README.md

Deployment

Production Checklist

  • Generate strong API keys (openssl rand -base64 32)
  • Enable HTTPS (nginx/Caddy reverse proxy)
  • Configure firewall (restrict API/VNC to trusted IPs)
  • Set resource limits (CPU, memory)
  • Enable profile encryption (LUKS or application-level)
  • Set up monitoring and alerting
  • Configure backups
  • Review Security Documentation

Horizontal Scaling

Run multiple instances with external load balancer:

# Instance 1
docker-compose up -d

# Instance 2 (different ports)
docker-compose -f docker-compose.instance2.yml up -d

# Load balancer (nginx)
upstream browserapi {
    server instance1:8000;
    server instance2:8000;
}

See ADR-002 for scaling strategy.

Security

Browserious provides multiple security layers:

  • API key authentication
  • Docker container isolation
  • Chromium sandbox
  • Per-session VNC passwords
  • Resource limits

Important: This service exposes significant attack surface. Review SECURITY.md before production deployment.

Quick Security Wins

  1. HTTPS Only: Use TLS for API (nginx reverse proxy)
  2. Network Isolation: Firewall rules to restrict access
  3. Strong API Keys: Generate with openssl rand -base64 32
  4. Resource Limits: Prevent DoS via docker-compose limits
  5. Profile Encryption: Encrypt /data/profiles volume

Troubleshooting

Common Issues

Session creation fails

  • Check Docker is running: docker ps
  • Check logs: docker-compose logs
  • Verify shm_size: docker inspect | grep ShmSize

VNC not showing browser

  • Ensure you're using the web VNC URL: http://localhost:8100/vnc.html?session={session_id}
  • Check that the session exists: curl http://localhost:8100/sessions/{session_id}
  • Verify the browser node container is running: docker ps | grep session-

Browser crashes

  • Increase shm_size in docker-compose.yml (recommended: 2g)
  • Check memory limits
  • Review container logs

Profile corruption

  • Avoid concurrent access to same profile_id
  • Use unique profile IDs: user-{id}-{session-num}
  • See ADR-003

Roadmap

MVP (Current)

  • Session management
  • Page operations (all selector strategies)
  • Request interception
  • Profile management
  • Extension support
  • VNC access
  • CDP WebSocket

Post-MVP

  • Metrics and monitoring (/metrics, /health)
  • Session event webhooks
  • Redis-based session registry (multi-instance)
  • Session recording (Playwright trace)
  • Firefox support
  • Mobile device emulation

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Make changes following code style guidelines
  4. Run tests: pytest tests/ -v
  5. Commit changes (git commit -m 'Add amazing feature')
  6. Push to branch (git push origin feature/amazing-feature)
  7. Open Pull Request

Quick Setup for Contributors

git clone https://github.com/muzhig/browserious.git
cd browserious
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
playwright install chromium
pytest tests/ -v

See CONTRIBUTING.md for detailed guidelines.

Acknowledgments

Support


Built for automation, testing, and scraping workflows.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

browserious-0.1.0.tar.gz (24.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

browserious-0.1.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file browserious-0.1.0.tar.gz.

File metadata

  • Download URL: browserious-0.1.0.tar.gz
  • Upload date:
  • Size: 24.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for browserious-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cf52281dcf8cd32b058e6d14dd64f49f8633ea5a1854e837a439db1ecf673880
MD5 25ec6de1c77c50a9ce19fd12493301ba
BLAKE2b-256 87fe8ba588086ab7d92e9084b54f8d117380698d5f071bca6aca70e86c419787

See more details on using hashes here.

File details

Details for the file browserious-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: browserious-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for browserious-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3fa4ed08dece17b85260a897c2b2750251ee953644301bcfa590614175484b06
MD5 8dc277d95d198d02f76fbccbc62f2e53
BLAKE2b-256 639100273f59f6ac1369d449f779713b1b128df039eaafb83fc19930f1a31a2b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page