Browser tools
Lightpanda exposes one set of browser tools through these interfaces: the MCP server serves them over tools/call, the agent calls them for the model and as slash commands, and PandaScript records them as page methods. This page lists each tool with its arguments as the browser declares them.
Tools that target an element take a selector or a backendNodeId. Prefer selector for reproducibility; it also wins when you pass both. backendNodeId values come from a prior tree, links or findElement call.
Navigation and search
These tools bring a page into the browser.
| Tool | Summary |
|---|---|
goto | Open a URL and keep the page in memory |
search | Web search, results as markdown |
goto
Navigate the current page to a URL. Returns the HTTP status once waitUntil fires (default load), or a timeout notice; a 4xx or 5xx means the page you got is an error page, not the content — check it before reading on; content rendered by post-load JavaScript may not be there yet (see waitForState). The page stays loaded for later reads and actions. To navigate and read in one call, pass url to markdown, tree or html instead; use goto when the next step is an action or extract.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | yes | The URL to navigate to, must be a valid URL. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
waitUntil | string | no | Event that completes the navigation. Defaults to ‘load’. Prefer ‘domcontentloaded’ followed by waitForSelector on pages whose late scripts (ads) hold ‘load’ back. Avoid ‘done’ (full quiescence): on pages with constant background activity it is the slowest choice and can run to the timeout. One of load, domcontentloaded, networkalmostidle, networkidle, done. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
search
Run a web search and return results as markdown: a numbered list of {title, url, snippet}. Search tries brave, tavily, exa, then keenable in order, each when its API key (BRAVE_API_KEY, TAVILY_API_KEY, EXA_API_KEY or KEENABLE_API_KEY) is set; keenable also works without a key through its public endpoint (rate-limited per client IP). Prefer this over goto-ing google.com/search directly (Google blocks the browser on User-Agent/TLS). The browser does not navigate — to open a result, use goto with its URL.
| Argument | Type | Required | Description |
|---|---|---|---|
query | string | yes | The search query. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Reading the page
These tools read the loaded page without modifying it.
| Tool | Summary |
|---|---|
markdown | Render the page or a subtree as markdown |
html | Raw HTML of the page or a node |
screenshot | Screenshot of the page or a node |
links | List all links on the page |
tree | Semantic DOM tree of the page |
nodeDetails | Inspect a node by backendNodeId |
interactiveElements | List interactive elements on the page |
structuredData | Extract JSON-LD / OpenGraph data |
detectForms | List forms and their fields |
findElement | Find elements by role or name |
markdown
Render the page (or a subtree) as markdown. Scope with selector or backendNodeId to read just the relevant region — full-page markdown is the last resort. Use maxBytes to cap long pages.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | Optional CSS selector. Render markdown for just that element’s subtree. |
backendNodeId | integer | no | Optional backend node ID. Render markdown for just that node’s subtree. 0 is treated as omitted. |
maxBytes | integer | no | Optional soft cap on output size in bytes. Content is truncated at a UTF-8 boundary and a short ‘[truncated]’ marker is appended past the cap. |
strip | object | no | Optional. Omit element groups from the output; same groups as the html tool’s strip. shell (page chrome by markup) and clutter (keep only the main content, in the manner of reader modes) are the ones that matter for reading; ui also drops images. Keys: js, css, ui, invisible, shell, clutter. |
url | string | no | Optional URL to navigate to before rendering. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
html
Raw HTML for the document or, with selector/backendNodeId, a single node’s outerHTML. Verbose; use only when you need attributes that markdown discards.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | Optional CSS selector. When set, dump only that element’s outerHTML. |
backendNodeId | integer | no | Optional backend node ID. When set, dump only that node’s outerHTML. 0 is treated as omitted. |
maxBytes | integer | no | Optional soft cap on output size in bytes. Content is truncated at a UTF-8 boundary and a short ‘[truncated]’ marker is appended past the cap. |
strip | object | no | Optional. Omit element groups from the output: js (script, noscript, script preloads), css (style, stylesheet links), ui (css plus img, picture, video, audio, svg, canvas, iframe), invisible (elements an author rule or inline style sets to display:none), shell (nav, aside, dialog, page-level header/footer and the matching landmark roles; skipped when that would drop most of the text), clutter (keep only the main content, in the manner of reader modes; includes shell and invisible, and falls back to shell when it finds too little). {“js”:true,“css”:true} keeps a page dump small. Keys: js, css, ui, invisible, shell, clutter. |
url | string | no | Optional URL to navigate to before dumping. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
screenshot
Render the page, or one node, as a PNG: the text layout Lightpanda computes, not a pixel-accurate browser rendering (no images, fonts or CSS colours). With path, writes the file at full size and returns its location; without it, returns the image inline where the client can display one, at most 1280px wide and 4096px tall. Use it to see spatial layout; read content with markdown/tree.
| Argument | Type | Required | Description |
|---|---|---|---|
path | string | no | Optional relative path (no ’..’ segments) to write the PNG to. Created or overwritten. Without it the image is returned inline, which needs a client that can display images. |
selector | string | no | Optional CSS selector. When set, render only that element. |
backendNodeId | integer | no | Optional backend node ID. When set, render only that node. 0 is treated as omitted. |
fullPage | boolean | no | Render the whole content height instead of one viewport. Defaults to false. |
strip | object | no | Optional. Omit element groups from the render; same groups as the html tool’s strip (js, css, ui, invisible, shell, clutter). Keys: js, css, ui, invisible, shell, clutter. |
url | string | no | Optional URL to navigate to before rendering. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Recorded in saved scripts. Navigates first when given url.
links
Extract the visible links in the opened page as JSON objects with text (anchor text, falling back to aria-label/title/image alt), href (resolved URL), and backendNodeId (pass to click/nodeDetails). One entry per href; hidden links are omitted. If a url is provided, it navigates to that url first.
| Argument | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Optional. Return at most this many links, in document order. |
url | string | no | Optional URL to navigate to before processing. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
tree
Semantic outline of the page as indented text: one node per line with its role, accessible name, value and backendNodeId, plus checked state and select options with the selected one marked. The default first read of an unfamiliar page; input and select values are already here, so no nodeDetails call is needed to read them. Pass backendNodeId to scope to a subtree and maxDepth to survey structure before going deeper. Read it again after any page-changing action, since the DOM it describes may have changed; use nodeDetails to turn a backendNodeId into a CSS selector for actions.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | no | Optional URL to navigate to before fetching the semantic tree. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
backendNodeId | integer | no | Optional backend node ID to get the tree for a specific element instead of the document root. 0 is treated as omitted. |
maxDepth | integer | no | Optional maximum depth of the tree to return. Useful for exploring high-level structure first. |
maxBytes | integer | no | Optional cap on output size in bytes. Past it, lines are kept by priority (alerts, dialogs, invalid fields and the focused element, then controls and named nodes, then text; list entries breadth-first), and dropped lines are counted in a ’[+N more @id]’ marker. id is the backendNodeId of the node holding them, often a list item or list that isn’t printed itself: call tree with backendNodeId=id to read them. |
Navigates first when given url.
nodeDetails
Details for a node by backendNodeId: a ready-to-use CSS selector that resolves to the node (the first match, as click/fill resolve it), plus tag, role, name, interactivity, disabled, value, input type, placeholder, href, id, class, checked, select options. The canonical way to turn a tree backendNodeId into a CSS selector.
| Argument | Type | Required | Description |
|---|---|---|---|
backendNodeId | integer | yes | The backend node ID of the element to inspect. |
interactiveElements
List every visible interactive element on the page as a JSON array: native controls, ARIA widgets, contenteditable regions, elements with event listeners, and focusable elements. Each entry has backendNodeId, tagName, role, name, type (why it counts as interactive), tabIndex, and when present listeners, disabled, id, class, href, inputType, value, elementName and placeholder. Use it to survey what can be acted on; to locate one element by role or name, findElement is cheaper. If a url is provided, it navigates there first.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | no | Optional URL to navigate to before processing. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
structuredData
Page metadata as JSON: jsonLd (each JSON-LD block as a string), openGraph, twitterCard, meta and links (key/value lists), plus alternate (hreflang variants) and linkHeaders (relations from the HTTP Link header) when present. Empty sections come back as empty arrays. Use it for publisher-declared facts such as product price, article author or canonical URL before scraping the visible text for them. If a url is provided, it navigates there first.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | no | Optional URL to navigate to before processing. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
detectForms
List the forms on the page as JSON: each form’s backendNodeId, action, method and fields, where each field has backendNodeId, tagName, name, inputType, required, disabled, and when present value, placeholder and select options. Use it before filling a form to see every field it expects. It returns no CSS selectors; get one per field with nodeDetails so the fill calls stay replayable. If a url is provided, it navigates there first.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | no | Optional URL to navigate to before processing. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
Navigates first when given url.
findElement
Find interactive elements by role and/or accessible name. Returns matching elements with their backend node IDs. Useful for locating specific elements without parsing the full semantic tree.
| Argument | Type | Required | Description |
|---|---|---|---|
role | string | no | Optional ARIA role to match (e.g. ‘button’, ‘link’, ‘textbox’, ‘checkbox’). |
name | string | no | Optional accessible name to match, case-insensitive: a substring, or a JavaScript regex literal such as /sign (in|up)/ (unanchored; flags i, m, s, u accepted; case-insensitive even without i, prefix (?-i) to make it case-sensitive). |
Data extraction and scripting
These tools return structured results from the loaded page.
| Tool | Summary |
|---|---|
evaluate | Run JavaScript in the page |
extract | Extract structured data via a CSS-selector schema |
evaluate
Evaluate JavaScript in the current page context — an escape hatch for page-side logic the dedicated tools can’t express; prefer extract for data and click/fill/etc. for actions. It runs in the page, so it cannot see the agent script’s variables or builtins — interpolate any value into the script string. A bare trailing expression yields its value; top-level await and return are supported (the body then runs as an async function, so use return to produce a value). Objects and arrays return as JSON, so no JSON.stringify is needed. If a url is provided, it navigates there first. The globalThis.lp object exposes a Session-scoped bridge store: values written via lp.foo = ... auto-sync at end of evaluate, surviving navigation; values previously set via /extract save= or /evaluate save= appear as lp.<name>.
| Argument | Type | Required | Description |
|---|---|---|---|
script | string | yes | JavaScript run in the page context. A bare trailing expression, or return with top-level await, is the result. |
url | string | no | Optional URL to navigate to before evaluating. An empty string is treated as omitted. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 10000. |
save | string | no | Optional bridge-store key. The evaluate’s return value is stored under this name and re-exposed as lp.<name> to subsequent evaluates. Objects, arrays, and strings are serialized automatically — no JSON.stringify needed. |
Recorded in saved scripts.
extract
Extract structured data from the current page (navigate first). schema is a JSON object (passed as a string) mapping output field names to CSS-selector specs. It is NOT a JSON Schema — no “type”/“properties” wrappers; the keys ARE your output fields. Value shapes:
"<sel>" → first match's text (trimmed; null if no match)
["<sel>"] → every match's text (string[])
{"selector":"<sel>","attr":"<name>"} → first match's attribute value (href/src resolved to absolute URLs)
[{"selector":"<sel>","attr":"<name>"}] → every match's attribute (string[])
[{"selector":"<sel>","fields":{…}}] → one object per match; field selectors resolve relative to that match and accept any shape above ("" = the match's own text; nest arrays for per-item sub-lists)Add “limit”: N inside any array’s object spec to cap matches.
Every extracted value is a string or null — parse numbers downstream. An empty array is a valid result, but if ALL top-level keys miss, the call errors: inspect the page (tree/markdown) and retry with corrected selectors.
Finish data tasks with extract — it is the only read recorded as a replayable extract(...) script call; answers lifted from markdown text in chat are not.
Examples (schema → result):
{"karma": "#karma"} → {"karma":"42"}
{"items": [".story .title"]} → {"items":["Title 1","Title 2"]}
{"top3": [{"selector":".story .title","limit":3}]} → {"top3":["A","B","C"]}
{"links": [{"selector":"a.title","attr":"href"}]} → {"links":["https://site/a","https://site/b"]}
{"stories": [{"selector":".athing","fields":{"title":".titleline","rank":".rank"}}]} → {"stories":[{"title":"Foo","rank":"1"}]}| Argument | Type | Required | Description |
|---|---|---|---|
schema | string | yes | Extraction schema as a string: a JSON object literal mapping output field names to CSS-selector specs (see tool description). Not a JSON Schema. |
save | string | no | Optional bridge-store key. The extracted JSON is stored under this name and exposed as lp.<name> in subsequent /evaluate calls. |
Recorded in saved scripts.
Interacting with the page
These tools dispatch real DOM events on the page.
| Tool | Summary |
|---|---|
click | Click an element |
fill | Type text into an input |
scroll | Scroll the page or an element |
hover | Hover over an element |
press | Press a keyboard key |
selectOption | Select an option in a dropdown |
setChecked | Check or uncheck a box |
click
Click on an interactive element. Provide either a CSS selector (preferred for reproducibility) or a backendNodeId. Returns the current page URL and title after the click.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | CSS selector of the element to click. Preferred over backendNodeId. |
backendNodeId | integer | no | The backend node ID of the element to click. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
fill
Fill text into an input element. Provide either a CSS selector (preferred for reproducibility) or a backendNodeId.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | CSS selector of the input element to fill. Preferred over backendNodeId. |
backendNodeId | integer | no | The backend node ID of the input element to fill. |
value | string | yes | The text to fill into the input element. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
scroll
Scroll the window, or an element’s scroll container, to an absolute position; an omitted axis keeps its current offset. Target an element with a CSS selector (preferred for reproducibility) or a backendNodeId; omit both to scroll the window. Page scripts receive a scroll event, so content that loads on scroll (infinite feeds, lazy lists) may appear: read the page again afterwards, with waitForState if it is still loading. Returns the final scroll position and the current page URL and title.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | Optional: CSS selector of the element to scroll. Preferred over backendNodeId. If the element is not itself a scroll container, its nearest scrollable ancestor is scrolled instead. |
backendNodeId | integer | no | Optional: The backend node ID of the element to scroll. If the element is not itself a scroll container, its nearest scrollable ancestor is scrolled instead. If neither this nor selector is given (or it is 0), scrolls the window. |
x | integer | no | Optional: The horizontal scroll offset. |
y | integer | no | Optional: The vertical scroll offset. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
hover
Hover over an element, triggering mouseover and mouseenter events. Provide either a CSS selector (preferred for reproducibility) or a backendNodeId. Useful for menus, tooltips, and hover states.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | CSS selector of the element to hover over. Preferred over backendNodeId. |
backendNodeId | integer | no | The backend node ID of the element to hover over. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
press
Press a keyboard key, dispatching keydown and keyup events. Use key names like ‘Enter’, ‘Tab’, ‘Escape’, ‘ArrowDown’, ‘Backspace’, or single characters like ‘a’, ‘1’. Common shorthand is normalized: ‘enter’/‘return’ → ‘Enter’, ‘esc’ → ‘Escape’, ‘up’/‘down’/‘left’/‘right’ → ‘Arrow*’, ‘space’ → ’ ’. Pressing ‘Enter’ on a form input or submit button triggers implicit form submission.
| Argument | Type | Required | Description |
|---|---|---|---|
key | string | yes | The key to press (e.g. ‘Enter’, ‘Tab’, ‘a’). |
selector | string | no | Optional CSS selector of the element to target. Preferred over backendNodeId. |
backendNodeId | integer | no | Optional backend node ID of the element to target. Defaults to the document when neither selector nor backendNodeId is provided; 0 is treated as omitted. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
selectOption
Select an option in a <select> dropdown element by its value. Provide either a CSS selector (preferred for reproducibility) or a backendNodeId. Dispatches input and change events.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | CSS selector of the <select> element. Preferred over backendNodeId. |
backendNodeId | integer | no | The backend node ID of the <select> element. |
value | string | yes | The value of the option to select. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
setChecked
Check or uncheck a checkbox or radio button. Provide either a CSS selector (preferred for reproducibility) or a backendNodeId. Dispatches input, change, and click events.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | no | CSS selector of the checkbox or radio input element. Preferred over backendNodeId. |
backendNodeId | integer | no | The backend node ID of the checkbox or radio input element. |
checked | boolean | yes | Whether to check (true) or uncheck (false) the element. Defaults to true. |
Recorded in saved scripts. Reports the resulting page state (url, httpStatus, title).
Waiting
These tools block until the page reaches a condition.
| Tool | Summary |
|---|---|
waitForSelector | Wait for an element to appear |
waitForScript | Wait until a JS expression is truthy |
waitForState | Wait for the page to reach a load state |
waitForSelector
Wait for an element matching a CSS selector to appear in the page. Returns the backend node ID of the matched element.
| Argument | Type | Required | Description |
|---|---|---|---|
selector | string | yes | The CSS selector to wait for. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 5000, or 15000 when the page has not reached ‘load’ yet. |
Recorded in saved scripts.
waitForScript
Wait until a JS expression returns truthy. Re-evaluates on each tick of the event loop. Use for synchronization beyond what CSS selectors can express — e.g. window.dataLoaded === true, document.readyState === 'complete', document.querySelectorAll('.row').length >= 5.
| Argument | Type | Required | Description |
|---|---|---|---|
script | string | yes | JS expression evaluated each tick until truthy. Must be an expression (not a statement). |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 5000, or 15000 when the page has not reached ‘load’ yet. |
Recorded in saved scripts.
waitForState
Wait for the CURRENT page to reach a load state (no navigation). After a goto, the page is returned at the fast load snapshot, so content rendered by post-load JS (XHR-loaded lists, feeds, search results) may still be missing. When a read looks incomplete — empty lists, spinners, skeletons — call this with ‘networkidle’ and re-read. Prefer ‘networkidle’; ‘done’ can be slow on sites with constant background activity (ads, polling).
| Argument | Type | Required | Description |
|---|---|---|---|
state | string | yes | Load state to wait for. ‘networkidle’ = network settled (the usual choice to finish a dynamic page). One of load, domcontentloaded, networkalmostidle, networkidle, done. |
timeout | integer | no | Optional timeout in milliseconds. Defaults to 5000. |
Recorded in saved scripts.
State and debugging
These tools inspect browser state outside the DOM.
| Tool | Summary |
|---|---|
consoleLogs | Read buffered console messages |
getUrl | Show the current page URL |
getCookies | Show stored cookies |
getEnv | Read or list LP_* env vars |
consoleLogs
Get buffered console.log/warn/error messages from the current page. Returns all messages since last call and clears the buffer.
No arguments.
getUrl
Current page URL. The browser may already have a page loaded (command, replayed script) not visible in this conversation — call this before assuming nothing is loaded when the user references the current page/site. Also useful to verify a navigation or detect a redirect.
No arguments.
getCookies
Cookies stored in the browser. Defaults to cookies whose domain matches the current page’s host. Pass url=<URL> to filter for another host, or all=true to dump every cookie regardless of host. Useful for debugging authentication and session state.
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | no | Restrict output to cookies matching this URL’s host. Defaults to the current page. An empty string is treated as omitted. |
all | boolean | no | If true, dump every cookie regardless of host. Overrides url. Defaults to false. |
getEnv
With name: read an LP_* env var (other namespaces report as not set) — for non-secret config only (base URLs, flags). Without name: list LP_* names that are set (no values) — safe credential discovery. For secrets, pass $LP_* placeholders in tool args; never request a credential by name (the value would land in your context).
| Argument | Type | Required | Description |
|---|---|---|---|
name | string | no | Optional. If provided, must start with LP_; returns the value. If omitted, returns the list of LP_* names that are set. |