Documentation

TypeScript SDK Reference

Package browserscale-ts. All methods return a Promise; the return types below show the resolved value (the Promise<…> wrapping is implicit).

CloudBrowser

CloudBrowser is the SDK-side handle for an active browserscale browser session.

One CloudBrowser corresponds to exactly one browser context, which always has at least one page. The session is implicitly bound to its primary page server-side — the proto's page_id field is currently ignored server-side, so the SDK never sets it.

Construct via rentBrowser() / createWebSocketBrowser() — never directly.

clearCookies

method on CloudBrowser
clearCookies(): void

Deletes every cookie in the browser context.

await browser.clearCookies();
Returns
void
Throws
UNKNOWN_ERRORthe cookies could not be cleared

clearStorage

method on CloudBrowser
clearStorage(origin: string | undefined): void

Deletes localStorage in the browser context.

Parameters
originstring | undefinedif set, only this origin's storage is deleted (e.g. "https://example.com"); omit to delete all origins
// Wipe one origin.
await browser.clearStorage("https://example.com");

// Wipe everything.
await browser.clearStorage();
Returns
void
Throws
UNKNOWN_ERRORthe storage could not be cleared

click

method on CloudBrowser
click(target: Locator, opts: ClickOpts | undefined): ElementResult

Triggers a single left mouse click on the given target.

The browser scrolls the element into view if needed, moves the cursor along a human-like path, then dispatches a full mouseDown+mouseUp at a randomized point inside the element's bounding rect.

For right-click, double-click, press/release-only, or to override the target frame, pass a ClickOpts object as the second argument.

Parameters
targetLocatorlocator describing what to click; at is also valid
optsClickOpts | undefinedoptional click customization; see ClickOpts
await browser.click(css("button.submit"));
// Right double-click on a context menu trigger.
await browser.click(css("li.menu"), { button: "right", clickCount: 2 });
Returns
ElementResultElementResult with success, resolved frameId, backendNodeId, post-scroll isVisible, element bounds, and the root-viewport (rootX, rootY) where the click landed
Throws
CLICK_FAILEDthe click could not be dispatched
ELEMENT_NOT_FOUNDno element matched the locator
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty or has multiple targets set
PAGE_NOT_ALIVEthe page has been closed
TIMEOUTthe operation exceeded the server-side timeout

dragBy

method on CloudBrowser
dragBy(target: Locator, offsetX: number, offsetY: number): DragResult

Picks up the target and drops it at an offset relative to the pickup point.

The browser presses the left mouse button at a pickup point inside the element, drags along a human-like path to (pickupX+offsetX, pickupY+offsetY), then releases. at is not a valid target — drag needs a real element.

Parameters
targetLocatorlocator describing the element to pick up
offsetXnumberhorizontal distance to drag, in CSS pixels
offsetYnumbervertical distance to drag, in CSS pixels
await browser.dragBy(css(".slider .handle"), 120, 0);
Returns
DragResultDragResult with the resolved frameId, backendNodeId and the final cursor position (rootX, rootY) where the drop happened
Throws
UNKNOWN_ERRORthe drag could not be performed

dragTo

method on CloudBrowser
dragTo(target: Locator, absoluteX: number, absoluteY: number): DragResult

Picks up the target and drops it at absolute root-viewport coordinates.

Same gesture as dragBy, but the drop destination is in page coordinates rather than relative to the pickup point.

Parameters
targetLocatorlocator describing the element to pick up
absoluteXnumberhorizontal drop coordinate in the root viewport
absoluteYnumbervertical drop coordinate in the root viewport
await browser.dragTo(css(".card"), 800, 400);
Returns
DragResultDragResult with the resolved frameId, backendNodeId and the final cursor position (rootX, rootY) where the drop happened
Throws
UNKNOWN_ERRORthe drag could not be performed

evaluate

method on CloudBrowser
evaluate(expression: string): EvaluateResult<T>

Runs a JavaScript expression in the page's main frame.

The expression's return value is JSON-serialized server-side and parsed eagerly into .value. When the expression returns a DOM element the .value is null and the element metadata (backendNodeId, isVisible, bounds) is populated instead — use node in subsequent calls to act on it.

The generic T is a TypeScript hint only — there is no runtime validation that the JS expression actually returned that type.

Parameters
expressionstringJavaScript expression evaluated in the main frame
const res = await browser.evaluate<string>("document.title");
console.log(res.value);
Returns
EvaluateResult<T>EvaluateResult with either value (non-Element) or element metadata (Element)
Throws
UNKNOWN_ERRORthe expression threw or could not be compiled

evaluateInFrame

method on CloudBrowserinherits evaluate
evaluateInFrame(frameId: string, expression: string): EvaluateResult<T>

Runs a JavaScript expression in the given frame.

Same semantics as evaluate but targets a specific frame instead of the main frame. Useful for evaluating inside OOPIFs (out- of-process iframes) found via getPages. ALL_FRAMES is not supported here.

Parameters
frameIdstringid of the frame to evaluate in
expressionstringJavaScript expression evaluated in the main frame
const pages = await browser.getPages();
const iframeId = pages[0].frameTree.children[0].frameId;
await browser.evaluateInFrame(iframeId, "location.href");
Returns
EvaluateResult<T>EvaluateResult with either value (non-Element) or element metadata (Element)
Throws
UNKNOWN_ERRORthe expression threw or could not be compiled

fill

method on CloudBrowser
fill(target: Locator, text: string, opts: FillOpts | undefined): ElementResult

Clicks the target and types text into it, appending to any existing content.

The browser scrolls the element into view, moves the cursor along a human-like path, clicks to focus, then types the text character- by-character with QWERTZ keyboard simulation and human-like timing.

To overwrite the field instead of appending, pass { clearFirst: true }.

at is not a valid target — fill requires an actual element.

Parameters
targetLocatorlocator describing the input element
textstringtext to type into the element
optsFillOpts | undefinedoptional fill customization; see FillOpts
await browser.fill(css("input[name=email]"), "user@example.com");
// Wipe the field first, then type fresh content.
await browser.fill(css("input[name=email]"), "user@example.com", { clearFirst: true });
Returns
ElementResultElementResult with success, resolved frameId, backendNodeId and the root-viewport (rootX, rootY) where the element was clicked
Throws
ELEMENT_NOT_FOUNDno element matched the locator
FILL_FAILEDthe input could not be filled
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty or has multiple targets set
PAGE_NOT_ALIVEthe page has been closed
TIMEOUTthe operation exceeded the server-side timeout

getApiKey

method on CloudBrowser
getApiKey(): string

Returns the API key used to rent this session.

Returns
string

getCookies

method on CloudBrowser
getCookies(): CookieParam[]

Returns all cookies currently stored in this session's browser context.

const cookies = await browser.getCookies();
for (const c of cookies) console.log(c.name, "=", c.value);
Returns
CookieParam[]CookieParam[], one per cookie in the context
Throws
UNKNOWN_ERRORthe cookies could not be read

getDOM

method on CloudBrowser
getDOM(frameId: string, opts: GetDOMOpts | undefined): DOMResult

Returns the DOM in CDP DOM.Node shape for the requested frame.

The shape matches Chrome DevTools' Protocol DOM.Node — useful for piping into agent loops or visualizers that already speak CDP. For a much smaller agent-oriented payload, prefer getObservation instead. The cheap polling endpoint is getDOMHash.

Parameters
frameIdstringid of the frame to dump; empty string targets the main frame
optsGetDOMOpts | undefinedoptional depth: -1 full tree (default), 0 root only, N root + N descendant levels
const { dom } = await browser.getDOM();
Returns
DOMResultDOMResult with the JSON string in .dom (the .hash field is populated by getDOMHash, not by this call)
Throws
UNKNOWN_ERRORthe DOM could not be retrieved

getDOMHash

method on CloudBrowser
getDOMHash(frameId: string): string

Returns sha256:8 of the full-tree DOM JSON for cheap polling-based change detection.

Computing a hash is much cheaper than transferring the full tree — pair this with getDOM only when the hash differs from your last snapshot.

Parameters
frameIdstringid of the frame to hash; empty string targets the main frame
const hash = await browser.getDOMHash();
if (hash !== lastHash) {
// DOM changed → re-fetch
}
Returns
string16-char hex string (the first 8 bytes of sha256 of the DOM JSON)
Throws
UNKNOWN_ERRORthe hash could not be computed

getFingerprint

method on CloudBrowser
getFingerprint(): string

Returns the browser fingerprint id in use for this session.

Returns
string

getObservation

method on CloudBrowser
getObservation(opts: GetObservationOpts | undefined): ObservationResult

Returns a compact, agent-friendly description of every interactable element currently visible on the page, together with a truncated view of the surrounding text.

Intended as input for LLM/agent loops where a full DOM dump would be too large; the server filters down to elements that are actually visible and interactable.

Parameters
optsGetObservationOpts | undefinedoptional caps: maxElementsPerFrame, maxTextLength; omit either to use the server default
const obs = await browser.getObservation({ maxElementsPerFrame: 200 });
console.log(obs.text);
Returns
ObservationResultObservationResult with both a human-readable text rendering and a json payload of the structured observation
Throws
UNKNOWN_ERRORthe observation could not be produced

getPages

method on CloudBrowser
getPages(): PageInfo[]

Returns all open pages (tabs and popups) for this session's browser context.

Each PageInfo carries the page's URL, title, viewport and a full nested frame tree (out-of-process iframes are children of the page's main frame).

const pages = await browser.getPages();
for (const p of pages) console.log(p.url, p.title);
Returns
PageInfo[]PageInfo[] for every page currently open in the context
Throws
UNKNOWN_ERRORthe pages could not be enumerated

getSelection

method on CloudBrowser
getSelection(): string

Returns the current text selection.

Walks every frame and returns the first non-empty selection found — useful for "copy what the user highlighted" flows. Returns an empty string when nothing is selected anywhere.

const sel = await browser.getSelection();
console.log("user selected:", sel);
Returns
stringthe selected text, or "" when nothing is selected
Throws
UNKNOWN_ERRORthe selection could not be read

getSessionId

method on CloudBrowser
getSessionId(): string

Returns the unique server-assigned id for this browser session.

Returns
string

getStorage

method on CloudBrowser
getStorage(origin: string | undefined): StorageOriginEntry[]

Returns the localStorage contents of this session's browser context, grouped by origin.

The storage database is read directly in the browser process, so no page needs to be open. Only first-party localStorage is included — sessionStorage is per-tab and not covered.

Parameters
originstring | undefinedif set, only this origin is returned (e.g. "https://example.com"); omit to get all origins
const storage = await browser.getStorage();
for (const e of storage) {
for (const { key, value } of e.items) console.log(e.origin, key, "=", value);
}
Returns
StorageOriginEntry[]StorageOriginEntry[], one per origin with localStorage data
Throws
UNKNOWN_ERRORthe storage could not be read

highlightNode

method on CloudBrowser
highlightNode(backendNodeId: number, frameId: string): void

Paints a debug overlay over the node identified by backendNodeId.

Useful for visual debugging of agent flows — the overlay stays until the next call. Pass backendNodeId <= 0 to clear any current highlights.

Parameters
backendNodeIdnumberid of the node to highlight, or <= 0 to clear
frameIdstringid of the frame the node lives in; empty string targets the main frame
await browser.highlightNode(res.backendNodeId, res.frameId);
Returns
void
Throws
UNKNOWN_ERRORthe highlight could not be applied

insertText

method on CloudBrowser
insertText(text: string): void

Pastes text at the current caret using IME-style input.

No individual key events are dispatched; the entire string is committed at once via Input.insertText. Whatever element currently has focus receives the text. Use click or fill first if you need a specific element to be focused.

Parameters
textstringthe text to insert at the caret
await browser.insertText("hello world");
Returns
void
Throws
UNKNOWN_ERRORthe text could not be inserted

inspectAtPosition

method on CloudBrowser
inspectAtPosition(x: number, y: number): InspectResult

Hit-tests at the viewport-relative (x, y) and returns the topmost element under that point.

Mirrors what the live-UI overlay does on hover. Elements with pointer-events:none are skipped — the result is the actual click target, not the visually-topmost node. A backendNodeId === 0 in the result means nothing was found.

Parameters
xnumberviewport-relative x in CSS pixels
ynumberviewport-relative y in CSS pixels
const r = await browser.inspectAtPosition(200, 300);
console.log(r.tagName, r.textContent);
Returns
InspectResultInspectResult with the resolved backendNodeId, frameId, tag name, trimmed textContent, visibility and bounds
Throws
UNKNOWN_ERRORthe hit-test failed

loadHTML

method on CloudBrowser
loadHTML(url: string, html: string, opts: LoadHTMLOpts | undefined): void

Serves a synthetic response for the next navigation to url.

Registers a one-shot interceptor that intercepts the next request to url and replies with the supplied html and headers instead of going to the network. Useful for snapshotted pages, test fixtures, and offline replays. Pair with navigate to trigger the load.

Parameters
urlstringURL pattern that, when navigated to, returns the html
htmlstringresponse body to serve
optsLoadHTMLOpts | undefinedoptional headers and statusCode (default 200)
await browser.loadHTML("https://example.com", "<h1>hi</h1>");
await browser.navigate("https://example.com");
Returns
void
Throws
UNKNOWN_ERRORthe interceptor could not be installed

modifyRequest

method on CloudBrowser
modifyRequest(urlPattern: string, opts: {
      body?: string;
      modifications?: HeaderModification[];
      timeoutMs?: number;
    } | undefined): InterceptedRequest | null

Waits for the next request whose URL matches urlPattern, applies the supplied header modifications (and optional body replacement), then forwards the modified request.

One-shot: consumes the first matching request. Each modification is a plain HeaderModification object literal.

Parameters
urlPatternstringURL wildcard to wait for
opts{ body?: string; modifications?: HeaderModification[]; timeoutMs?: number; } | undefinedoptional body (replacement request body), modifications (header changes), and timeoutMs (per-call timeout)
const req = await browser.modifyRequest("*\/api/me", {
modifications: [
  { action: "add", name: "X-Trace", value: "abc123" },
  { action: "remove", name: "Cookie" },
],
timeoutMs: 5000,
});
console.log("forwarded headers:", req?.headers);
Returns
InterceptedRequest | nullInterceptedRequest carrying the method/URL/headers/body that were actually sent on the wire after modifications were applied; null when no request payload was reported
Throws
UNKNOWN_ERRORno matching request appeared within the timeout

moveTo

method on CloudBrowser
moveTo(target: Locator): ElementResult

Moves the mouse cursor over the given target.

The browser scrolls the target into view first if necessary, then animates the cursor along a human-like path to the element's center (or to the viewport coordinate when target is at).

Parameters
targetLocatorlocator describing where to move; at is also valid
await browser.moveTo(css("nav .menu"));
Returns
ElementResultElementResult with the resolved frameId, backendNodeId, post-scroll isVisible, element bounds and the root-viewport (rootX, rootY) where the cursor ended up
Throws
UNKNOWN_ERRORthe move could not be completed

pressKey

method on CloudBrowser
pressKey(key: string, opts: { code?: string; modifiers?: number; location?: number } | undefined): void

Fires a single key-down event.

Only the keydown half is dispatched — pair with releaseKey for a full press cycle. The event targets whichever element currently has focus.

Parameters
keystringDOM KeyboardEvent.key value (e.g. "Enter", "a", "ArrowLeft")
opts{ code?: string; modifiers?: number; location?: number } | undefinedoptional key customization: code (DOM KeyboardEvent.code, e.g. "KeyA"), modifiers (bit-flag: Alt=1, Ctrl=2, Meta=4, Shift=8), location (0=standard, 1=left, 2=right, 3=numpad)
// Ctrl+A
await browser.pressKey("a", { code: "KeyA", modifiers: 2 });
await browser.releaseKey("a", { code: "KeyA", modifiers: 2 });
Returns
void
Throws
UNKNOWN_ERRORthe event could not be dispatched

readCanvas

method on CloudBrowser
readCanvas(target: Locator, opts: ReadCanvasOpts | undefined): ReadCanvasResult

Reads the pixels of a <canvas> element directly in the renderer, bypassing the origin-clean (tainted) security check and without executing any page JavaScript — so cross-origin/tainted canvases (common in captchas) read fine where a normal toDataURL / getImageData would throw a SecurityError.

at is not a valid target — a real <canvas> element is required.

Parameters
targetLocatorlocator for the <canvas>; css, js or node
optsReadCanvasOpts | undefinedoptional format, quality, sub-rectangle and frame override; see ReadCanvasOpts
const res = await browser.readCanvas(css("#game canvas"));
await fs.writeFile("canvas.png", Buffer.from(res.dataBase64, "base64"));
// Read the left half as JPEG at quality 80.
const res = await browser.readCanvas(css("canvas"), {
format: "jpeg", quality: 80, sw: 150, sh: 300,
});
Returns
ReadCanvasResultReadCanvasResult with the base64 image in dataBase64, the canvas width/height, resolved frameId/backendNodeId and the originClean flag
Throws
ELEMENT_NOT_FOUNDno element matched the locator
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty, uses at(x,y), or has multiple targets
PAGE_NOT_ALIVEthe page has been closed
TIMEOUTthe operation exceeded the server-side timeout

releaseKey

method on CloudBrowserinherits pressKey
releaseKey(key: string, opts: { code?: string; modifiers?: number; location?: number } | undefined): void

Fires a single key-up event.

Mirror of pressKey. Same parameter semantics; use this to close a press cycle that was started with pressKey.

Parameters
keystringDOM KeyboardEvent.key value (e.g. "Enter", "a", "ArrowLeft")
opts{ code?: string; modifiers?: number; location?: number } | undefinedoptional key customization: code (DOM KeyboardEvent.code, e.g. "KeyA"), modifiers (bit-flag: Alt=1, Ctrl=2, Meta=4, Shift=8), location (0=standard, 1=left, 2=right, 3=numpad)
await browser.pressKey("Shift", { code: "ShiftLeft", location: 1 });
await browser.releaseKey("Shift", { code: "ShiftLeft", location: 1 });
Returns
void
Throws
UNKNOWN_ERRORthe event could not be dispatched

screenshot

method on CloudBrowser
screenshot(opts: ScreenshotOpts | undefined): ScreenshotResult

Captures a single image of the page's current frame and returns it as base64-encoded image bytes.

The capture uses a one-shot surface copy (the same mechanism as CDP Page.captureScreenshot), so it is independent of any active live stream and works with both GPU (hardware) and software compositing.

Parameters
optsScreenshotOpts | undefinedoptional format ("png" default, "jpeg", "webp") and quality (0-100, for jpeg/webp only); omit to use the server defaults
const shot = await browser.screenshot({ format: "png" });
await fs.writeFile("page.png", Buffer.from(shot.dataBase64, "base64"));
Returns
ScreenshotResultScreenshotResult with the base64 image in dataBase64 and the physical pixel width/height
Throws
UNKNOWN_ERRORthe screenshot could not be captured

scrollTo

method on CloudBrowser
scrollTo(target: Locator): ElementResult

Scrolls the given element into view.

Whatever scroll container is closest to the element does the scrolling — nested scroll containers and out-of-process iframe chains are walked automatically. at is not a valid target here; scrolling needs a real element.

Parameters
targetLocatorlocator describing the element to bring into view; at is rejected
await browser.scrollTo(css("#footer"));
Returns
ElementResultElementResult with the resolved frameId, backendNodeId, post-scroll isVisible and the element's bounds after the scroll
Throws
UNKNOWN_ERRORthe element could not be scrolled into view

selectByIndex

method on CloudBrowser
selectByIndex(target: Locator, index: number, opts: SelectOpts | undefined): SelectOptionResult

Picks the <option> at the zero-based index inside the targeted <select> element.

Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via opts.fireEvents = false).

at is not a valid target — select requires an actual <select> element.

Parameters
targetLocatorlocator describing the <select> element
indexnumberzero-based option index
optsSelectOpts | undefinedoptional select customization; see SelectOpts
await browser.selectByIndex(css("select#country"), 2);
// Pick the option silently, no input/change events.
await browser.selectByIndex(css("select#hidden"), 0, { fireEvents: false });
Returns
SelectOptionResultSelectOptionResult with the resolved selectedIndex, selectedValue and selectedText after the change
Throws
ELEMENT_NOT_FOUNDno element matched the locator
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty or has multiple targets set
PAGE_NOT_ALIVEthe page has been closed
SELECT_FAILEDthe option could not be selected (out of range, or element is not a `<select>`)
TIMEOUTthe operation exceeded the server-side timeout

selectByText

method on CloudBrowserinherits selectByIndex
selectByText(target: Locator, text: string, opts: SelectOpts | undefined): SelectOptionResult

Picks the <option> whose visible (trimmed) text matches the given string exactly.

Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via opts.fireEvents = false).

at is not a valid target — select requires an actual <select> element.

Parameters
targetLocatorlocator describing the <select> element
textstringthe visible option text to match
optsSelectOpts | undefinedoptional select customization; see SelectOpts
await browser.selectByText(css("select#country"), "Germany");
Returns
SelectOptionResultSelectOptionResult with the resolved selectedIndex, selectedValue and selectedText after the change
Throws
ELEMENT_NOT_FOUNDno element matched the locator
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty or has multiple targets set
PAGE_NOT_ALIVEthe page has been closed
SELECT_FAILEDthe option could not be selected (out of range, or element is not a `<select>`)
TIMEOUTthe operation exceeded the server-side timeout

selectByValue

method on CloudBrowserinherits selectByIndex
selectByValue(target: Locator, value: string, opts: SelectOpts | undefined): SelectOptionResult

Picks the <option> whose value attribute matches the given string exactly.

Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via opts.fireEvents = false).

at is not a valid target — select requires an actual <select> element.

Parameters
targetLocatorlocator describing the <select> element
valuestringthe value attribute to match
optsSelectOpts | undefinedoptional select customization; see SelectOpts
await browser.selectByValue(css("select#country"), "DE");
Returns
SelectOptionResultSelectOptionResult with the resolved selectedIndex, selectedValue and selectedText after the change
Throws
ELEMENT_NOT_FOUNDno element matched the locator
FRAME_NOT_FOUNDthe requested frame does not exist
INVALID_LOCATORtarget is empty or has multiple targets set
PAGE_NOT_ALIVEthe page has been closed
SELECT_FAILEDthe option could not be selected (out of range, or element is not a `<select>`)
TIMEOUTthe operation exceeded the server-side timeout

setBlockList

method on CloudBrowser
setBlockList(patterns: string[]): void

Replaces the session's URL blocklist.

Any request whose URL matches one of the supplied patterns is blocked before it leaves the browser. Patterns are simple URL wildcards (* matches any character span). Pass an empty array to clear the blocklist and let everything through.

Parameters
patternsstring[]URL wildcards to block; empty array clears the list
await browser.setBlockList([
"*.doubleclick.net/*",
"*googletagmanager.com*",
]);
Returns
void
Throws
UNKNOWN_ERRORthe blocklist could not be applied

setCookies

method on CloudBrowser
setCookies(cookies: CookieParam[]): void

Writes the supplied cookies into the browser context.

Existing cookies with the same (name, domain, path) tuple are overwritten. Pass an empty array for a no-op.

Parameters
cookiesCookieParam[]cookies to write; empty array is a no-op
await browser.setCookies([
{ name: "auth", value: "tok", domain: "example.com", path: "/" },
]);
Returns
void
Throws
UNKNOWN_ERRORthe cookies could not be written

setProxy

method on CloudBrowser
setProxy(proxyHost: string, proxyPort: number, proxyUsername: string, proxyPassword: string): void

Changes the runtime proxy for this session.

Takes effect for new requests immediately; in-flight requests keep their original routing. Pass an empty proxyHost to clear the proxy and route directly.

Parameters
proxyHoststringupstream proxy host; empty disables the proxy
proxyPortnumberupstream proxy port; ignored when proxyHost is empty
proxyUsernamestringproxy auth user; empty for unauthenticated proxies
proxyPasswordstringproxy auth password; empty for unauthenticated proxies
await browser.setProxy("proxy.example.com", 8080, "user", "pass");
Returns
void
Throws
UNKNOWN_ERRORthe proxy could not be applied

setStaticPaths

method on CloudBrowser
setStaticPaths(blobName: string, patterns: string[]): void

Configures the session to serve cached static responses for requests matching the given patterns from blobName.

Useful for replaying frozen page assets (HTML/JS/CSS/images) without hitting the origin every time. The cache backend itself is configured server-side. Pass an empty patterns array to disable caching for this session.

Parameters
blobNamestringserver-side identifier of the snapshot to serve from
patternsstring[]URL wildcards to redirect to the cache; empty disables
await browser.setStaticPaths("snap-2026-05", ["*.example.com/*"]);
Returns
void
Throws
UNKNOWN_ERRORthe static paths could not be configured

setStorage

method on CloudBrowser
setStorage(storage: StorageOriginEntry[]): void

Writes localStorage entries into the browser context, grouped by origin.

Accepts the same structure getStorage() returns, so a dump can be fed back verbatim. Existing keys are overwritten. Works without any open page; pages that are already open will not observe the writes until they reload.

Parameters
storageStorageOriginEntry[]entries to write, grouped by origin
await browser.setStorage([
{
  origin: "https://example.com",
  items: [
    { key: "token", value: "abc123" },
    { key: "theme", value: "dark" },
  ],
},
]);
Returns
void
Throws
UNKNOWN_ERRORthe storage could not be written

solveCaptcha

method on CloudBrowser
solveCaptcha(opts: { timeoutMs?: number; retryAmount?: number } | undefined): string

Detects and solves the first supported bot-challenge it finds anywhere on the page.

Detection covers the common challenge types you run into in the wild. The challenge is completed in-page server-side (the resulting token / bypass cookies are wired into the page automatically), so callers can ignore the returned string.

Parameters
opts{ timeoutMs?: number; retryAmount?: number } | undefinedoptional timeoutMs (how long to wait for a captcha to appear; omit for server default 60s) and retryAmount (failures tolerated before giving up)
await browser.solveCaptcha({ retryAmount: 2 });
Returns
stringempty string on success — the solution is applied server-side
Throws
UNKNOWN_ERRORno captcha appeared within timeoutMs, or the detected captcha could not be solved within retryAmount attempts

wait

method on CloudBrowserinherits waitAny
wait(condition: Locator, opts: WaitOpts | undefined): WaitResult

Blocks until the given locator matches.

Shortcut for waitAny(condition, opts). See waitAny for timeout handling, per-locator visible/steady defaults and the list of locators that are not valid wait conditions.

Parameters
conditionLocatorthe single locator to wait for
optsWaitOpts | undefinedoptional wait customization (timeoutMs)
await browser.wait(css(".success"));
Returns
WaitResultWaitResult for the first matching condition
Throws
UNKNOWN_ERRORthe wait timed out or a condition was invalid

waitAny

method on CloudBrowser
waitAny(conditions: Locator[], opts: WaitOpts | undefined): WaitResult

Blocks until any of the supplied locators matches.

When several conditions are supplied, the first one to match wins; the others are abandoned. The returned WaitResult's .index points to the entry in conditions that matched.

Defaults applied automatically: - timeout: 30000 ms — override via opts.timeoutMs - per-locator visible/steady: true / 500 for css() and js() locators. For js() expressions returning a non-Element value both flags are no-ops. Override with .visible(false) / .steady(ms) on individual locators.

node and at are not valid wait conditions — they only make sense as action targets — and throw at send time.

Parameters
conditionsLocator[]one or more Locators to wait for; must be non-empty
optsWaitOpts | undefinedoptional wait customization (timeoutMs)
const r = await browser.waitAny(
[css(".success"), js("window.__ready === true")],
{ timeoutMs: 5000 },
);
console.log("matched index:", r.index);
Returns
WaitResultWaitResult for the first matching condition
Throws
UNKNOWN_ERRORthe wait timed out or a condition was invalid

waitForAnyRequest

method on CloudBrowser
waitForAnyRequest(patterns: RequestPattern[], opts: { timeoutMs?: number } | undefined): { index: number; request: InterceptedRequest | null }

Blocks until the next request whose URL matches one of the supplied patterns is observed.

Returns the matched pattern's index and the captured request. When patternsi.abort is true the request is dropped with an empty 200 response instead of being sent to the network.

Parameters
patternsRequestPattern[]one or more URL patterns (with optional abort flags)
opts{ timeoutMs?: number } | undefinedoptional timeoutMs; omit to use the server default
const { index, request } = await browser.waitForAnyRequest(
[{ url: "*\/api/login" }],
{ timeoutMs: 5000 },
);
console.log(index, request?.method, request?.url);
Returns
{ index: number; request: InterceptedRequest | null }object with index (matched pattern index) and request (the captured method/URL/headers/body; null if intercepted with no body)
Throws
UNKNOWN_ERRORthe wait timed out or no patterns were supplied

waitForAnyResponse

method on CloudBrowserinherits waitForAnyRequest
waitForAnyResponse(patterns: RequestPattern[], opts: { timeoutMs?: number } | undefined): { index: number; response: InterceptedResponse | null }

Blocks until the next response whose URL matches one of the supplied patterns is observed.

Same shape as waitForAnyRequest but on the response phase. When patternsi.abort is true the page receives an empty 200 instead of the real response.

Parameters
patternsRequestPattern[]one or more URL patterns (with optional abort flags)
opts{ timeoutMs?: number } | undefinedoptional timeoutMs; omit to use the server default
const { index, response } = await browser.waitForAnyResponse(
[{ url: "*\/api/login" }],
{ timeoutMs: 5000 },
);
console.log(index, response?.statusCode);
Returns
{ index: number; response: InterceptedResponse | null }object with index (matched pattern index) and response (the captured status/headers/body; null if no body was returned)
Throws
UNKNOWN_ERRORthe wait timed out or no patterns were supplied

Locator

Locator is the universal "what element / what condition" type. It is used both as a wait condition (passed to wait()/waitAny()) and as a target for element actions (passed to click(), fill(), …).

Not every field is meaningful in every context: - selector / jsExpression → both wait and actions - backendNodeId → actions only (wait rejects it) - visible / steadyMs → wait only (silently ignored by actions) - x / y → actions only (wait rejects it) - frameId → both, may be overridden by call-level opts.inFrame

Use the css() / js() / node() / at() constructors instead of building this class by hand.

Modifiers (visible, steady, inFrame, inAllFrames) are immutable — they return a new Locator and leave the original untouched, so it's safe to share a base locator across calls.

inAllFrames

method on Locator
inAllFrames(): Locator

Scopes this Locator to every frame.

Equivalent to .inFrame(AllFrames). Use this when an element might appear inside any of several frames and you do not want to enumerate them.

await browser.wait(css("button.consent").inAllFrames());
Returns
Locatora new Locator scoped to all frames

inFrame

method on Locator
inFrame(frameId: string): Locator

Scopes this Locator to a specific frameId.

Use the frameId from a previous result or CloudBrowser.getPages to target elements inside a known iframe.

Parameters
frameIdstringid of the frame to scope to
const pages = await browser.getPages();
const iframeId = pages[0].frameTree.children[0].frameId;
await browser.click(css("button").inFrame(iframeId));
Returns
Locatora new Locator scoped to that frame

steady

method on Locator
steady(ms: number): Locator

Requires the element to keep a stable position and size for at least ms milliseconds before the wait matches.

Pass 0 to disable the default DefaultSteadyMs (500). Has no effect for js() expressions that return a non-Element value, nor when used as an action target.

Parameters
msnumbersteady-state duration in milliseconds; 0 disables
await browser.wait(css(".banner").steady(0));
Returns
Locatora new Locator with the override applied

visible

method on Locator
visible(v: boolean): Locator

Enforces or disables the visibility check for this Locator's wait condition.

Pass false to opt out of the default DefaultVisible (true). Has no effect when used as an action target — actions never check visibility before dispatching.

Parameters
vbooleantrue to require visibility, false to skip the check
await browser.wait(css("#hidden").visible(false));
Returns
Locatora new Locator with the override applied

BrowserConfig

Configuration for renting a browser session. Create with the required parameters, then chain optional setters.

withCountryCode

method on BrowserConfig
withCountryCode(countryCode: string): BrowserConfig

Sets the geo-IP country code for the rented session.

Drives both the assigned exit-IP region and the locale defaults (Accept-Language, timezone fallback) when those are not overridden separately.

Parameters
countryCodestringISO-3166 country code (e.g. "DE", "US")
new BrowserConfig(apiKey, 600, "", 0, "", "").withCountryCode("DE");
Returns
BrowserConfigthis BrowserConfig for chaining

withFingerprint

method on BrowserConfig
withFingerprint(fingerprint: string): BrowserConfig

Pins a specific browser fingerprint id for the session.

When omitted the server picks a fingerprint based on the country code. Pass a known id (e.g. one returned by a previous rental) to keep fingerprints stable across sessions.

Parameters
fingerprintstringserver-side fingerprint id
new BrowserConfig(apiKey, 600, "", 0, "", "").withFingerprint("fp_abc123");
Returns
BrowserConfigthis BrowserConfig for chaining

withTimezone

method on BrowserConfig
withTimezone(timezone: string): BrowserConfig

Sets the IANA timezone for the rented session.

Parameters
timezonestringIANA timezone (e.g. "Europe/Berlin")
new BrowserConfig(apiKey, 600, "", 0, "", "").withTimezone("Europe/Berlin");
Returns
BrowserConfigthis BrowserConfig for chaining

Functions

at

function
at(x: number, y: number): Locator

at targets viewport coordinates instead of an element.

Useful for clicking inside a canvas, hovering decorative regions, or dispatching events at synthetic positions. Action-only — using it in wait() throws at send time. Note that only click and moveTo accept at; scrollTo, drag, fill and select all require a real element.

Parameters
xnumberviewport-relative x in CSS pixels
ynumberviewport-relative y in CSS pixels
// Click at canvas-relative coordinates.
await browser.click(at(120, 240));
Returns
LocatorLocator usable only as an action target

createWebSocketBrowser

function
createWebSocketBrowser(wsUrl: string, sessionId: string, apiKey: string, fingerprint: string): CloudBrowser

Attaches a CloudBrowser to an existing session over a raw WebSocket transport.

Use this from a browser context: the WebSocket transport framing is defined by WebSocketTransport and is served directly by the browserscale session host. The session must already exist server-side; unlike rentBrowser this does not call the rent API. Closing the returned handle (via CloudBrowser.stopBrowser) only closes the transport — the rental stays alive.

Parameters
wsUrlstringWebSocket URL (ws:// or wss://) of the session host
sessionIdstringid of the existing session
apiKeystringAPI key authorizing access to the session
fingerprintstringbrowser fingerprint id; empty if unknown
const browser = createWebSocketBrowser(
"wss://session-abc.browserscale.example.com/ws",
sessionId,
apiKey,
);
await browser.navigate("https://example.com");
Returns
CloudBrowserCloudBrowser attached to the existing session

css

function
css(selector: string): Locator

css waits for / targets an element matching the given CSS selector.

When used in CloudBrowser.wait/CloudBrowser.waitAny, the returned Locator carries the SDK defaults DefaultVisible (true) and DefaultSteadyMs (500). Override per call with .visible(false) / .steady(ms) (use .steady(0) to disable the steady check).

When used as an action target (click, fill, …) the visible/steady fields are ignored — there are no corresponding fields on the action requests.

Parameters
selectorstringCSS selector matching the element
// As a wait condition.
await browser.wait(css("button.submit"));
// As an action target.
await browser.click(css("button.submit"));
Returns
LocatorLocator usable as a wait condition or as an action target

js

function
js(expression: string): Locator

js waits for / targets the result of a JavaScript expression.

Same wait defaults as css (DefaultVisible=true, DefaultSteadyMs=500); these only apply when the expression returns a DOM Element. For non-Element truthy values (boolean, string, number, plain object) both fields are no-ops and the condition matches as soon as the value is truthy. Use .visible(false) / .steady(0) to opt out.

Parameters
expressionstringJavaScript expression evaluated in the target frame
await browser.wait(js("window.__ready === true"));
Returns
LocatorLocator usable as a wait condition or as an action target

node

function
node(backendNodeId: number): Locator

node targets an element by its DevTools backendNodeId.

Use this when you already have a backendNodeId from a previous result (e.g. a wait or evaluate result) and want to act on the exact same element without re-resolving by selector. Action-only — using it in wait() throws at send time.

Parameters
backendNodeIdnumberDevTools backendNodeId of the target element
const r = await browser.click(css("button.open"));
await browser.click(node(r.backendNodeId));
Returns
LocatorLocator usable only as an action target

rentBrowser

function
rentBrowser(config: BrowserConfig): CloudBrowser

Rents a new browser session and returns a connected handle.

Calls the browserscale rent endpoint with the supplied BrowserConfig, opens a gRPC connection to the assigned session host, and returns a ready-to-use CloudBrowser. Closing the returned handle (via CloudBrowser.stopBrowser) also releases the rental.

Parameters
configBrowserConfigrental parameters
const cfg = new BrowserConfig("sk_…", 600, "", 0, "", "");
const browser = await rentBrowser(cfg);
try {
await browser.navigate("https://example.com");
} finally {
await browser.stopBrowser();
}
Returns
CloudBrowserCloudBrowser ready to drive the rented session
Throws
UNKNOWN_ERRORthe rent API rejected the request or the gRPC connection could not be established

setApiEndpoint

function
setApiEndpoint(endpoint: string): void

Overrides the HTTP rent/stop endpoint.

Defaults to https://api.browserscale.cloud. Call this before any rentBrowser / stopBrowser call if you need to point at a private browserscale deployment.

Parameters
endpointstringbase URL of the rent/stop service, with no trailing slash
setApiEndpoint("https://browserscale.internal.example.com");
Returns
void

stopBrowser

function
stopBrowser(apiKey: string, sessionId: string): void

Releases a session without needing a CloudBrowser handle.

Useful when a session id was persisted across processes and the rental outlived the original handle. Only calls the rent stop endpoint; there is no gRPC connection to close in this form.

Parameters
apiKeystringAPI key the session was rented with
sessionIdstringid of the session to release
await stopBrowser(apiKey, sessionId);
Returns
void
Throws
UNKNOWN_ERRORthe stop API rejected the request

Types

BrowserScaleError

class

BrowserScaleError is the single error type thrown by all SDK methods. It wraps either: - a client-side validation failure (bad locator, missing patterns, …) - a server-side gRPC error (Connect's ConnectError, available as cause)

Catch it with instanceof BrowserScaleError:

try { await browser.click(css("#btn")); } catch (e) { if (e instanceof BrowserScaleError) { ... } }

Button

type alias
type Button = "left" | "right" | "middle"

Mouse button used by CloudBrowser.click.

ClickAction

type alias
type ClickAction = "click" | "press" | "release"

Mouse phase performed by CloudBrowser.click.

ClickOpts

interface

Optional customization for CloudBrowser.click. All fields are optional; missing or zero values mean "use the server default".

Fields
inFrame?stringOverride the locator's frame. Omit to use the locator's own Locator.inFrame (or the main frame). Pass a specific frameId or AllFrames to search elsewhere.
button?ButtonMouse button. Default "left".
clickCount?number1 = single click (default), 2 = double-click.
action?ClickAction"click" (default) performs a full mouseDown+mouseUp. "press" only dispatches mouseDown, "release" only mouseUp at the current cursor position.

CookieParam

interface

CookieParam is one entry returned by getCookies() or passed to setCookies().

Fields
namestring
valuestring
url?string
domainstring
pathstring
secure?boolean
httpOnly?boolean
sameSite?string
expires?number
priority?string
sourceScheme?string
sourcePort?number
partitionKey?CookiePartitionKey

CookiePartitionKey

interface

Partition metadata for partitioned cookies (CHIPS).

Fields
topLevelSitestring
hasCrossSiteAncestorboolean

DOMResult

interface

DOMResult is the full-tree DOM snapshot returned by CloudBrowser.getDOM, plus its sha256:8 hash for cheap change detection.

Fields
hashstring
domstring

DragResult

interface

DragResult is the outcome of a CloudBrowser.drag gesture: the resolved source element and the start/end coordinates of the performed drag.

Fields
successboolean
frameIdstring
backendNodeIdnumber
startXnumber
startYnumber
endXnumber
endYnumber

ElementResult

interface

ElementResult is the outcome of an element interaction such as CloudBrowser.click, CloudBrowser.fill or CloudBrowser.scrollTo: the resolved element plus the root-relative coordinates the action was performed at.

Fields
successboolean
frameIdstring
backendNodeIdnumber
isVisibleboolean
boundsRect
rootXnumber
rootYnumber

EvaluateResult

interface

EvaluateResult carries the outcome of a JS evaluate call.

If the expression returned a DOM element, backendNodeId/isVisible/bounds are populated and value is null. Otherwise value holds the parsed JSON value (string/number/boolean/array/object/null). On parse failure value falls back to the raw server string so the caller is never empty-handed.

The optional generic T types the .value field for convenience — this is purely a TS hint, not a runtime guarantee.

Fields
valueT
backendNodeIdnumber
isVisibleboolean
boundsRect

FillOpts

interface

Optional customization for CloudBrowser.fill. All fields are optional; missing values mean "use the server default".

Fields
inFrame?stringOverride the locator's frame. Omit to use the locator's own Locator.inFrame (or the main frame). Pass a specific frameId or AllFrames to search elsewhere.
clearFirst?booleantrue wipes the field's existing content with Ctrl+A, Delete before typing. Default (false) appends to whatever is already in the field.

FrameInfo

interface

FrameInfo describes a single frame within a page's frame tree.

Fields
frameIdstring
urlstring
isOOPIFboolean
hasJSContextboolean
isLoadingboolean
isVisibleboolean
absoluteRectRect
relativeRectRect
childrenFrameInfo[]

GetDOMOpts

interface

Depth used by getDOM(). 0 = whole tree (default), >0 = limited depth.

Fields
depth?number

GetObservationOpts

interface

Optional customization for CloudBrowser.getObservation.

Fields
maxElementsPerFrame?numberDefault 200.
maxTextLength?numberDefault 200.

HeaderModification

interface

HeaderModification is one entry passed to CloudBrowser.modifyRequest. Write it as a plain object literal.

Fields
actionHeaderModificationAction"add" inserts a new header, "edit" replaces an existing header's value, "remove" drops the header.
namestringHeader name the action applies to.
value?stringHeader value for add/edit; ignored for remove.
before?stringPositions an "add" immediately before the named existing header; otherwise the header is appended at the end. Ignored for edit/remove.
after?stringPositions an "add" immediately after the named existing header. Mirror of before; ignored for edit/remove.

HeaderModificationAction

type alias
type HeaderModificationAction = "add" | "edit" | "remove"

Action verb for a HeaderModification.

InspectResult

interface

InspectResult describes the topmost element hit at viewport-relative (x, y). backendNodeId === 0 means nothing was found at that position.

Fields
backendNodeIdnumber
frameIdstring
tagNamestring
textContentstring
isVisibleboolean
boundsRect

InterceptedRequest

interface

InterceptedRequest describes an outgoing request captured by CloudBrowser.waitForAnyRequest.

Fields
methodstring
urlstring
headersHeader[]
bodystring
resourceTypestring

InterceptedResponse

interface

InterceptedResponse describes a network response captured by CloudBrowser.waitForAnyResponse.

Fields
urlstring
statusCodenumber
headersHeader[]
bodystring

LoadHTMLOpts

interface

Optional customization for CloudBrowser.loadHTML.

Fields
headers?{ name: string; value: string }[]Extra headers to attach to the synthetic response.
statusCode?numberDefault 200.

ObservationResult

interface

ObservationResult is the compact page snapshot returned by CloudBrowser.getObservation — the visible, interactive elements rendered as prompt-friendly text and as JSON.

Fields
textstring
jsonstring

PageInfo

interface

PageInfo describes an open page (tab or popup) inside a browser context.

Fields
pageIdstring
browserContextIdstring
urlstring
titlestring
viewportRect
frameTreeFrameInfo

ReadCanvasOpts

interface

Optional customization for CloudBrowser.readCanvas.

Fields
inFrame?stringOverride the locator's frame. Omit to use the locator's own Locator.inFrame (or the main frame). Pass a specific frameId or AllFrames to search elsewhere.
format?"png" | "jpeg" | "webp" | "rgba"Output encoding: "png" (default), "jpeg", "webp", or "rgba" for the raw unpremultiplied RGBA pixel buffer.
quality?numberEncode quality 0-100 for "jpeg"/"webp" (ignored otherwise). Default 90.
sx?numberOptional sub-rectangle in canvas pixels (mirrors getImageData(sx, sy, sw, sh)). The full canvas is read when sw/sh are omitted or <= 0.
sy?number
sw?number
sh?number

ReadCanvasResult

interface

ReadCanvasResult is the pixel readback of a <canvas>, returned by CloudBrowser.readCanvas. dataBase64 holds the encoded image bytes (PNG by default) or the raw RGBA buffer when format is "rgba". originClean reports whether the canvas was untainted (informational — the read succeeds either way).

Fields
successboolean
frameIdstring
backendNodeIdnumber
dataBase64string
widthnumber
heightnumber
originCleanboolean

Rect

interface

Rect describes a position and size in CSS pixels.

Fields
xnumber
ynumber
widthnumber
heightnumber

RentResponse

interface

RentResponse is the result of renting a browser via the REST API.

Fields
sessionIdstring
grpcUrlstring
countryCodestring
timezonestring
acceptLanguagestring
fingerprintstring

RequestPattern

interface

RequestPattern matches a URL pattern in waitForAnyRequest/Response. Set abort to true to drop the request with an empty 200 response instead of letting it through to the network.

Fields
urlstring
abort?booleanDefault false.

ScreenshotOpts

interface

Optional customization for CloudBrowser.screenshot.

Fields
format?"png" | "jpeg" | "webp"Image format: "png" (default), "jpeg", or "webp".
quality?numberEncode quality 0-100 for "jpeg"/"webp" (ignored for "png"). Default 90.

ScreenshotResult

interface

ScreenshotResult is a single captured image of the page, returned by CloudBrowser.screenshot. dataBase64 holds the encoded image bytes (PNG by default); width and height are in physical pixels.

Fields
dataBase64string
widthnumber
heightnumber

SelectOptionResult

interface

SelectOptionResult reports which option a selectByXxx call ended up selecting.

Fields
selectedIndexnumber
selectedValuestring
selectedTextstring

SelectOpts

interface

Optional customization for CloudBrowser.selectByIndex, CloudBrowser.selectByValue and CloudBrowser.selectByText.

Fields
inFrame?stringOverride the locator's frame. Omit to use the locator's own Locator.inFrame (or the main frame). Pass a specific frameId or AllFrames to search elsewhere.
fireEvents?booleanfalse suppresses change/input events. Default (true) fires the standard events after the selection.

StorageItem

interface

StorageItem is a single localStorage key/value pair.

Fields
keystring
valuestring

StorageOriginEntry

interface

StorageOriginEntry groups the localStorage entries of one origin (e.g. "https://example.com"). getStorage() returns these and setStorage() accepts the same shape, so a dump can be fed back verbatim.

Fields
originstring
itemsStorageItem[]

WaitOpts

interface

Optional customization for CloudBrowser.wait / CloudBrowser.waitForAny.

Fields
timeoutMs?numberDefault DefaultWaitTimeoutMs (30 000 ms).

WaitResult

interface

WaitResult is the outcome of a CloudBrowser.wait / CloudBrowser.waitForAny call: which condition matched (index, in argument order) and where the matched element lives.

Fields
indexnumber
frameIdstring
backendNodeIdnumber
isVisibleboolean
boundsRect

WaitUntil

type alias
type WaitUntil = "load" | "domcontentloaded" | "networkidle"

Lifecycle event CloudBrowser.navigate waits for before returning.