Skip to main content

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
  • Restart-safe session cleanup with durable retry state and ownership-scoped orphan reporting

✅ 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

Browserious CLI and MCP

The browserious wheel contains the complete CLI, shared OAuth client, and optional MCP compatibility adapter. The CLI is the primary interface.

Setup

Install:

pip install browserious
browserious login
browserious whoami
browserious session create

For an isolated run use uvx browserious --help. Pin a release for reproducible automation; because uvx caches environments, add --refresh when it must resolve the requested release again:

uvx --refresh --from browserious==0.2.0 browserious --version

browserious login uses device authorization and stores rotating OAuth credentials. Use --no-browser on a headless host. CLI/MCP browser commands use authenticated shared REST operations and share server-owned sessions by ID without a process-local registry. The local tunnel owner alone requests a short-lived tunnel capability. Run browserious --help and browserious GROUP --help for the installed wheel's normative command inventory; the API guide lists all command groups, output and exit semantics, tunnels, and MCP parity.

The CLI defaults to human output; --json or --output json emits compact JSON. Errors go to stderr. Secrets are recursively redacted unless --show-secrets is used on one of the four bounded commands that permit it (session create, file get, profile get, profile export). Exit codes classify success (0), local validation (2), auth (3), forbidden (4), not found (5), conflict (6), rate limit (7), transport/server (8), other HTTP (9), and interrupted foreground tunnel (130).

Open a foreground localhost tunnel with:

browserious tunnel open SESSION_ID --local-port 3000

The command owns its WebSocket until interrupted. --detach transfers ownership to the per-user daemon; inspect it with browserious tunnel list and stop it with browserious daemon stop. Detached tunnels require Unix-domain sockets, while foreground tunnels remain available on unsupported daemon platforms.

Local MCP compatibility

Run MCP explicitly from the same wheel with browserious mcp. It uses the CLI credential store, refresh lifecycle, capability client, operations, scopes, and revocation path. A pinned local host configuration is:

{
  "mcpServers": {
    "browserious": {
      "command": "uvx",
      "args": ["--refresh", "--from", "browserious==0.2.0", "browserious", "mcp"],
      "env": {
        "BROWSERIOUS_API_URL": "https://api.browserious.com"
      }
    }
  }
}

Credential precedence is --access-token, BROWSERIOUS_ACCESS_TOKEN, legacy BROWSERIOUS_API_KEY, then the stored login. Normal interactive setup uses device login rather than pasted br_live_* tokens. The 0.2.0 compatibility release contains exactly two deprecated, transitional bridges: python -m browserious_mcp, and zero-argument browserious when both standard streams are non-TTY. Interactive zero-argument invocation shows CLI help. Eventual MCP retirement removes the verb, bridges, browserious_mcp module, MCP dependencies, parity tests, and MCP docs from this wheel; it does not create or migrate to a second package. No later removal version is promised.

Optional remote MCP

The same bundled adapter is also available over stateless Streamable HTTP at https://api.browserious.com/mcp. Remote clients discover the shared Browserious authorization server, dynamically register as public clients, and complete authorization-code authentication with S256 PKCE. They request the existing browser:read browser:write tunnel scopes and use the same rotating br_at_* and br_rt_* token families as other Browserious clients.

Discovery starts from the 401 challenge's RFC 9728 resource_metadata URL, https://api.browserious.com/.well-known/oauth-protected-resource/mcp. That document identifies the resource and authorization server; the client then reads https://api.browserious.com/.well-known/oauth-authorization-server, registers at the advertised endpoint, and uses the advertised authorization/token/revocation endpoints with the exact redirect URI and S256 verifier.

Claude Code can add the remote endpoint with:

claude mcp add --transport http browserious https://api.browserious.com/mcp

Claude Code configuration was sanitized and probed against this URL. Cursor and Windsurf onboarding remains manual-only; no completed client-specific OAuth flow is claimed. If a client cannot complete remote OAuth, use local stdio. Remote and stdio enumerate the same tools and call the same operations. Remote open_tunnel and close_tunnel fail safely because a service-host process cannot own a client-local port; use the CLI or local stdio MCP for tunnels.

Public DNS is Cloudflare Anycast/proxied, and requests traverse Cloudflare → Caddy → FastAPI. The local 192.168.1.3 address is an intentional host/VPN shortcut. Node callbacks send the explicit Browserious-Node/0.2.0 service User-Agent to avoid Cloudflare error 1010. This topology makes no unverified streaming timeout promise.

Available Tools

The wheel currently exposes 23 MCP tools. Runtime enumeration and the installed-wheel parity check are normative, not this descriptive count. Every tool has a CLI equivalent:

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, return a reference plus metadata (opt into bytes with inline)
display_screenshot Capture X11 display with cursor, same reference-first contract
play_input Hardware-level mouse/keyboard via X11
get_cursor_position Get current cursor screen coordinates
element_at_point Identify the element at viewport coordinates
captcha_detect Detect CAPTCHA regions
open_tunnel Open a client-owned localhost tunnel (local transports only)
close_tunnel Close a client-owned localhost tunnel (local transports only)
list_files List stored files
get_file Return owner-scoped metadata and a redacted-by-default presigned download URL
delete_file Delete a stored file

Screenshot handling

CLI screenshot commands write image bytes to --output-file or browserious-output.bin.

MCP screenshot tools return a reference plus metadata instead of an inline image, so a large capture cannot flood a caller's context:

{"session_id": "sess-1", "page_id": "page-0", "format": "png", "size_bytes": 454931,
 "width": 1920, "height": 4200, "path": "/tmp/browserious-screenshots/sess-1-page-0.png",
 "path_scope": "mcp-client-host", "file_id": null, "retrievable": true, "inline": false,
 "hint": "Local stdio MCP: ...", "warnings": []}

inline=true returns FastMCP image content, but only below BROWSERIOUS_MCP_INLINE_MAX_BYTES (default 1 MiB; a value that is not a byte count is ignored); above it the tool raises a structured error that still carries the reference. path resolves on the MCP server's host — the caller's own machine over local stdio (BROWSERIOUS_SCREENSHOT_DIR overrides the directory), and null over remote MCP, where get_file(file_id) is the way to the bytes. Each capture target reuses one stable path, and the directory keeps only the most recent captures, so a verification loop cannot fill the disk. When no path and no file_id can be produced, the tool still returns the reference with retrievable: false and a hint naming the prerequisites, rather than discarding a capture that already succeeded. Secret-bearing JSON fields remain redacted by default.

Fonts are required for meaningful screenshots. A browser container without fonts renders invisible text, producing a structurally correct and completely worthless capture; installing fonts-dejavu-core and fontconfig grew a real text-heavy capture roughly 15x. This is a property of whichever environment renders the page — Browserious' own node image inherits fonts from its Playwright base, so the risk is a browser container you build or run yourself. The signal is relative, not absolute: a correct but sparse page (a login form, an empty state) is within ~1.2x of a fontless full-page render in bytes per pixel, so size alone cannot diagnose it. Compare size_bytes for the same page before and after installing fonts.

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',
  headers: {Authorization: `Bearer ${process.env.BROWSERIOUS_ACCESS_TOKEN}`}
});

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 src.server

src.server enables Uvicorn proxy-header processing only for peers in FORWARDED_ALLOW_IPS, an explicit comma-separated IP/CIDR allowlist. It defaults to 127.0.0.1, matching the supported local Caddy deployment. Keep that default for direct API exposure; when another ingress connects to the container, set the variable to that ingress network only. Wildcard trust is rejected.

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)
  • Set JWT_SECRET to 32+ random bytes (openssl rand -base64 32) — required outside dev/testing, the API refuses to start without it
  • 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.

Release files for browserious 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for browserious 0.2.0
File Size Uploaded
browserious-0.2.0.tar.gz 589.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for browserious 0.2.0
File Interpreter ABI Platform
browserious-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 633.2 kB

Release files / browserious-0.2.0.tar.gz

Download URL browserious-0.2.0.tar.gz
Size 589.7 kB
Tags Source
SHA-256 checksum
How to use checksums
09d5c29ee722e8fc925f3c052f5885583c101af1bc68672ed4cc47cf5a05b257
BLAKE2b-256 checksum
How to use checksums
1e17ad6b861bb08b8f2f41c32accd5296b94a2993d8fdd6647694f2aca15ba2e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / browserious-0.2.0-py3-none-any.whl

Download URL browserious-0.2.0-py3-none-any.whl
Size 43.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
42fa26e2aab9695b355bb7ae5392a1739be0efeac2eb4bc9d7cd72ff111cb401
BLAKE2b-256 checksum
How to use checksums
3354c8ac62013715d5757e7de874e5ae18c35f1f36fe537d0089c0ad562dbbd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page