api reference.
Three endpoints. JSON in, JSON out, and a CDP websocket where the browser lives. Everything below works with curl.
# basics
base url https://api.guise.sh
auth x-api-key: <key> (get one at guise.sh/keys)
content application/json────────────────────────────────────────────────────────────────
POST/v1/sessions
Create a browser. One session is one browser — warm, wired to its egress, handed over as a CDP websocket. ~150ms end to end.
proxystringEgress tier:"residential"(default) or"dc". You can omit this — residential is the right answer for almost everything.ttlSecnumberSelf-destruct timer, 30–3600 seconds. Default 900. The browser is destroyed when it fires — nothing idle to babysit.
# request
curl -s -X POST https://api.guise.sh/v1/sessions \
-H "x-api-key: $GUISE_KEY" \
-d '{"ttlSec":1800}'# response — 201
{
"id": "s_01J9K7Q8ZV3M",
"connectUrl": "wss://api.guise.sh/v1/sessions/s_01J9K7Q8ZV3M/cdp?token=…",
"proxy": "residential",
"ttlSec": 1800,
"createdAt": "2026-08-16T20:31:04Z"
}GET/v1/sessions
List your live sessions.
# response — 200
{ "sessions": [ { "id": "s_01J9K7Q8ZV3M", "proxy": "residential",
"secondsLeft": 1341, "createdAt": "…" } ] }GET/v1/sessions/:id
Status of one session: connectUrl, tier, and time left before the TTL reaper takes it.
DELETE/v1/sessions/:id
Kill it now. The browser is destroyed — disk and all — never recycled. Returns 204.
────────────────────────────────────────────────────────────────
## connect
connectUrl is a plain CDP websocket. Anything that speaks CDP works — no SDK, no wrapper.
# playwright (node)
const b = await chromium.connectOverCDP(session.connectUrl);
const page = await b.contexts()[0].newPage();
await page.goto("https://example.com");# puppeteer
const b = await puppeteer.connect({ browserWSEndpoint: session.connectUrl });
const page = await b.newPage();# playwright (python)
b = playwright.chromium.connect_over_cdp(session["connectUrl"])
page = b.contexts[0].new_page()────────────────────────────────────────────────────────────────
## proxy tiers
"residential"Sticky residential exit, one per session, held for the session’s lifetime. The default — right for anything that checks who you are."dc"Datacenter egress. For APIs, scrapes that don’t care, and dev loops.
────────────────────────────────────────────────────────────────
## errors
400malformed body — check proxy tier and ttlSec bounds401missing or unknown x-api-key404no such session — already reaped or never existed429slow down — retry with backoff503pool momentarily empty — retry-after header tells you when