Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/l-xiaoshen/handstage/llms.txt

Use this file to discover all available pages before exploring further.

Handstage exposes cookie and header management directly on V3Context — the object accessible via handstage.context. These methods talk to Chrome over CDP and apply context-wide, so they affect every page and frame within the context.

Cookies

Get cookies

context.cookies(urls?) returns all cookies in the browser context. Pass one or more URLs to filter by domain and path:
import { V3 } from "@handstage/core"

const handstage = await V3.connectLocal()
const context = handstage.context

// All cookies in the context
const all = await context.cookies()

// Only cookies that would be sent to these URLs
const filtered = await context.cookies([
  "https://example.com",
  "https://api.example.com",
])

console.log(filtered)
// [{ name: "session", value: "abc123", domain: "example.com", ... }]

await handstage.close()
Each returned Cookie object has these fields:
FieldTypeDescription
namestringCookie name.
valuestringCookie value.
domainstringDomain the cookie is scoped to.
pathstringURL path the cookie is scoped to.
expiresnumberExpiry as a Unix timestamp in seconds. -1 means the cookie is a session cookie.
httpOnlybooleanWhether the cookie is inaccessible to JavaScript.
securebooleanWhether the cookie is only sent over HTTPS.
sameSite"Strict" | "Lax" | "None"Cross-site request behavior.

Add cookies

context.addCookies(cookies) injects one or more cookies. Each entry must specify either a url (from which the domain, path, and secure flag are derived) or an explicit domain + path pair:
await context.addCookies([
  {
    name: "session",
    value: "abc123",
    url: "https://example.com",
    httpOnly: true,
    secure: true,
  },
])
The CookieParam type supports these fields:
FieldTypeDescription
namestringCookie name (required).
valuestringCookie value (required).
urlstringDerive domain, path, and secure from this URL. Use this or domain+path.
domainstringCookie domain.
pathstringCookie path.
expiresnumberUnix timestamp in seconds. Omit or pass -1 for a session cookie.
httpOnlybooleanRestrict cookie access to HTTP (not JavaScript).
securebooleanOnly send cookie over HTTPS.
sameSite"Strict" | "Lax" | "None"Cross-site request policy.
If Chrome rejects the cookie batch (for example, because of an invalid domain or an incompatible sameSite + secure combination), Handstage throws a CookieSetError describing the problem.

Clear cookies

context.clearCookies(options?) removes cookies. Called without arguments it clears everything in one atomic operation. Pass filter options to clear only matching cookies:
await context.clearCookies()
ClearCookieOptions accepts:
FieldTypeDescription
namestring | RegExpMatch by cookie name.
domainstring | RegExpMatch by cookie domain.
pathstring | RegExpMatch by cookie path.
When you pass filter options, Handstage fetches all cookies, clears the entire cookie jar, and re-adds the ones that do not match your filter. This is necessary because the underlying CDP Storage domain does not support targeted deletes. The read-clear-rewrite sequence is performed atomically in terms of your Handstage code, but there is a brief window where all cookies are absent.

Extra HTTP headers

context.setExtraHTTPHeaders(headers) injects a fixed set of headers into every outgoing HTTP request made by any page in the context. This is the standard way to attach authentication tokens, API keys, or tracing headers:
await context.setExtraHTTPHeaders({
  Authorization: "Bearer my-token",
  "X-Custom-Header": "handstage",
})
Headers are applied to all existing pages immediately and to any new pages created afterwards.
Calling setExtraHTTPHeaders replaces the full set of extra headers — it does not merge with a previous call. To remove all injected headers, pass an empty object: await context.setExtraHTTPHeaders({}).

Complete example

import { V3 } from "@handstage/core"

const handstage = await V3.connectLocal()
const context = handstage.context

// Inject an auth header on every request
await context.setExtraHTTPHeaders({
  Authorization: "Bearer eyJhbGci...",
})

// Pre-load a session cookie
await context.addCookies([
  {
    name: "session_id",
    value: "s:abc123.xyz",
    url: "https://app.example.com",
    httpOnly: true,
    secure: true,
    sameSite: "Strict",
  },
])

const page = context.activePage()
await page.goto("https://app.example.com/dashboard")

// Inspect what cookies were set
const cookies = await context.cookies("https://app.example.com")
console.log(cookies)

// Clear the session cookie before logging out
await context.clearCookies({ name: "session_id" })

await handstage.close()

Build docs developers (and LLMs) love