Documentation

Hosted headless browsers over the Chrome DevTools Protocol (CDP). Connect Puppeteer, Playwright or chromedp to a WebSocket URL with an API token and get a fresh, isolated browser (Lightpanda, Chrome or CloakBrowser) that is destroyed when you disconnect. You can also create long-lived sessions over REST or from the dashboard, reconnect to them, watch and control them live, record them to MP4 and keep logins in persistent Chrome profiles.

Dashboard: https://app.hermesbrowsers.com

Quick start

  1. Sign up at https://app.hermesbrowsers.com/signup.
  2. Create a token at https://app.hermesbrowsers.com/tokens (you can show and copy the full 40-character token there anytime) and store it as HERMES_TOKEN.
  3. Connect to wss://cdp.hermesbrowsers.com/ws?token=$HERMES_TOKEN.

Connection URL

wss://cdp.hermesbrowsers.com/ws?token=<token>&browser=<lightpanda|chrome|cloak>&proxy=<name>&country=<cc>&timeout=<min>&profile=<name>&record=1

Parameter Required Meaning
token yes API token from the Tokens page
browser no lightpanda (default; fast, low memory, partial Web API coverage), chrome (full rendering) or cloak (CloakBrowser stealth Chromium: spoofed fingerprint, navigator.webdriver false, presents as Windows)
proxy no Name of a shared proxy or of one of your dedicated proxies (Proxies page)
country no Two-letter country code for proxies that support it
timeout no Session lifetime in minutes, 1-15 (default 15)
profile no Chrome/cloak only. Persistent profile name ([A-Za-z0-9_-]{1,64}); cookies, storage and logins survive between sessions (cloak also keeps the same fingerprint). Created on first use; one running session per profile
record no Chrome/cloak only. 1 records the session to MP4 (kept 7 days)

Regions:

  • eu (Europe): wss://cdp.hermesbrowsers.com/ws

Examples

Puppeteer:

JavaScript
import puppeteer from "puppeteer-core";
const browser = await puppeteer.connect({ browserWSEndpoint: `wss://cdp.hermesbrowsers.com/ws?token=${process.env.HERMES_TOKEN}&browser=lightpanda` });
const page = await browser.newPage();
await page.goto("https://example.com");
console.log(await page.title());
await browser.disconnect();

Playwright (CDP only, Chromium API):

JavaScript
import { chromium } from "playwright-core";
const browser = await chromium.connectOverCDP(`wss://cdp.hermesbrowsers.com/ws?token=${process.env.HERMES_TOKEN}&browser=chrome`);
const page = await browser.contexts()[0].newPage();
await page.goto("https://example.com");
await browser.close();

chromedp (Go):

Go
ctx, cancel := chromedp.NewRemoteAllocator(context.Background(), "wss://cdp.hermesbrowsers.com/ws?token="+os.Getenv("HERMES_TOKEN"), chromedp.NoModifyURL)
defer cancel()
ctx, cancel = chromedp.NewContext(ctx)
defer cancel()
var title string
err := chromedp.Run(ctx, chromedp.Navigate("https://example.com"), chromedp.Title(&title))

Automation > Script generator in the dashboard builds these snippets with your token, browser and proxy filled in.

Agents

AI agents use the same URL. Pick Chrome for them (full Web APIs and screenshots): wss://cdp.hermesbrowsers.com/ws?token=<token>&browser=chrome, written <url> below.

  • Hermes Agent: /browser connect <url> in chat, or set browser.cdp_url (or BROWSER_CDP_URL).
  • OpenClaw: add a remote profile, browser.profiles.hermes.cdpUrl: "<url>".
  • Claude Code: claude mcp add hermes -- npx @playwright/mcp@latest --cdp-endpoint "<url>"
  • Codex: codex mcp add hermes -- npx @playwright/mcp@latest --cdp-endpoint "<url>"
  • Kilo Code, Cline, Strix and omp: add Playwright MCP to the agent's MCP servers file (Kilo Code and Cline: MCP settings; Strix: ~/.strix/mcp-servers.json; omp: ~/.omp/agent/mcp.json, after setting browser.enabled: false, since omp hides browser MCP servers while its own browser is on):
{
  "mcpServers": {
    "hermes": { "command": "npx", "args": ["@playwright/mcp@latest", "--cdp-endpoint", "<url>"] }
  }
}
  • pi: has no MCP by design; ask it to run a Puppeteer or Playwright script that connects to <url> (see Examples).

REST API (persistent sessions)

Base URL https://cdp.hermesbrowsers.com. Authenticate with Authorization: Bearer <token> (or X-API-Key). A session created over REST stays alive across disconnects until you stop it or timeout is reached, so you can reconnect to cdp_url any number of times (one client at a time recommended).

Method Path Meaning
POST /v1/browsers Start a session. JSON body: browser, proxy, country, region, timeout, profile, record (same meaning as above). 201 with the session
GET /v1/browsers Running sessions of the token's account
GET /v1/browsers/{id} One session
DELETE /v1/browsers/{id} Stop it (409 if not running)
GET /v1/browsers/{id}/recording The MP4 once recording is ready

Session object: id, status (running/closed/error), browser, proxy, country, region, profile, persistent, recording (recording/ready/failed/expired/null), started_at, timeout_at, ended_at, close_reason, cdp_url (connect here; null once closed), live_url (Chrome/cloak only), recording_url.

Shell
curl -s -X POST https://cdp.hermesbrowsers.com/v1/browsers -H "Authorization: Bearer $HERMES_TOKEN" -H 'content-type: application/json' \
  -d '{"browser":"chrome","profile":"shop-login","record":true,"timeout":10}'
JavaScript
const s = await (await fetch("https://cdp.hermesbrowsers.com/v1/browsers", { method: "POST", headers: { authorization: `Bearer ${process.env.HERMES_TOKEN}`, "content-type": "application/json" }, body: JSON.stringify({ browser: "chrome" }) })).json();
const browser = await puppeteer.connect({ browserWSEndpoint: s.cdp_url });
// ... later, from any process:
await fetch(`https://cdp.hermesbrowsers.com/v1/browsers/${s.id}`, { method: "DELETE", headers: { authorization: `Bearer ${process.env.HERMES_TOKEN}` } });

Live view

Every running Chrome/cloak session has a live_url: a page that streams the browser screen and lets whoever opens it click, type, paste (Cmd/Ctrl+V sends your local clipboard), scroll and navigate (human-in-the-loop for logins, 2FA or CAPTCHAs). On a slow link it skips frames instead of falling behind, so what you see stays current. It is a bearer link: anyone holding it can control the browser until the session ends. It is shown on the Browsers and session pages in the dashboard and returned by the REST API.

Proxies

HTTP proxies only. Shared proxies:

  • residential: Residential (residential), accepts country

Shared proxy traffic is prepaid: every account gets 1 GB free, then $0.27/GB. Used and remaining GB are on the Subscription & billing page. With the balance at zero new sessions on a shared proxy are refused (402) and running ones are closed. Dedicated proxies are not billed.

Dedicated proxies: add host:port with optional username/password on the Proxies page, then pass its name as proxy.

Limits

Plan Concurrent sessions Browser hours / month
Explorer (free) 5 10
Builder 30 300
  • Each token also has its own concurrency limit (set on the Tokens page).
  • A session is closed after 15 minutes, or after its timeout.

Connection errors

The WebSocket upgrade is rejected with an HTTP status and a JSON body {"error": "..."}:

Status Error Fix
401 missing token / invalid token Pass a valid token
403 token disabled Re-enable the token on the Tokens page
400 unknown browser: x / unknown proxy: x Use lightpanda/chrome/cloak, or an existing proxy name
403 browser=cloak is not enabled for this account Use chrome, or ask the operator to enable CloakBrowser
429 token concurrency limit reached / plan concurrency limit reached Close other sessions or raise the limit
402 monthly browser hours exhausted Wait for next month or upgrade
402 residential proxy balance exhausted Contact support to add proxy GB

Dashboard

  • Browsers: launch a Chrome or CloakBrowser browser (proxy, country, profile) without code, open its live view, stop it
  • Sessions: every session with duration, bandwidth, close reason and its CDP message log
  • Tokens: create, show/copy, disable, delete and limit API tokens
  • Proxies: shared and dedicated proxies
  • Profiles: persistent Chrome profiles; import cookies (Cookie-Editor/EditThisCookie export or Puppeteer/Playwright JSON) to start one already signed in, they load on its next session; delete one to wipe its data
  • Scripts: write TypeScript scripts in the browser and run them on demand on the console's servers (Run button only, no schedule, 2-minute limit); process.env.CDP_WS_URL is preset. Run history is under Script runs
  • Script generator: ready-to-run connection snippets for your own machine or server (use these for cron jobs or longer runs)

Session pages show live view and share link, a Stop button and the recording player.