Go SDK Reference
github.com/browserscale/browserscale-go. Every method takes ctx context.Context as its first argument and returns an explicit error; both are omitted from the signatures below for brevity.CloudBrowser
CloudBrowser is the SDK-side handle for an active browserscale browser session.
One CloudBrowser corresponds to exactly one browser context, which 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.
AcceptLanguage
method on CloudBrowserAcceptLanguage() → stringAcceptLanguage returns the Accept-Language header value the session was provisioned with.
stringAddReaction
method on CloudBrowserAddReaction(match *Locator) → stringAddReaction registers a one-shot "reaction": a background poller (one shared loop per page) watches for the match locator and, as soon as it matches, clicks it with the full smart-click machinery (scroll, human path, occlusion gate, evade) — then removes itself. The poller yields to any in-flight input action and only fires while the pointer is idle, so a reaction naturally slots into the gaps of a retrying foreground action (e.g. it dismisses a newsletter modal blocking a CloudBrowser.Click, after which the click's own retry succeeds). Reactions are scoped to the page and torn down automatically when the page/session ends.
match must be a CSS or JS Locator — Node and At are rejected. Use Locator.InAllFrames to watch every frame and Locator.Visible(false) to opt out of the default visibility gate.
| match | *Locator | the CSS/JS locator to watch for |
// Auto-dismiss a consent button whenever it appears, in any frame.
id, err := browser.AddReaction(ctx, browserscale.CSS("button#accept").InAllFrames())
if err != nil {
log.Fatal(err)
}
_ = idstringthe reactionId (pass to CloudBrowser.RemoveReaction)| INVALID_LOCATOR | match is nil, has no selector/JS expression, or is |
AddReactionWith
method on CloudBrowserinherits AddReactionAddReactionWith(match *Locator, opts ReactionOpts) → stringAddReactionWith is the customizable variant of CloudBrowser.AddReaction.
match must be a CSS or JS Locator — Node and At are rejected. Use Locator.InAllFrames to watch every frame and Locator.Visible(false) to opt out of the default visibility gate.
| match | *Locator | the CSS/JS locator to watch for |
| opts | ReactionOpts | reaction customization; see ReactionOpts |
// Watch for a newsletter modal, but click its close "X" instead.
id, err := browser.AddReactionWith(ctx,
browserscale.CSS("#newsletter-modal"),
browserscale.ReactionOpts{On: browserscale.CSS(".modal-close")},
)stringthe reactionId (pass to CloudBrowser.RemoveReaction)| INVALID_LOCATOR | match is nil, has no selector/JS expression, or is |
ApiKey
method on CloudBrowserApiKey() → stringApiKey returns the API key used to rent this session.
stringClearCookies
method on CloudBrowserClearCookies()ClearCookies deletes every cookie in the browser context.
_ = browser.ClearCookies(ctx)| UNKNOWN_ERROR | the cookies could not be cleared |
ClearStorage
method on CloudBrowserClearStorage(origin string)ClearStorage deletes localStorage in the browser context.
| origin | string | if non-empty, only this origin's storage is deleted (e.g. "https://example.com"); empty string deletes all origins |
// Wipe one origin.
_ = browser.ClearStorage(ctx, "https://example.com")
// Wipe everything.
_ = browser.ClearStorage(ctx, "")| UNKNOWN_ERROR | the storage could not be cleared |
Click
method on CloudBrowserClick(target *Locator) → *ElementResultClick 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.
| target | *Locator | locator describing what to click; At is also valid |
res, err := browser.Click(ctx, browserscale.CSS("button.submit"))
if err != nil {
var ce *browserscale.ClickError
if errors.As(err, &ce) {
log.Printf("blocked by %s (%s)", ce.Occluder.TagName, ce.Code)
}
log.Fatal(err)
}*ElementResult*ElementResult with success, resolved frameId, backendNodeId,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
ClickWith
method on CloudBrowserinherits ClickClickWith(target *Locator, opts ClickOpts) → *ElementResultClickWith is the customizable variant of CloudBrowser.Click.
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.
| target | *Locator | locator describing what to click; At is also valid |
| opts | ClickOpts | click customization; see ClickOpts |
// Right double-click on a context menu trigger.
_, err := browser.ClickWith(ctx, browserscale.CSS("li.menu"), browserscale.ClickOpts{
Button: "right",
ClickCount: 2,
})*ElementResult*ElementResult with success, resolved frameId, backendNodeId,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
Close
method on CloudBrowserinherits StopBrowserClose()Close is the defer-friendly alias for CloudBrowser.StopBrowser that uses a background context.
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.
browser, err := browserscale.RentBrowser(ctx, cfg)
if err != nil { log.Fatal(err) }
defer browser.Close()| UNKNOWN_ERROR | the stop API rejected the request |
CloseConn
method on CloudBrowserCloseConn()CloseConn closes only the gRPC connection, leaving the server-side session running.
Use this to detach without releasing the rental — the common case when you attached with ConnectSession to act on a session owned elsewhere, or when a short-lived handle should not outlive its work but the session must. Contrast with CloudBrowser.Close / CloudBrowser.StopBrowser, which also release the rental via the stop endpoint.
browser, err := browserscale.ConnectSession(ctx, grpcUrl, apiKey, sessionId)
if err != nil { log.Fatal(err) }
defer browser.CloseConn() // detach; the session keeps running| UNKNOWN_ERROR | the gRPC connection could not be closed |
CountryCode
method on CloudBrowserCountryCode() → stringCountryCode returns the ISO-3166 country code the server allocated for this session (drives geo-IP and locale defaults).
stringDragBy
method on CloudBrowserDragBy(target *Locator, offsetX float64, offsetY float64) → *DragResultDragBy 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.
| target | *Locator | locator describing the element to pick up |
| offsetX | float64 | horizontal distance to drag, in CSS pixels |
| offsetY | float64 | vertical distance to drag, in CSS pixels |
_, err := browser.DragBy(ctx, browserscale.CSS(".slider .handle"), 120, 0)
if err != nil {
log.Fatal(err)
}*DragResult*DragResult with the resolved frameId, backendNodeId and the| UNKNOWN_ERROR | the drag could not be performed |
DragTo
method on CloudBrowserDragTo(target *Locator, absoluteX float64, absoluteY float64) → *DragResultDragTo picks up the target and drops it at absolute root-viewport coordinates.
Same gesture as CloudBrowser.DragBy, but the drop destination is in page coordinates rather than relative to the pickup point.
| target | *Locator | locator describing the element to pick up |
| absoluteX | float64 | horizontal drop coordinate in the root viewport |
| absoluteY | float64 | vertical drop coordinate in the root viewport |
_, err := browser.DragTo(ctx, browserscale.CSS(".card"), 800, 400)
if err != nil {
log.Fatal(err)
}*DragResult*DragResult with the resolved frameId, backendNodeId and the| UNKNOWN_ERROR | the drag could not be performed |
Evaluate
method on CloudBrowserEvaluate(expression string) → *EvaluateResultEvaluate runs a JavaScript expression in the page's main frame.
The expression's return value is JSON-serialized server-side and parsed eagerly into EvaluateResult.Value. When the expression returns a DOM element the EvaluateResult.Value is left empty and the element metadata (BackendNodeId, IsVisible, Bounds) is populated instead — use Node(id) in subsequent calls to act on it.
| expression | string | JavaScript expression evaluated in the main frame |
res, err := browser.Evaluate(ctx, "document.title")
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Value)*EvaluateResult*EvaluateResult with either Value (for non-Element returns) or| UNKNOWN_ERROR | the expression threw or could not be compiled |
EvaluateInFrame
method on CloudBrowserinherits EvaluateEvaluateInFrame(frameId string, expression string) → *EvaluateResultEvaluateInFrame runs a JavaScript expression in the given frame.
Same semantics as CloudBrowser.Evaluate but targets a specific frame instead of the main frame. Useful for evaluating inside OOPIFs (out-of- process iframes) found via CloudBrowser.GetPages.
| frameId | string | id of the frame to evaluate in; empty falls back to the main frame |
| expression | string | JavaScript expression evaluated in the main frame |
pages, _ := browser.GetPages(ctx)
iframeId := pages[0].FrameTree.Children[0].FrameId
_, _ = browser.EvaluateInFrame(ctx, iframeId, "location.href")*EvaluateResult*EvaluateResult with either Value (for non-Element returns) or| UNKNOWN_ERROR | the expression threw or could not be compiled |
Fill
method on CloudBrowserFill(target *Locator, text string) → *ElementResultFill 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, use CloudBrowser.FillWith with ClearFirst: true.
At is not a valid target — Fill requires an actual element.
| target | *Locator | locator describing the input element |
| text | string | text to type into the element |
res, err := browser.Fill(ctx, browserscale.CSS("input[name=email]"), "user@example.com")
if err != nil {
var fe *browserscale.FillError
if errors.As(err, &fe) && fe.ClickError != nil {
log.Printf("blocked by %s", fe.ClickError.Occluder.TagName)
}
log.Fatal(err)
}
_ = res*ElementResult*ElementResult with success, resolved frameId, backendNodeId| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
FillWith
method on CloudBrowserinherits FillFillWith(target *Locator, text string, opts FillOpts) → *ElementResultFillWith is the customizable variant of CloudBrowser.Fill.
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, use CloudBrowser.FillWith with ClearFirst: true.
At is not a valid target — Fill requires an actual element.
| target | *Locator | locator describing the input element |
| text | string | text to type into the element |
| opts | FillOpts | fill customization; see FillOpts |
// Wipe the field first, then type fresh content.
_, err := browser.FillWith(ctx, browserscale.CSS("input[name=email]"), "user@example.com", browserscale.FillOpts{
ClearFirst: true,
})*ElementResult*ElementResult with success, resolved frameId, backendNodeId| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
Fingerprint
method on CloudBrowserFingerprint() → stringFingerprint returns the browser fingerprint id in use for this session.
stringGetAuthSession
method on CloudBrowserGetAuthSession() → *AuthSessionGetAuthSession exports the signed-in primary account and DBSC sessions of this browser context. Reads state in the browser process — no page needed.
Returns nil, nil when the context has neither a signed-in account nor DBSC sessions.
auth, err := browser.GetAuthSession(ctx)
if err != nil {
log.Fatal(err)
}
if auth == nil {
log.Println("no auth/DBSC state")
return
}
// persist auth, then later SetAuthSession on a fresh rent*AuthSession*AuthSession, or nil when there is nothing to export| UNKNOWN_ERROR | the auth session could not be read |
GetCookies
method on CloudBrowserGetCookies() → []CookieParamGetCookies returns all cookies currently stored in this session's browser context.
cookies, err := browser.GetCookies(ctx)
if err != nil {
log.Fatal(err)
}
for _, c := range cookies {
fmt.Println(c.Name, "=", c.Value)
}[]CookieParam[]CookieParam, one per cookie in the context| UNKNOWN_ERROR | the cookies could not be read |
GetDOM
method on CloudBrowserGetDOM(frameId string, depth int32) → stringGetDOM returns a JSON string 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 CloudBrowser.GetObservation instead.
| frameId | string | id of the frame to dump; empty targets the main frame |
| depth | int32 | tree depth: -1 for the full tree, 0 for root only, N for |
tree, err := browser.GetDOM(ctx, "", -1)
if err != nil {
log.Fatal(err)
}
fmt.Println(tree)stringJSON string in CDP DOM.Node shape| UNKNOWN_ERROR | the DOM could not be retrieved |
GetDOMHash
method on CloudBrowserGetDOMHash(frameId string) → stringGetDOMHash 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 CloudBrowser.GetDOM only when the hash differs from your last snapshot.
| frameId | string | id of the frame to hash; empty targets the main frame |
hash, err := browser.GetDOMHash(ctx, "")
if err != nil {
log.Fatal(err)
}
if hash != lastHash {
// DOM changed → re-fetch
}string16-char hex string (the first 8 bytes of sha256 of the DOM JSON)| UNKNOWN_ERROR | the hash could not be computed |
GetObservation
method on CloudBrowserGetObservation() → stringGetObservation returns a compact, frame-aware view of the visible page — the first thing to reach for on an unfamiliar page, and the cheapest way to re-read the current state afterwards.
Each frame opens with header lines carrying the URL, the title and the scroll position, then one line per visible element:
input#email47 type="email" name="loginId" value="a@b.com" required click "E-Mail"
It spans every frame, pierces open and closed shadow roots, enumerates <select> options, and reports live form state: value= is what is typed in right now (passwords as a length), checked= for boxes. The trailing quoted string is always the label or text, never the value, so an empty and a prefilled field stay distinguishable. Because the headers already carry URL, title and scroll offset, this replaces the usual handful of CloudBrowser.Evaluate probes after each step.
On what to do with the result: backendNodeId (the 47 above) is a handle for this session and can be passed straight to click/fill via Node. It does not survive a new document, so for anything you write into a script, target with CSS or JS instead — those calls return the backendNodeId they resolved to, which lets you confirm the durable anchor hits the element you saw.
obs, err := browser.GetObservation(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(obs)stringthe observation in the requested format, ready to hand to a model| UNKNOWN_ERROR | the observation could not be produced |
GetObservationWith
method on CloudBrowserinherits GetObservationGetObservationWith(opts ObservationOpts) → stringGetObservationWith is the customizable variant of CloudBrowser.GetObservation.
Each frame opens with header lines carrying the URL, the title and the scroll position, then one line per visible element:
input#email47 type="email" name="loginId" value="a@b.com" required click "E-Mail"
It spans every frame, pierces open and closed shadow roots, enumerates <select> options, and reports live form state: value= is what is typed in right now (passwords as a length), checked= for boxes. The trailing quoted string is always the label or text, never the value, so an empty and a prefilled field stay distinguishable. Because the headers already carry URL, title and scroll offset, this replaces the usual handful of CloudBrowser.Evaluate probes after each step.
On what to do with the result: backendNodeId (the 47 above) is a handle for this session and can be passed straight to click/fill via Node. It does not survive a new document, so for anything you write into a script, target with CSS or JS instead — those calls return the backendNodeId they resolved to, which lets you confirm the durable anchor hits the element you saw.
| opts | ObservationOpts | observation customization; see ObservationOpts |
// Only what is on screen right now, as structured JSON.
obs, err := browser.GetObservationWith(ctx, browserscale.ObservationOpts{
Format: "json",
ViewportOnly: true,
})
// Re-read just one form after the first full look.
obs, err = browser.GetObservationWith(ctx, browserscale.ObservationOpts{
Selector: "form#register",
})stringthe observation in the requested format, ready to hand to a model| UNKNOWN_ERROR | the observation could not be produced |
GetPages
method on CloudBrowserGetPages() → []*PageInfoGetPages 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).
pages, err := browser.GetPages(ctx)
if err != nil {
log.Fatal(err)
}
for _, p := range pages {
fmt.Println(p.Url, p.Title)
}[]*PageInfo[]*PageInfo for every page currently open in the context| UNKNOWN_ERROR | the pages could not be enumerated |
GetSelection
method on CloudBrowserGetSelection() → stringGetSelection 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.
sel, err := browser.GetSelection(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println("user selected:", sel)stringthe selected text, or "" when nothing is selected| UNKNOWN_ERROR | the selection could not be read |
GetStorage
method on CloudBrowserGetStorage(origin string) → []StorageOriginEntryGetStorage 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.
| origin | string | if non-empty, only this origin is returned (e.g. "https://example.com"); empty string returns all origins |
storage, err := browser.GetStorage(ctx, "")
if err != nil {
log.Fatal(err)
}
for _, e := range storage {
for _, item := range e.Items {
fmt.Println(e.Origin, item.Key, "=", item.Value)
}
}[]StorageOriginEntry[]StorageOriginEntry, one per origin with localStorage data| UNKNOWN_ERROR | the storage could not be read |
GetStreamConfig
method on CloudBrowserGetStreamConfig() → []IceServerGetStreamConfig returns the ICE servers (TURN URL + short-lived credentials) to put in your RTCPeerConnection BEFORE creating the offer, so it can gather relay candidates.
Live streaming is a two-step, client-offerer handshake: call GetStreamConfig, build your peer with the returned servers, create an offer, then pass its SDP to CloudBrowser.StartStream and apply the returned answer.
ice, err := browser.GetStreamConfig(ctx)
if err != nil { log.Fatal(err) }
// configure your RTCPeerConnection with ice, then create an offer …[]IceServerthe ICE servers for the client RTCPeerConnection| UNKNOWN_ERROR | TURN is not configured on the server |
GrpcUrl
method on CloudBrowserGrpcUrl() → stringGrpcUrl returns the gRPC endpoint the session is connected to.
stringHighlightNode
method on CloudBrowserHighlightNode(backendNodeId int32, frameId string)HighlightNode 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.
| backendNodeId | int32 | id of the node to highlight, or <= 0 to clear |
| frameId | string | id of the frame the node lives in; empty targets the main frame |
if err := browser.HighlightNode(ctx, res.BackendNodeId, res.FrameId); err != nil {
log.Fatal(err)
}| UNKNOWN_ERROR | the highlight could not be applied |
InsertText
method on CloudBrowserInsertText(text string)InsertText 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 CloudBrowser.Click or CloudBrowser.Fill first if you need a specific element to be focused.
| text | string | the text to insert at the caret |
if err := browser.InsertText(ctx, "hello world"); err != nil {
log.Fatal(err)
}| UNKNOWN_ERROR | the text could not be inserted |
InspectAtPosition
method on CloudBrowserInspectAtPosition(x float64, y float64) → *InspectResultInspectAtPosition 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.
| x | float64 | viewport-relative x in CSS pixels |
| y | float64 | viewport-relative y in CSS pixels |
res, err := browser.InspectAtPosition(ctx, 200, 300)
if err != nil {
log.Fatal(err)
}
fmt.Println(res.TagName, res.TextContent)*InspectResult*InspectResult with the resolved backendNodeId, frameId, tag| UNKNOWN_ERROR | the hit-test failed |
ListReactions
method on CloudBrowserListReactions() → []ReactionInfoListReactions returns the still-pending reactions registered for the current page. Reactions that have already fired (one-shot) are not included.
pending, err := browser.ListReactions(ctx)
for _, r := range pending {
log.Printf("reaction %s watching %s%s", r.ReactionID, r.MatchSelector, r.MatchJsExpression)
}[]ReactionInfothe pending reactions for the pageLoadHTML
method on CloudBrowserLoadHTML(url string, html string, headers []Header, statusCode int32)LoadHTML 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 CloudBrowser.Navigate to trigger the load.
| url | string | the URL pattern that, when navigated to, returns the html |
| html | string | the response body to serve |
| headers | []Header | extra response headers (Content-Type is set automatically) |
| statusCode | int32 | HTTP status code to serve; 0 means 200 |
_ = browser.LoadHTML(ctx, "https://example.com", "<h1>hi</h1>", nil, 0)
_, _ = browser.Navigate(ctx, "https://example.com", 0)| UNKNOWN_ERROR | the interceptor could not be installed |
ModifyRequest
method on CloudBrowserModifyRequest(urlPattern string, body string, timeoutMs float64, mods []HeaderModification) → *InterceptedRequestModifyRequest 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. Pass nil/empty mods to leave headers untouched and only override the body.
| urlPattern | string | URL wildcard to wait for |
| body | string | replacement request body; empty leaves the original body |
| timeoutMs | float64 | per-call timeout in milliseconds; 0 uses the server default |
| mods | []HeaderModification | HeaderModification entries; see HeaderModification for the fields |
req, err := browser.ModifyRequest(ctx, "*/api/me", "", 5000, []browserscale.HeaderModification{
{Action: browserscale.HeaderModificationAdd, Name: "X-Trace", Value: "abc123"},
{Action: browserscale.HeaderModificationRemove, Name: "Cookie"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println("forwarded headers:", req.Headers)*InterceptedRequest*InterceptedRequest carrying the method/URL/headers/body that| UNKNOWN_ERROR | no matching request appeared within the timeout |
MoveTo
method on CloudBrowserMoveTo(target *Locator) → *ElementResultMoveTo 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 random center area (or to the viewport coordinate when target is At).
| target | *Locator | locator describing where to move; At is also valid |
_, err := browser.MoveTo(ctx, browserscale.CSS("nav .menu"))
if err != nil {
log.Fatal(err)
}*ElementResult*ElementResult with the resolved frameId, backendNodeId,| UNKNOWN_ERROR | the move could not be completed |
PressKey
method on CloudBrowserPressKey(key string, code string, modifiers int32, location int32)PressKey fires a single key-down event.
Only the keydown half is dispatched — pair with CloudBrowser.ReleaseKey for a full press cycle. The event targets whichever element currently has focus.
| key | string | DOM KeyboardEvent.key value (e.g. "Enter", "a", "ArrowLeft") |
| code | string | DOM KeyboardEvent.code value (e.g. "Enter", "KeyA"); empty falls back to key |
| modifiers | int32 | bit-flag combination: Alt=1, Ctrl=2, Meta=4, Shift=8 |
| location | int32 | DOM KeyboardEvent.location: 0=standard, 1=left, 2=right, 3=numpad |
// Ctrl+A
_ = browser.PressKey(ctx, "a", "KeyA", 2, 0)
_ = browser.ReleaseKey(ctx, "a", "KeyA", 2, 0)| UNKNOWN_ERROR | the event could not be dispatched |
ReadCanvas
method on CloudBrowserReadCanvas(target *Locator) → *ReadCanvasResultReadCanvas 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.
| target | *Locator | locator for the <canvas>; CSS, JS or Node |
res, err := browser.ReadCanvas(ctx, browserscale.CSS("#game canvas"))
if err != nil {
log.Fatal(err)
}
img, _ := base64.StdEncoding.DecodeString(res.DataBase64)
os.WriteFile("canvas.png", img, 0o644)*ReadCanvasResult*ReadCanvasResult with the base64 image in DataBase64, the canvas| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty, uses At(x,y), or has multiple targets |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
ReadCanvasWith
method on CloudBrowserinherits ReadCanvasReadCanvasWith(target *Locator, opts ReadCanvasOpts) → *ReadCanvasResultReadCanvasWith is the customizable variant of CloudBrowser.ReadCanvas.
| target | *Locator | locator for the <canvas>; CSS, JS or Node |
| opts | ReadCanvasOpts | format, quality, sub-rectangle and frame override; see ReadCanvasOpts |
// Read the left half of the canvas as JPEG at quality 80.
res, err := browser.ReadCanvasWith(ctx, browserscale.CSS("canvas"),
browserscale.ReadCanvasOpts{Format: "jpeg", Quality: 80, SW: 150, SH: 300})*ReadCanvasResult*ReadCanvasResult with the base64 image in DataBase64, the canvas| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty, uses At(x,y), or has multiple targets |
| PAGE_NOT_ALIVE | the page has been closed |
| TIMEOUT | the operation exceeded the server-side timeout |
ReleaseKey
method on CloudBrowserinherits PressKeyReleaseKey(key string, code string, modifiers int32, location int32)ReleaseKey fires a single key-up event.
Mirror of CloudBrowser.PressKey. Same parameter semantics; use this to close a press cycle that was started with PressKey.
| key | string | DOM KeyboardEvent.key value (e.g. "Enter", "a", "ArrowLeft") |
| code | string | DOM KeyboardEvent.code value (e.g. "Enter", "KeyA"); empty falls back to key |
| modifiers | int32 | bit-flag combination: Alt=1, Ctrl=2, Meta=4, Shift=8 |
| location | int32 | DOM KeyboardEvent.location: 0=standard, 1=left, 2=right, 3=numpad |
_ = browser.PressKey(ctx, "Shift", "ShiftLeft", 0, 1)
_ = browser.ReleaseKey(ctx, "Shift", "ShiftLeft", 0, 1)| UNKNOWN_ERROR | the event could not be dispatched |
RemoveReaction
method on CloudBrowserRemoveReaction(reactionID string) → boolRemoveReaction removes a pending reaction by id. It returns false if the reaction had already fired (one-shot) or was never registered.
| reactionID | string | id returned by CloudBrowser.AddReaction |
removed, err := browser.RemoveReaction(ctx, id)booltrue if a pending reaction with this id existed and was removedScreenshot
method on CloudBrowserScreenshot(format string, quality int32) → *ScreenshotResultScreenshot 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.
| format | string | "png" (default), "jpeg", or "webp"; pass "" for PNG |
| quality | int32 | encode quality 0-100 for "jpeg"/"webp" (ignored for |
shot, err := browser.Screenshot(ctx, "png", 0)
if err != nil {
log.Fatal(err)
}
img, _ := base64.StdEncoding.DecodeString(shot.DataBase64)
os.WriteFile("page.png", img, 0o644)*ScreenshotResult*ScreenshotResult with the base64 image in DataBase64 and the| UNKNOWN_ERROR | the screenshot could not be captured |
ScrollTo
method on CloudBrowserScrollTo(target *Locator) → *ElementResultScrollTo 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.
| target | *Locator | locator describing the element to bring into view; |
_, err := browser.ScrollTo(ctx, browserscale.CSS("#footer"))
if err != nil {
log.Fatal(err)
}*ElementResult*ElementResult with the resolved frameId, backendNodeId,| UNKNOWN_ERROR | the element could not be scrolled into view |
SelectByIndex
method on CloudBrowserSelectByIndex(target *Locator, index int32) → *SelectOptionResultSelectByIndex 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 CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| index | int32 | zero-based option index |
_, err := browser.SelectByIndex(ctx, browserscale.CSS("select#country"), 2)*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SelectByIndexWith
method on CloudBrowserinherits SelectByIndexSelectByIndexWith(target *Locator, index int32, opts SelectOpts) → *SelectOptionResultSelectByIndexWith is the customizable variant of CloudBrowser.SelectByIndex.
Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| index | int32 | zero-based option index |
| opts | SelectOpts | select customization; see SelectOpts |
// Pick the option silently, no input/change events.
_, err := browser.SelectByIndexWith(ctx, browserscale.CSS("select#hidden"), 0, browserscale.SelectOpts{
NoEvents: true,
})*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SelectByText
method on CloudBrowserinherits SelectByIndexSelectByText(target *Locator, text string) → *SelectOptionResultSelectByText 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 CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| text | string | the visible option text to match |
_, err := browser.SelectByText(ctx, browserscale.CSS("select#country"), "Germany")*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SelectByTextWith
method on CloudBrowserinherits SelectByTextSelectByTextWith(target *Locator, text string, opts SelectOpts) → *SelectOptionResultSelectByTextWith is the customizable variant of CloudBrowser.SelectByText.
Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| text | string | the visible option text to match |
| opts | SelectOpts | select customization; see SelectOpts |
_, err := browser.SelectByTextWith(ctx, browserscale.CSS("select#country"), "Germany", browserscale.SelectOpts{
NoEvents: true,
})*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SelectByValue
method on CloudBrowserinherits SelectByIndexSelectByValue(target *Locator, value string) → *SelectOptionResultSelectByValue 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 CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| value | string | the value attribute to match |
_, err := browser.SelectByValue(ctx, browserscale.CSS("select#country"), "DE")*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SelectByValueWith
method on CloudBrowserinherits SelectByValueSelectByValueWith(target *Locator, value string, opts SelectOpts) → *SelectOptionResultSelectByValueWith is the customizable variant of CloudBrowser.SelectByValue.
Sets the option as selected on the targeted <select>, then fires the standard input + change events (unless suppressed via CloudBrowser.SelectByIndexWith with SelectOpts.NoEvents).
At is not a valid target — Select requires an actual <select> element.
| target | *Locator | locator describing the <select> element |
| value | string | the value attribute to match |
| opts | SelectOpts | select customization; see SelectOpts |
_, err := browser.SelectByValueWith(ctx, browserscale.CSS("select#country"), "DE", browserscale.SelectOpts{
NoEvents: true,
})*SelectOptionResult*SelectOptionResult with the resolved selectedIndex,| ELEMENT_NOT_FOUND | no element matched the locator |
| FRAME_NOT_FOUND | the requested frame does not exist |
| INVALID_LOCATOR | target is empty or has multiple targets set |
| PAGE_NOT_ALIVE | the page has been closed |
| SELECT_FAILED | the option could not be selected |
| TIMEOUT | the operation exceeded the server-side timeout |
SessionId
method on CloudBrowserSessionId() → stringSessionId returns the unique server-assigned id for this browser session.
stringSetAuthSession
method on CloudBrowserSetAuthSession(session AuthSession)SetAuthSession imports an auth session so the context comes up signed in (and syncing if SyncConsent) with its DBSC sessions restored.
Call before navigating. Pair with SetCookies / SetStorage to fully restore a persona.
| session | AuthSession | session as returned by GetAuthSession |
_ = browser.SetAuthSession(ctx, *saved)
_ = browser.Navigate(ctx, "https://mail.google.com")| UNKNOWN_ERROR | the auth session could not be written |
SetBlockList
method on CloudBrowserSetBlockList(patterns []string)SetBlockList 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 a nil/empty slice to clear the blocklist and let everything through.
| patterns | []string | URL wildcards to block; nil or empty clears the list |
_ = browser.SetBlockList(ctx, []string{
"*.doubleclick.net/*",
"*googletagmanager.com*",
})| UNKNOWN_ERROR | the blocklist could not be applied |
SetCookies
method on CloudBrowserSetCookies(cookies []CookieParam)SetCookies writes the supplied cookies into the browser context.
Existing cookies with the same (name, domain, path) tuple are overwritten. Pass an empty slice for a no-op.
| cookies | []CookieParam | cookies to write; empty slice is a no-op |
secure := true
httpOnly := true
sameSite := "Lax"
_ = browser.SetCookies(ctx, []browserscale.CookieParam{
{
Name: "auth",
Value: "tok",
Domain: "example.com",
Path: "/",
Secure: &secure,
HTTPOnly: &httpOnly,
SameSite: &sameSite,
},
})| UNKNOWN_ERROR | the cookies could not be written |
SetProxy
method on CloudBrowserSetProxy(proxyHost string, proxyPort int32, proxyUsername string, proxyPassword string)SetProxy 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.
| proxyHost | string | upstream proxy host; empty disables the proxy |
| proxyPort | int32 | upstream proxy port; ignored when proxyHost is empty |
| proxyUsername | string | proxy auth user (empty for unauthenticated proxies) |
| proxyPassword | string | proxy auth password (empty for unauthenticated proxies) |
_ = browser.SetProxy(ctx, "proxy.example.com", 8080, "user", "pass")| UNKNOWN_ERROR | the proxy could not be applied |
SetStaticPaths
method on CloudBrowserSetStaticPaths(blobName string, patterns []string)SetStaticPaths 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 (blob storage, CDN, …) is configured server-side. Pass an empty patterns slice to disable caching for this session.
| blobName | string | server-side identifier of the snapshot to serve from |
| patterns | []string | URL wildcards to redirect to the cache; nil/empty disables |
_ = browser.SetStaticPaths(ctx, "snap-2026-05", []string{"*.example.com/*"})| UNKNOWN_ERROR | the static paths could not be configured |
SetStorage
method on CloudBrowserSetStorage(storage []StorageOriginEntry)SetStorage 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.
| storage | []StorageOriginEntry | entries to write, grouped by origin |
_ = browser.SetStorage(ctx, []browserscale.StorageOriginEntry{
{
Origin: "https://example.com",
Items: []browserscale.StorageItem{
{Key: "token", Value: "abc123"},
{Key: "theme", Value: "dark"},
},
},
})| UNKNOWN_ERROR | the storage could not be written |
SolveCaptcha
method on CloudBrowserSolveCaptcha(timeoutMs int32, retryAmount int32) → stringSolveCaptcha 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.
| timeoutMs | int32 | how long to wait for a captcha to appear, in |
| retryAmount | int32 | number of retries on a failed solve before giving up |
if _, err := browser.SolveCaptcha(ctx, 0, 2); err != nil {
log.Fatal(err)
}stringempty string on success — the solution is applied server-side| UNKNOWN_ERROR | no captcha appeared within timeoutMs, or the |
StartStream
method on CloudBrowserStartStream(offerSDP string) → stringStartStream answers your WebRTC SDP offer and starts streaming the page as a video track, returning the SDP answer to set as your peer's remote description. The browser is the answerer; you are the offerer (see CloudBrowser.GetStreamConfig for the credentials to build the offer).
| offerSDP | string | your RTCPeerConnection's SDP offer |
answer, err := browser.StartStream(ctx, offer.SDP)
if err != nil { log.Fatal(err) }
// peer.SetRemoteDescription({type: "answer", sdp: answer}) …stringthe SDP answer to apply as the remote description| UNKNOWN_ERROR | the offer was empty, TURN is unconfigured, or the |
StopStream
method on CloudBrowserStopStream()StopStream tears down the live video stream for the session's page. It is safe to call even if no stream is running.
if err := browser.StopStream(ctx); err != nil { log.Fatal(err) }| UNKNOWN_ERROR | the stream could not be stopped |
Timezone
method on CloudBrowserTimezone() → stringTimezone returns the IANA timezone the session was provisioned with (e.g. "Europe/Berlin").
stringType
method on CloudBrowserType(text string, clearFirst bool)Type types text into the currently focused element as a per-key stream of real keyboard events (keyDown/char/keyUp with the context's QWERTZ/QWERTY layout and human cadence) — unlike CloudBrowser.InsertText, a single IME-style commit with no key events.
Type is intentionally UNtargeted and loose: it does not locate or focus any element and does NOT pin focus, so the page is free to route keys and move focus between fields mid-stream — ideal for one-time-code / OTP inputs that auto-advance to the next box on each digit. To type one specific field that must stay focused for the whole value, use CloudBrowser.Fill instead (strict, target-bound, per-key focus-verified).
Nothing is focused for you: CloudBrowser.Click (or Fill) the field first, or otherwise ensure focus, before calling Type.
| text | string | the text to type as real key events |
| clearFirst | bool | when true, clears the focused field (Ctrl+A, Delete) first |
// OTP field that auto-advances across boxes.
_, _ = browser.Click(ctx, browserscale.CSS("input.otp-0"))
if err := browser.Type(ctx, "123456", false); err != nil {
log.Fatal(err)
}| UNKNOWN_ERROR | the page/context was torn down mid-stream |
Wait
method on CloudBrowserWait(args ...WaitArg) → *WaitResultWait blocks until any of the supplied locators matches.
Pass one or more Locators (built with CSS, JS, …) plus optional wait-level arguments such as Timeout. When several locators are supplied, the first one to match wins; the others are abandoned.
Defaults applied automatically: - timeout: DefaultWaitTimeoutMs (30s) — override with Timeout - per-locator visible/steady: DefaultVisible (true) and DefaultSteadyMs (500) for CSS and JS locators. For JS expressions returning a non-Element value (bool/string/number/object) both flags are no-ops. Override with Locator.Visible / Locator.Steady on individual locators.
Node and At are not valid wait conditions — they only make sense as action targets — and produce an error at send time.
| args | ...WaitArg | one or more Locators plus optional wait-level options; |
// Wait for either a success banner or a JS condition, max 5s.
res, err := browser.Wait(ctx,
browserscale.CSS(".success"),
browserscale.JS("window.__ready === true"),
browserscale.Timeout(5000),
)
if err != nil {
var we *browserscale.WaitError
if errors.As(err, &we) {
for _, c := range we.Conditions {
log.Printf("condition %d: %s", c.Index, c.State)
}
}
log.Fatal(err)
}
_ = res*WaitResult*WaitResult for the first matching condition (carries theWaitForAnyRequest
method on CloudBrowserWaitForAnyRequest(timeoutMs float64, patterns []RequestPattern) → int32, *InterceptedRequestWaitForAnyRequest 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.
| timeoutMs | float64 | per-call timeout in milliseconds; 0 uses the server default |
| patterns | []RequestPattern | one or more URL patterns (with optional Abort flags) |
idx, req, err := browser.WaitForAnyRequest(ctx, 5000, []browserscale.RequestPattern{
{URL: "*/api/login"},
})
if err != nil {
log.Fatal(err)
}
_ = idx
fmt.Println(req.Method, req.Url)int32, *InterceptedRequestint32 index of the matched pattern, *InterceptedRequest with| UNKNOWN_ERROR | the wait timed out or no patterns were supplied |
WaitForAnyResponse
method on CloudBrowserinherits WaitForAnyRequestWaitForAnyResponse(timeoutMs float64, patterns []RequestPattern) → int32, *InterceptedResponseWaitForAnyResponse blocks until the next response whose URL matches one of the supplied patterns is observed.
Same shape as CloudBrowser.WaitForAnyRequest but on the response phase. When patternsi.Abort is true the page receives an empty 200 instead of the real response.
| timeoutMs | float64 | per-call timeout in milliseconds; 0 uses the server default |
| patterns | []RequestPattern | one or more URL patterns (with optional Abort flags) |
idx, resp, err := browser.WaitForAnyResponse(ctx, 5000, []browserscale.RequestPattern{
{URL: "*/api/login"},
})
if err != nil {
log.Fatal(err)
}
_ = idx
fmt.Println(resp.StatusCode)int32, *InterceptedResponseint32 index of the matched pattern, *InterceptedResponse with| UNKNOWN_ERROR | the 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) and as a target for element actions (passed to Click, Fill, etc.).
Not every field is meaningful in every context: - selector / jsExpression → both wait and actions - backendNodeId → actions only (Wait rejects it) - visible / steadyTime → wait only (silently ignored by actions) - x / y → actions only (Wait rejects it) - frameId → both, may be overridden by call-level browserscale.InFrame() / browserscale.InAllFrames() options
Use the CSS / JS / Node / At constructors instead of building this struct by hand.
InAllFrames
method on LocatorInAllFrames() → *LocatorInAllFrames 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.
_, _ = browser.Wait(ctx, browserscale.CSS("button.consent").InAllFrames())*Locatorthe same Locator for chainingInFrame
method on LocatorInFrame(id string) → *LocatorInFrame scopes this Locator to a specific frameId.
Use the frameId from a previous result or CloudBrowser.GetPages to target elements inside a known iframe.
| id | string | id of the frame to scope to |
pages, _ := browser.GetPages(ctx)
iframeId := pages[0].FrameTree.Children[0].FrameId
_, _ = browser.Click(ctx, browserscale.CSS("button").InFrame(iframeId))*Locatorthe same Locator for chainingSteady
method on LocatorSteady(ms float64) → *LocatorSteady 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 the Locator is used as an action target.
| ms | float64 | steady-state duration in milliseconds; 0 disables |
_, _ = browser.Wait(ctx, browserscale.CSS(".banner").Steady(0))*Locatorthe same Locator for chainingVisible
method on LocatorVisible(v bool) → *LocatorVisible 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 the Locator is used as an action target — actions never check visibility before dispatching.
| v | bool | true to require visibility, false to skip the check |
_, _ = browser.Wait(ctx, browserscale.CSS("#hidden").Visible(false))*Locatorthe same Locator for chainingBrowserConfig
BrowserConfig holds all parameters for renting a browser session. Use NewBrowserConfig with the required fields, then chain optional setters.
UnstableWithFakeGpu
method on BrowserConfigUnstableWithFakeGpu(renderer string, vendor string, extensions []string) → *BrowserConfigUnstableWithFakeGpu overrides WebGL UNMASKED_RENDERER_WEBGL, UNMASKED_VENDOR_WEBGL and getSupportedExtensions().
Unstable API — likely to be reshaped or removed without notice. Use only when you have a specific WebGL-fingerprint requirement.
| renderer | string | value to return for UNMASKED_RENDERER_WEBGL |
| vendor | string | value to return for UNMASKED_VENDOR_WEBGL |
| extensions | []string | list returned by getSupportedExtensions() |
cfg.UnstableWithFakeGpu("ANGLE", "Google Inc.", []string{"OES_texture_float"})*BrowserConfigthe modified *BrowserConfig for chainingWithCountryCode
method on BrowserConfigWithCountryCode(countryCode string) → *BrowserConfigWithCountryCode 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.
| countryCode | string | ISO-3166 country code (e.g. "DE", "US") |
cfg := browserscale.NewBrowserConfig(apiKey, 600, "", 0, "", "").WithCountryCode("DE")*BrowserConfigthe modified *BrowserConfig for chainingWithFingerprint
method on BrowserConfigWithFingerprint(fingerprint string) → *BrowserConfigWithFingerprint 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.
| fingerprint | string | server-side fingerprint id |
cfg := browserscale.NewBrowserConfig(apiKey, 600, "", 0, "", "").WithFingerprint("fp_abc123")*BrowserConfigthe modified *BrowserConfig for chainingWithTimezone
method on BrowserConfigWithTimezone(timezone string) → *BrowserConfigWithTimezone sets the IANA timezone for the rented session.
| timezone | string | IANA timezone (e.g. "Europe/Berlin") |
cfg := browserscale.NewBrowserConfig(apiKey, 600, "", 0, "", "").WithTimezone("Europe/Berlin")*BrowserConfigthe modified *BrowserConfig for chainingMoveError
MoveError is returned as the error from CloudBrowser.MoveTo when the target could not be located. A move has no occlusion notion, so this is the only semantic failure. Implements the error interface; recover with errors.As.
| Code | string | Code is currently always "not_found". |
| Message | string | Message is a human-readable description. |
Error
method on MoveErrorError() → stringError implements the error interface.
stringFunctions
At
functionAt(x float64, y float64) → *LocatorAt 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 CloudBrowser.Wait returns an error at send time. Note that only Click and MoveTo accept At; Scroll, Drag, Fill and Select all require a real element.
| x | float64 | viewport-relative x in CSS pixels |
| y | float64 | viewport-relative y in CSS pixels |
// Click at canvas-relative coordinates.
_, _ = browser.Click(ctx, browserscale.At(120, 240))*Locator*Locator usable only as an action targetConnectSession
functionConnectSession(grpcUrl string, apiKey string, sessionId string) → *CloudBrowserConnectSession attaches to an already-running session via gRPC.
Use this when you have a session id and gRPC URL from a previous RentBrowser (for example stored across process restarts). Unlike RentBrowser this does not call the rent API — the session must already exist server-side.
| grpcUrl | string | the session's gRPC endpoint as returned by CloudBrowser.GrpcUrl, |
| apiKey | string | API key authorizing access to the session |
| sessionId | string | id of the existing session to attach to |
browser, err := browserscale.ConnectSession(ctx, "grpcs://api.browserscale.cloud:443", apiKey, sessionId)
if err != nil {
log.Fatal(err)
}
defer browser.Close()*CloudBrowser*CloudBrowser attached to the existing session; the returned| UNKNOWN_ERROR | the gRPC connection could not be opened |
CSS
functionCSS(selector string) → *LocatorCSS waits for / targets an element matching the given CSS selector.
When used in CloudBrowser.Wait, the returned Locator carries the SDK defaults DefaultVisible (true) and DefaultSteadyMs (500). Override per call with Locator.Visible / Locator.Steady (use .Steady(0) to disable the steady check).
When used as an action target (Click, etc.) the visible/steady fields are ignored — there are no corresponding fields on the action requests.
| selector | string | CSS selector matching the element |
// As a wait condition.
_, _ = browser.Wait(ctx, browserscale.CSS("button.submit"))
// As an action target.
_, _ = browser.Click(ctx, browserscale.CSS("button.submit"))*Locator*Locator usable as a wait condition or as an action targetJS
functionJS(expression string) → *LocatorJS 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 Locator.Visible(false) / Locator.Steady(0) on the returned Locator to opt out.
| expression | string | JavaScript expression evaluated in the target frame |
_, _ = browser.Wait(ctx, browserscale.JS("window.__ready === true"))*Locator*Locator usable as a wait condition or as an action targetNewBrowserConfig
functionNewBrowserConfig(apiKey string, rentDuration int, proxyHost string, proxyPort int, proxyUsername string, proxyPassword string) → *BrowserConfigNewBrowserConfig returns a BrowserConfig populated with the required rental fields. Optional fields are configured via the chainable With… setters before passing the config to RentBrowser.
| apiKey | string | API key authenticating the rental |
| rentDuration | int | lifetime of the session in seconds |
| proxyHost | string | upstream proxy host (empty string disables the proxy) |
| proxyPort | int | upstream proxy port (ignored when proxyHost is empty) |
| proxyUsername | string | proxy auth user (empty for unauthenticated proxies) |
| proxyPassword | string | proxy auth password (empty for unauthenticated proxies) |
cfg := browserscale.NewBrowserConfig("sk_…", 600, "", 0, "", "").
WithCountryCode("DE").
WithTimezone("Europe/Berlin")*BrowserConfig*BrowserConfig ready to be customized further or passed to RentBrowserNode
functionNode(backendNodeId int32) → *LocatorNode targets an element by its DevTools backendNodeId.
Use this when you already have a backendNodeId from a previous result (e.g. WaitResult or EvaluateResult) and want to act on the exact same element without re-resolving by selector. Action-only — using it in CloudBrowser.Wait returns an error at send time.
| backendNodeId | int32 | DevTools backendNodeId of the target element |
res, _ := browser.Click(ctx, browserscale.CSS("button.open"))
_, _ = browser.Click(ctx, browserscale.Node(res.BackendNodeId))*Locator*Locator usable only as an action targetPtr
functionPtr(v T) → *TPtr returns a pointer to v. It is a convenience for the SDK's optional pointer fields where a zero value is meaningful and must be distinguished from "unset" — e.g. FillOpts.TimeoutMs: browserscale.Ptr(0.0) makes Fill one-shot, whereas a nil field takes the server default.
| v | T |
*TRentBrowser
functionRentBrowser(config *BrowserConfig) → *CloudBrowserRentBrowser 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. On any failure the partially-rented session is best-effort released.
| config | *BrowserConfig | rental parameters built with NewBrowserConfig |
cfg := browserscale.NewBrowserConfig("sk_…", 600, "", 0, "", "")
browser, err := browserscale.RentBrowser(ctx, cfg)
if err != nil {
log.Fatal(err)
}
defer browser.Close()*CloudBrowser*CloudBrowser ready to drive the rented session; call| UNKNOWN_ERROR | the rent API rejected the request or the gRPC |
SetApiEndpoint
functionSetApiEndpoint(endpoint string)SetApiEndpoint 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.
| endpoint | string | base URL of the rent/stop service, with no trailing slash |
browserscale.SetApiEndpoint("https://browserscale.internal.example.com")StopBrowser
functionStopBrowser(apiKey string, sessionId string)StopBrowser 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.
| apiKey | string | API key the session was rented with |
| sessionId | string | id of the session to release |
_ = browserscale.StopBrowser(context.Background(), apiKey, sessionId)| UNKNOWN_ERROR | the stop API rejected the request |
Timeout
functionTimeout(ms float64) → WaitArgTimeout overrides the CloudBrowser.Wait timeout.
When omitted, DefaultWaitTimeoutMs (30s) is used. Pass once per Wait call as one of the variadic arguments.
| ms | float64 | timeout in milliseconds |
_, _ = browser.Wait(ctx, browserscale.CSS("#done"), browserscale.Timeout(5000))WaitArga WaitArg suitable for passing to WaitTypes
AuthSession
structAuthSession is a portable snapshot of a context's signed-in Google account and/or DBSC sessions. All fields are optional so a context that only has DBSC (no primary account) or only a sign-in (no DBSC) round-trips.
Pair with CloudBrowser.GetCookies / CloudBrowser.SetCookies and CloudBrowser.GetStorage / CloudBrowser.SetStorage to fully move a persona between fresh contexts. Call CloudBrowser.SetAuthSession before navigating.
| GaiaID? | *string | |
| Email? | *string | |
| RefreshToken? | *string | |
| WrappedBindingKey? | *string | |
| SigninScopedDeviceID? | *string | |
| SyncConsent? | *bool | |
| DbscSessions | []DbscSession |
ClickError
structClickError is returned as the error from CloudBrowser.Click / CloudBrowser.ClickWith when the click did not land (the element was occluded and the point could not be reached). It implements the error interface, so the ordinary res, err := browser.Click(...) shape keeps working; recover the structured detail with errors.As:
res, err := browser.Click(ctx, browserscale.CSS("#buy")) var ce *browserscale.ClickError if errors.As(err, &ce) { // ce.Code, ce.Message, ce.Occluder describe the blocker }
| Code | string | Code is a machine-stable failure code, e.g. "occluded_no_reachable_point" (target fully covered, no exposed part reachable) or "occluded_after_evade" (a reposition was tried but the target was still covered). |
| Message | string | Message is a human-readable description. |
| Occluder? | *OccluderInfo | Occluder is the intercepting element (present for occlusion codes). |
| EvadeAttempted | bool | EvadeAttempted reports whether a pointer reposition was tried before giving up. |
ClickOpts
structClickOpts customizes a CloudBrowser.ClickWith call. Zero/empty values mean "use the server default".
| InFrame | string | InFrame overrides the locator's own frame. Empty = use the locator's frame (or the main frame if none). Pass a specific frameId, or AllFrames, to search elsewhere. |
| Button | string | Button is the mouse button to use. Valid: "left" (default), "right", "middle". |
| ClickCount | int32 | ClickCount controls single/double-click. 0 or 1 = single click (default), 2 = double-click. |
| Action | string | Action selects the mouse phase. "" or "click" = full mouseDown+mouseUp (default). "press" only dispatches mouseDown. "release" only dispatches mouseUp at the current cursor position. |
CookieParam
structCookieParam is one cookie returned by GetCookies / passed to SetCookies. Name, Value, Domain, and Path are the common required identity fields; optional attributes mirror the browser's CookieParam shape: URL, Secure, HTTPOnly, SameSite, Expires, Priority, SourceScheme, SourcePort, and PartitionKey.
| Name | string | |
| Value | string | |
| URL? | *string | |
| Domain | string | |
| Path | string | |
| Secure? | *bool | |
| HTTPOnly? | *bool | |
| SameSite? | *string | |
| Expires? | *float64 | |
| Priority? | *string | |
| SourceScheme? | *string | |
| SourcePort? | *int | |
| PartitionKey? | *CookiePartitionKey |
CookiePartitionKey
structCookiePartitionKey describes CHIPS partitioning metadata for partitioned cookies.
| TopLevelSite | string | |
| HasCrossSiteAncestor | bool |
DbscSession
structDbscSession is one Device Bound Session Credentials entry.
| Site | string | Site is the serialized schemeful site key, e.g. "https://google.com". |
| Session | string | Session is base64 of the serialized DBSC Session proto (includes the wrapped binding key; portable under WRC's software key provider). |
DragError
structDragError is returned as the error from CloudBrowser.Drag variants when the source element could not be acquired/pressed. Drag picks up the source with the same smart click as CloudBrowser.Click, so a pre-drag failure is a click failure: Code/Message mirror it and the full click diagnostics live under ClickError. Implements the error interface; recover with errors.As.
| Code | string | Code is mirrored from the underlying click failure: "not_found", "occluded_no_reachable_point" or "occluded_after_evade". |
| Message | string | Message is a human-readable description (mirrors ClickError.Message). |
| ClickError? | *ClickError | ClickError is the underlying click-core failure at the source pickup. |
DragResult
structDragResult is the outcome of a CloudBrowser.Drag gesture: the resolved source element and the start/end coordinates of the performed drag.
| Success | bool | |
| FrameId | string | |
| BackendNodeId | int32 | |
| StartX | float64 | |
| StartY | float64 | |
| EndX | float64 | |
| EndY | float64 |
ElementRef
structElementRef is a lightweight descriptor of an element — enough to identify it (and decide what to do) without another DOM round-trip. It names the element that stole focus in a FillError focus-loss failure.
| BackendNodeId | int32 | BackendNodeId is the element's stable backend node id. |
| TagName | string | TagName is the upper-case tag name, e.g. "INPUT", "BUTTON", "DIV". |
| Id | string | Id is the id attribute, if present. |
| Name | string | Name is the name attribute, if present. |
| ClassName | string | ClassName is the class attribute, if present. |
| InputType | string | InputType is the <input> type, if the element is an <input>. |
| Text | string | Text is a whitespace-collapsed textContent/value snippet (max 120 chars). |
| Editable | bool | Editable is true when the element is itself an editable text sink (input / textarea / contenteditable). |
ElementResult
structElementResult 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.
| Success | bool | |
| FrameId | string | |
| BackendNodeId | int32 | |
| IsVisible | bool | |
| Bounds | Rect | |
| RootX | float64 | |
| RootY | float64 |
EvaluateResult
structEvaluateResult carries the outcome of a JS evaluate call.
If the expression returned a DOM element, BackendNodeId/IsVisible/Bounds are populated and Value is nil. Otherwise Value holds the parsed JSON value (string/number/bool/[]any/mapstringany/nil). On parse failure Value falls back to the raw server string so the caller is never empty- handed.
| Value | any | |
| BackendNodeId | int32 | |
| IsVisible | bool | |
| Bounds | Rect |
FillError
structFillError is returned as the error from CloudBrowser.Fill / CloudBrowser.FillWith when the field could not be focused/typed. Fill focuses the field with the exact same smart click as CloudBrowser.Click, so a pre-typing failure is a click failure: Code/Message mirror it and the full click diagnostics live under ClickError. It implements the error interface, so the ordinary res, err := browser.Fill(...) shape keeps working; recover the detail with errors.As:
res, err := browser.Fill(ctx, browserscale.CSS("#email"), "a@b.com") var fe *browserscale.FillError if errors.As(err, &fe) && fe.ClickError != nil { // fe.ClickError.Occluder describes the blocker }
| Code | string | Code is the machine-stable failure code. Click-phase codes ("not_found", "occluded_no_reachable_point", "occluded_after_evade") mirror the underlying focus click, with diagnostics under ClickError. The focus codes are "focus_stolen" (another element took focus — FocusedElement names it; Fill is strictly target-bound and will not type into the thief) and "focus_lost" (focus left the target and nothing is focused). For untargeted stream typing that lets focus move (e.g. OTP), use Type. |
| Message | string | Message is a human-readable description (mirrors ClickError.Message). |
| ClickError? | *ClickError | ClickError is the underlying click-core failure (locate or occlusion) that prevented focusing/typing. Present for the click-phase codes; absent for "focus_stolen"/"focus_lost". |
| FocusedBackendNodeId | int32 | FocusedBackendNodeId is the node that held focus when Fill gave up (0 if nothing was focused), for the "focus_stolen"/"focus_lost" codes. |
| FocusedElement? | *ElementRef | FocusedElement describes the element that grabbed focus instead of the target ("focus_stolen"), so you can act on it (e.g. a consent button). |
| TargetEditable? | *bool | TargetEditable and TargetValueLength report the fill target's own state at the point of failure (the focus codes): whether it is still an editable text sink and its current text length. Both nil when not reported. |
| TargetValueLength? | *int |
FillOpts
structFillOpts customizes a CloudBrowser.FillWith call. Zero/empty values mean "use the server default".
| InFrame | string | InFrame overrides the locator's own frame. Empty = use the locator's frame (or the main frame if none). Pass a specific frameId, or AllFrames, to search elsewhere. |
| ClearFirst | bool | ClearFirst, when true, wipes the field's existing content with Ctrl+A, Delete before typing. Default (false) appends to whatever is already there. |
| TimeoutMs? | *float64 | TimeoutMs bounds focus acquisition (locate, scroll, settle, un-occlude) in ms, mirroring the click timeout. nil = server default (5000). It is a pointer because 0 is meaningful: browserscale.Ptr(0.0) makes Fill one-shot (no retry). |
| SteadyMs? | *float64 | SteadyMs is the settle window in ms before the focus click, mirroring the click steady-time. nil = server default (750); browserscale.Ptr(0.0) skips settling. |
FrameInfo
structFrameInfo describes a single frame within a page's frame tree.
Header
structHeader is a single HTTP header (name/value pair) on an intercepted request or response.
| Name | string | |
| Value | string |
HeaderModification
structHeaderModification is one entry passed to CloudBrowser.ModifyRequest. Build it as a plain struct literal.
| Action | HeaderModificationAction | Action selects what happens: HeaderModificationAdd inserts a new header, HeaderModificationEdit replaces an existing header's value, HeaderModificationRemove drops the header. |
| Name | string | Name is the header name the action applies to. |
| Value | string | Value is the header value for add/edit; ignored for remove. |
| Before | string | Before positions an "add" immediately before the named existing header; otherwise the header is appended at the end. Ignored for edit/remove. |
| After | string | After positions an "add" immediately after the named existing header. Mirror of Before; ignored for edit/remove. |
HeaderModificationAction
type aliastype HeaderModificationAction = stringHeaderModificationAction is the verb of a HeaderModification. Matches the add/edit/remove action strings; use the HeaderModificationXxx constants.
IceServer
structIceServer is one entry for a WebRTC RTCPeerConnection's ICE configuration: a TURN (or STUN) URL plus the short-lived credentials to authenticate with it. Pass these to your peer before creating the SDP offer.
| URLs | []string | URLs are the ICE server URLs (e.g. "turn:relay.example.com:3478?transport=udp"). |
| Username | string | Username is the short-lived TURN REST username (empty for plain STUN). |
| Credential | string | Credential is the short-lived TURN REST credential (empty for plain STUN). |
InspectResult
structInspectResult describes the topmost element hit at viewport-relative (x, y). BackendNodeId == 0 means nothing was found at that position.
| BackendNodeId | int32 | |
| FrameId | string | |
| TagName | string | |
| TextContent | string | |
| IsVisible | bool | |
| Bounds | Rect |
InterceptedRequest
structInterceptedRequest describes an outgoing request captured by CloudBrowser.WaitForAnyRequest.
| Method | string | |
| Url | string | |
| Headers | []Header | |
| Body | string | |
| ResourceType | string |
InterceptedResponse
structInterceptedResponse describes a network response captured by CloudBrowser.WaitForAnyResponse.
| Url | string | |
| StatusCode | int32 | |
| Headers | []Header | |
| Body | string |
ObservationOpts
structObservationOpts customizes a CloudBrowser.GetObservationWith call. Zero/empty values mean "use the server default".
| Format | string | Format is "text" (default) for the compact line format meant to be handed to a model as-is, or "json" for the structured form. Only the requested representation is built, so asking for one does not cost the other. |
| MaxElementsPerFrame | int32 | MaxElementsPerFrame caps emitted elements per frame. 0 = server default (800). This is a safety net against runaway documents; MaxTotalTokens is the limit that normally binds. |
| MaxTextLength | int32 | MaxTextLength caps human-readable strings (labels, text, values) in characters. 0 = server default (300). Identifier-like attributes (type, name, role) have their own fixed, shorter cap and are unaffected. |
| MaxTotalTokens | int32 | MaxTotalTokens budgets the whole page in estimated tokens rather than characters, because the same character count is worth roughly four times as many tokens in CJK text as in ASCII. 0 = server default (8000). Frames are visited in tree order and each gets whatever is left. |
| IncludeBounds | bool | IncludeBounds adds bounds="x,y,w,h" to every row. Off by default; bounds cost about as much as the rest of a row and are rarely needed, since elements are addressed by backendNodeId. |
| ViewportOnly | bool | ViewportOnly limits the walk to elements intersecting the frame's current viewport. Off by default. |
| BackendNodeId | int32 | Subtree scope — set exactly one of BackendNodeId, Selector or JSExpression to observe only that element's subtree (follow-up looks at a form then cost the form, not the ads around it). Omit all three for the whole page. Child iframes reached inside the scope are still visited. |
| Selector | string | |
| JSExpression | string | |
| InFrame | string | InFrame looks up the scope root: empty = main frame, a frameId, or AllFrames. Ignored when observing the whole page. |
OccluderInfo
structOccluderInfo describes the element that intercepted a click — the element sitting on top of the target at the intended click point. Coordinates are in root-viewport CSS pixels. Populated on ClickError for occlusion failures so the caller can locate and clear the blocker (e.g. find its close button).
| BackendNodeId | int32 | |
| FrameId | string | |
| TagName | string | |
| Id | string | |
| ClassName | string | |
| Text | string | |
| Bounds | Rect | |
| PointerEvents | string | PointerEvents is the blocker's computed pointer-events keyword (e.g. "auto", "none", "all"). Lets you tell an invisible pass-through layer from one that genuinely swallows the click. |
| Visibility | string | Visibility is the blocker's computed visibility keyword ("visible", "hidden", "collapse"). |
| Opacity | float64 | Opacity is the blocker's computed opacity (0..1). 0 means visually invisible but it may still intercept clicks depending on PointerEvents. |
| ZIndex | string | ZIndex is the blocker's computed effective z-index as a string ("0" when auto / not stacked). |
| HittableWhileInvisible | bool | HittableWhileInvisible is true when the blocker intercepts clicks even while invisible (computed pointer-events in {all, painted, fill, stroke}): a real click is swallowed even at visibility:hidden / opacity:0. When false and the element is invisible, a real click would fall through. |
| Position | string | Position is the computed position keyword. "fixed"/"sticky" means the blocker is pinned (by itself or an ancestor) and stays put no matter where the pointer goes — clear it by scrolling the target out from under it; ordinary overlays often collapse once the pointer leaves. |
PageInfo
structPageInfo describes an open page (tab or popup) inside a browser context.
ReactionInfo
structReactionInfo describes a still-pending reaction, as returned by CloudBrowser.ListReactions. One-shot reactions that have already fired are gone and never appear here.
| ReactionID | string | ReactionID is the stable id assigned by AddReaction (pass to RemoveReaction). |
| MatchSelector | string | MatchSelector is set if the reaction matches by CSS selector. |
| MatchJsExpression | string | MatchJsExpression is set if the reaction matches by JS expression. |
| ActionSelector | string | ActionSelector is set if the click target differs from the matched element. |
| ActionJsExpression | string | ActionJsExpression is set if the click target differs from the matched element. |
| FrameID | string | FrameID is the frame scope: "" for the main frame, a specific frameId, or AllFrames. |
| Visible | bool | Visible reports whether the match additionally requires visibility. |
ReactionOpts
structReactionOpts customizes CloudBrowser.AddReactionWith. Zero/empty values mean "use the server default".
| On? | *Locator | On overrides the click target. Nil = click the matched element itself. Provide a CSS or JS Locator to click a different element, resolved in the matched element's frame (e.g. a modal's close "X"). Node/At locators are rejected. |
| Button | string | Button is the mouse button for the click. Valid: "left" (default), "right", "middle". |
| ClickCount | int32 | ClickCount controls single/double-click. 0 or 1 = single click (default), 2 = double-click. |
| IntervalMs | float64 | IntervalMs is the poll cadence in milliseconds for the shared page loop. 0 = server default (300ms). |
ReadCanvasOpts
structReadCanvasOpts customizes a CloudBrowser.ReadCanvasWith call. Zero/empty values mean "use the server default".
| InFrame | string | InFrame overrides the locator's own frame. Empty = use the locator's frame (or the main frame if none). Pass a specific frameId, or AllFrames, to search elsewhere. |
| Format | string | Format is the output encoding. "" or "png" (default), "jpeg", "webp", or "rgba" for the raw unpremultiplied RGBA pixel buffer. |
| Quality | int32 | Quality is the encode quality 0-100 for "jpeg"/"webp" (ignored otherwise). 0 = server default (90). |
| SX | int32 | SX, SY, SW, SH is an optional sub-rectangle in canvas pixels (mirrors getImageData(sx, sy, sw, sh)). The full canvas is read when SW/SH <= 0. |
| SY | int32 | SX, SY, SW, SH is an optional sub-rectangle in canvas pixels (mirrors getImageData(sx, sy, sw, sh)). The full canvas is read when SW/SH <= 0. |
| SW | int32 | SX, SY, SW, SH is an optional sub-rectangle in canvas pixels (mirrors getImageData(sx, sy, sw, sh)). The full canvas is read when SW/SH <= 0. |
| SH | int32 | SX, SY, SW, SH is an optional sub-rectangle in canvas pixels (mirrors getImageData(sx, sy, sw, sh)). The full canvas is read when SW/SH <= 0. |
ReadCanvasResult
structReadCanvasResult 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 Opts.Format == "rgba". OriginClean reports whether the canvas was untainted (informational; the read succeeds either way).
| Success | bool | |
| FrameId | string | |
| BackendNodeId | int32 | |
| DataBase64 | string | |
| Width | int32 | |
| Height | int32 | |
| OriginClean | bool |
Rect
structRect describes a position and size in CSS pixels.
| X | float64 | |
| Y | float64 | |
| Width | float64 | |
| Height | float64 |
RequestPattern
structRequestPattern 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.
| URL | string | |
| Abort | bool |
ScreenshotResult
structScreenshotResult 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.
| DataBase64 | string | |
| Width | int32 | |
| Height | int32 |
ScrollError
structScrollError is returned as the error from CloudBrowser.ScrollTo when the target could not be located/scrolled. Implements the error interface; recover with errors.As.
| Code | string | Code is currently always "not_found". |
| Message | string | Message is a human-readable description. |
SelectOptionError
structSelectOptionError is returned as the error from CloudBrowser SelectByXxx calls when the option could not be selected. selectOption is programmatic (no pointer gate), so it only reports semantic failures. Implements the error interface; recover with errors.As.
| Code | string | Code is "not_found" (the <select> was not located) or "option_not_found" (no option matched the requested index/value/text). |
| Message | string | Message is a human-readable description. |
SelectOptionResult
structSelectOptionResult reports which <option> a SelectByXxx call ended up selecting.
| Success | bool | |
| SelectedIndex | int32 | |
| SelectedValue | string | |
| SelectedText | string |
SelectOpts
structSelectOpts customizes a SelectByXxxWith call. Zero/empty values mean "use the server default".
| InFrame | string | InFrame overrides the locator's own frame. Empty = use the locator's frame (or the main frame if none). Pass a specific frameId, or AllFrames, to search elsewhere. |
| NoEvents | bool | NoEvents picks the option silently without firing input/change events. Default (false) fires the standard events. |
StorageItem
structStorageItem is a single localStorage key/value pair.
| Key | string | |
| Value | string |
StorageOriginEntry
structStorageOriginEntry 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.
| Origin | string | |
| Items | []StorageItem |
WaitArg
interfaceWaitArg is the marker interface for everything Wait accepts: a Locator (treated as a condition) or a wait-level option such as Timeout / InFrame / InAllFrames.
WaitConditionStatus
structWaitConditionStatus is the per-condition diagnostic carried by WaitError when a CloudBrowser.Wait times out: one entry per condition (in the order they were passed) explaining why it never matched.
| Index | int32 | Index into the condition list this entry describes. |
| State | string | State is the last observed state: "not_found", "found_hidden", "found_occluded" (only when the condition required visibility), or "pending_steady". |
| BackendNodeId | int32 | BackendNodeId last seen for this condition (0 if never found). |
| FrameId | string | FrameId where it was last seen (empty if never found). |
| IsVisible | bool | IsVisible reports whether it was CSS-visible at the last observation. |
| Bounds? | *Rect | Bounds is the last known rect in root-viewport coordinates (nil if never found). |
| Occluder? | *OccluderInfo | Occluder is the intercepting element, present iff State == "found_occluded". |
WaitError
structWaitError is returned as the error from CloudBrowser.Wait when no condition matched before the deadline. It implements the error interface, so the ordinary res, err := browser.Wait(...) shape keeps working; recover the structured detail (including the per-condition breakdown) with errors.As:
res, err := browser.Wait(ctx, browserscale.CSS(".ready")) var we *browserscale.WaitError if errors.As(err, &we) { for _, c := range we.Conditions { log.Printf("condition %d: %s", c.Index, c.State) } }
| Code | string | Code is a machine-stable failure code, currently always "timeout". |
| Message | string | Message is a human-readable description. |
| Conditions | []WaitConditionStatus | Conditions holds the per-condition status, same order/length as the conditions passed to Wait. |
WaitResult
structWaitResult is the outcome of a CloudBrowser.Wait / CloudBrowser.WaitForAny call: which condition matched (Index, in argument order) and where the matched element lives.
| Index | int32 | |
| FrameId | string | |
| BackendNodeId | int32 | |
| IsVisible | bool | |
| Bounds | Rect |