Skip to content

Browser & DOM

MethodSignatureDescription
g.dom.click(selector, options?) → PromiseClick an element
g.dom.enterText(selector, value, options?) → PromiseType text into an input
g.dom.selectOption(selector, options?) → PromiseSelect an option in a native HTML <select> element by value, label, or zero-based index
g.dom.scrollTo(selector, options?) → PromiseScroll an element into view
g.dom.pressKey(key, options?) → PromisePress a keyboard key
g.dom.highlight(selector, durationMs?, options?) → PromiseVisually highlight an element
g.dom.waitForElement(selector, options?) → PromiseWait for element using MutationObserver (no polling)
g.dom.waitForDomStable(options?) → PromiseWait until DOM stops mutating for a quiet period
g.dom.waitForReady(selector, options?) → PromiseCombined element + DOM stability wait — the go-to for SPAs

ElementOptions (the options parameter for DOM methods):

{
selectorType?: "css" | "xpath" | "text" | "text-contains" // default: "css"
browserTabId?: string // defaults to active tab
}

ClickOptions:

{
selectorType?: "css" | "xpath" | "text" | "text-contains"
browserTabId?: string
mode?: "default" | "human" // default: deterministic CDP input; "human" uses visible mouse movement
}

Use the default click mode for stable automation. Use { mode: "human" } when the page needs visible pointer movement or hover-like browser behavior before the click.

SelectOptionOptions:

{
value?: string // option value to select
label?: string // visible option label to select
index?: number // zero-based option index to select
selectorType?: "css" | "xpath"
browserTabId?: string
}

Use g.dom.selectOption for native <select> controls. For custom comboboxes, listboxes, and framework-rendered dropdowns, use the page’s visible controls with click/keyboard/wait methods instead.

WaitForElementOptions:

{
timeout?: number // default: 10000
visible?: boolean // require visibility — offsetHeight > 0, not display:none (default: false)
selectorType?: "css" | "xpath"
browserTabId?: string
}

WaitForDomStableOptions:

{
timeout?: number // default: 15000
quietPeriod?: number // ms of no DOM mutations before declaring stable (default: 500)
browserTabId?: string
}

WaitForReadyOptions:

{
timeout?: number // default: 15000 — covers both element detection and stability
quietPeriod?: number // ms of no DOM mutations after element is found (default: 500)
selectorType?: "css" | "xpath"
browserTabId?: string
}

MethodSignatureDescription
g.dom.extractContent(selector, options?) → Promise<string>Extract text content from an element
g.dom.getElements(selector, attributeNames, options?) → Promise<Record[]>Get attributes from matching elements
g.dom.countElements(selector, options?) → Promise<number>Count matching elements
g.dom.getElementXPaths(selector, options?) → Promise<string[]>Get XPath for each matching element

MethodSignatureDescription
g.page.getDom(options?) → Promise<string>Get page HTML
g.page.getPageSource(options?) → Promise<string>Get raw page source
g.page.getPageElements(options?) → Promise<PageElement[]>Get structured page elements (headings, links, buttons, inputs)
g.page.executeJS(script, options?) → Promise<any>Execute JavaScript in the browser tab and return the browser result
g.page.getUrl(options?) → Promise<string>Get the current page URL
g.page.ocr(options?) → Promise<OcrResult>Run OCR on the viewport or a region

g.page.executeJS() returns structured values directly. If the browser expression returns an object, array, number, boolean, string, or null, JavaScript and Janet receive the corresponding value. Do not wrap browser snippets in JSON.stringify(...) and then JSON.parse(...) in the host script unless you intentionally want to transport text.

Browser snippets return the last expression evaluated by WebView2. Prefer:

const links = await g.page.executeJS(`
Array.from(document.querySelectorAll("a"))
.map(a => ({ text: a.textContent.trim(), href: a.href }))
`);

Use explicit JSON text only when the result itself is supposed to be a string:

const jsonText = await g.page.executeJS(`JSON.stringify(window.__APP_STATE__)`);
const appState = JSON.parse(jsonText);

PageElement:

{
type: string // "heading", "link", "button", "input"
text: string
href: string // for links
selector: string
selectorType: string
context: string // "nav", "header", "footer", "main", "article"
visibility: string // "visible" or "suspicious"
headingLevel: number
}

MethodSignatureDescription
g.nav.navigateToUrl(url, options?) → Promise<NavigateResult>Navigate to a URL, returns status and headers
g.nav.blockRedirects() → voidBlock all server-side redirects (301/302/307)
g.nav.allowRedirects() → voidRestore default redirect behavior

NavigateOptions:

{
waitForLoad?: boolean // default: true
browserTabId?: string
stealth?: boolean | StealthOptions // inject anti-detection patches before page scripts
detectRedirects?: boolean // detect JS/meta redirects (default: false)
}

StealthOptions — granular control over anti-detection patches (all default to true when stealth is enabled):

{
webdriver?: boolean // hide navigator.webdriver
chromeRuntime?: boolean // inject window.chrome.runtime
permissions?: boolean // fix Permissions.prototype.query for notifications
plugins?: boolean // inject navigator.plugins with Chrome entries
languages?: boolean // ensure navigator.languages returns ["en-US", "en"]
}

NavigateResult:

{
statusCode: number // HTTP status code (200, 301, 404, etc.)
headers: Record<string, string> // response headers
finalUrl?: string // actual URL after navigation (only with detectRedirects)
redirectDetected?: boolean // true if final URL differs from requested
metaRefresh?: string // content of <meta http-equiv="refresh"> if found
}

MethodSignatureDescription
g.tabs.getTabs() → TabInfo[]Get all open tabs
g.tabs.newBrowserTab(options?) → Promise<string>Create a new tab, returns tab ID
g.tabs.closeTab(tabId?) → PromiseClose a tab (defaults to active)
g.tabs.closeAllTabs()Close all tabs
g.tabs.closeOtherTabs(tabId?)Close all tabs except the specified one
g.tabs.setActiveBrowserTab(tabId)Switch to a tab
g.tabs.getActiveBrowserTab() → string | nullGet the active tab’s ID
g.tabs.getBrowserTabInfo(tabId) → TabInfoGet info about a specific tab
g.tabs.setBrowserTabName(tabId, name)Rename a tab
g.tabs.findTabByUrl(pattern) → TabInfo | nullFind a tab whose URL contains the pattern
g.tabs.findTabByTitle(pattern) → TabInfo | nullFind a tab whose title contains the pattern
g.tabs.nextTab()Switch to the next tab
g.tabs.prevTab()Switch to the previous tab
g.tabs.moveTab(tabId, index)Move a tab to a different position

TabInfo:

{
id: string
name: string
url: string
pageTitle: string
isActive?: boolean
}

MethodSignatureDescription
g.screenshot.screenshot(path?) → Promise<string>Capture viewport, returns base64 or file path
g.screenshot.screenshotElement(selector, path?, options?) → Promise<string>Capture a specific element
g.screenshot.screenshotFullPage(path?, options?) → Promise<string>Capture the full scrollable page

ScreenshotFullPageOptions:

{
clean?: boolean // remove overlays (default: false)
browserTabId?: string
}

MethodSignatureDescription
g.viewport.setViewport(options)Set viewport size (by preset name or custom dimensions)
g.viewport.getViewport(tabId?) → ViewportInfo | nullGet current viewport info
g.viewport.getViewportPresets() → string[]List available preset names

ViewportOptions:

{
tabId?: string
preset?: string // e.g., "iPhone 12", "Desktop"
width?: number // custom width in pixels
height?: number // custom height in pixels
}

Guida uses two viewport modes:

  • Desktop presets such as Full HD, QHD, and 4K UHD use fit-to-pane scaling so large desktop layouts can be reviewed inside a smaller tab pane.
  • Mobile and tablet presets such as Mobile M and Tablet Portrait use device emulation, including responsive viewport width, device scale factor, and touch behavior.

Custom dimensions remain desktop fit by default.

ViewportInfo includes mode metadata:

{
name: string
width: number
height: number
isNative: boolean
mode: "Native" | "DesktopFit" | "DeviceEmulation" | string
deviceScaleFactor: number
mobile: boolean
touch: boolean
visualScale?: number
}

Arrange browser tabs in split panes.

MethodSignatureAsyncDescription
single()NoCollapse to single pane
horizontal(n?)NoSide-by-side layout
vertical(n?)NoStacked layout
quad()No2x2 grid
grid(rows, cols)NoCustom grid layout
moveToPane(docId, paneIndex)NoMove a document to a specific pane
focusPane(paneIndex)NoFocus a pane
getPanes() → PaneInfo[]NoGet all panes and their documents
arrange(docIds)NoArrange specific documents
arrangeByPattern(urlPattern)NoArrange documents matching a URL pattern


MethodSignatureAsyncDescription
copy(text)NoCopy text to clipboard
paste() → stringNoRead clipboard text
copyElement(selector, options?) → Promise<string>YesCopy an element’s text content


Control Guida’s UI panes from scripts.

MethodSignatureAsyncDescription
show(paneName)NoShow a pane
hide(paneName)NoHide a pane
toggle(paneName)NoToggle pane visibility
focus(paneName)NoFocus a pane

Pane names: console, workspace, llminsight, secrets, taskmanager, history, searchIndex, store, queues, queueprocessor, mcphistory, terminal.



MethodSignatureAsyncDescription
toMarkdown(html, options?) → stringNoConvert HTML to Markdown

HtmlToMarkdownOptions:

{
githubFlavored?: boolean // default: false
removeComments?: boolean // default: false
smartHrefHandling?: boolean // default: false
listBulletChar?: string // default: "-"
}