The page object is the main interface for interacting with browser pages in Stagehand. It provides standard browser automation capabilities for navigation, interaction, and page inspection.Access the page object through your Stagehand instance:
Returns: An array of two strings containing the XPaths of the elements at the start and end positions when returnXpath is true, otherwise empty strings.
Provide the script to inject. Pass raw source, reference a preload file on disk,
or supply a function that Stagehand serializes before sending to the browser.
A plain object of header name–value pairs. All values must be strings.
This method:
Applies the headers to the page’s main CDP session and all of its child sessions (e.g. out-of-process iframes)
Automatically applies the same headers to any child sessions adopted after calling setExtraHTTPHeaders()
Calling it again replaces all previously set extra headers (it does not merge)
To clear all extra headers, pass an empty object: await page.setExtraHTTPHeaders({})
Headers set via page.setExtraHTTPHeaders() are page-scoped. They apply to every network request from this page only, including navigation requests, XHR/fetch calls, and subresource loads. Use context.setExtraHTTPHeaders() to set headers across all pages in the context.
import { Stagehand } from "@browserbasehq/stagehand";const stagehand = new Stagehand({ env: "LOCAL" });await stagehand.init();const page = stagehand.context.pages()[0];// Set custom headers for all requests from this pageawait page.setExtraHTTPHeaders({ "X-Custom-Token": "my-secret-token", "Accept-Language": "en-US",});// All subsequent requests from this page will include these headersawait page.goto("https://example.com");
Capture a structured accessibility snapshot of the current page. The returned data combines a human-readable accessibility tree with lookup maps so you can relate each node to DOM selectors or URLs.
Maps encoded IDs for link-like nodes to their resolved URLs.
See SnapshotResult for the static type definition.The formatted tree represents every accessibility node with:
A unique encoded ID in brackets (e.g., [0-1]) for cross-referencing with the maps
The node’s accessibility role (RootWebArea, heading, link, button, etc.)
The node’s accessible name, when available
Example formatted output:
[0-1] RootWebArea: Example Domain [0-3] heading: Example Domain [0-5] paragraph: This domain is for use in illustrative examples in documents. [0-8] link: More information...
Example usage:
const page = stagehand.context.pages()[0];await page.goto("https://example.com");const { formattedTree, xpathMap, urlMap } = await page.snapshot();// Print the accessibility treeconsole.log(formattedTree);// Look up a specific element's XPath by encoded IDconst linkId = "0-8";console.log(xpathMap[linkId]); // e.g., "/html/body/div/p[2]/a"// Resolve a link's URL via the urlMapconsole.log(urlMap[linkId]); // e.g., "https://www.example.com"// Exclude iframe content when you only need the main documentconst mainDocumentSnapshot = await page.snapshot({ includeIframes: false });
Wait for an element matching the selector to reach a specific state in the DOM. Uses a MutationObserver for efficiency, pierces shadow DOM by default, and supports iframe hops when needed.
import { Stagehand } from "@browserbasehq/stagehand";// Initialize with Browserbase (API key and project ID from environment variables)// Set BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID in your environmentconst stagehand = new Stagehand({ env: "BROWSERBASE" });await stagehand.init();const page = stagehand.context.pages()[0];// Navigate to a URLawait page.goto("https://example.com");// Get current URL and titleconsole.log("URL:", page.url());console.log("Title:", await page.title());// Navigate back and forwardawait page.goBack();await page.goForward();// Reload the pageawait page.reload();
// Execute JavaScript expressionconst pageHeight = await page.evaluate("document.body.scrollHeight");console.log("Page height:", pageHeight);// Execute function with argumentsconst result = await page.evaluate((selector) => { const element = document.querySelector(selector); return element ? element.textContent : null;}, "h1");console.log("H1 text:", result);// Async function evaluationconst data = await page.evaluate(async () => { const response = await fetch("/api/data"); return response.json();});
// Click at coordinatesawait page.click(100, 200);// Double clickawait page.click(100, 200, { clickCount: 2 });// Click and get the XPath of the clicked elementconst xpath = await page.click(100, 200, { returnXpath: true });console.log("Clicked element xpath:", xpath); // e.g., "/html/body/div[1]/button"// Hover at coordinatesawait page.hover(300, 150);// Hover and get the XPath of the hovered elementconst hoverXpath = await page.hover(300, 150, { returnXpath: true });// Scroll down at a positionawait page.scroll(400, 300, 0, 200); // scroll down 200px// Drag and drop between two pointsconst [fromXpath, toXpath] = await page.dragAndDrop(100, 100, 300, 300, { returnXpath: true });// Type textawait page.type("Hello, World!");// Type with delay between keystrokesawait page.type("Slow typing", { delay: 100 });// Use locator for element interactionconst button = page.locator("button.submit");await button.click();
// Navigate and wait for full loadawait page.goto("https://example.com", { waitUntil: "load", timeoutMs: 30000});// Wait for network idle after navigationawait page.goto("https://spa-app.com", { waitUntil: "networkidle"});// Wait for specific load stateawait page.waitForLoadState("domcontentloaded");
// Wait for element to be visible (default)await page.waitForSelector("#submit-btn");// Wait for element to appear with custom timeoutawait page.waitForSelector(".loading-spinner", { state: "visible", timeout: 10000});// Wait for element to be removed from DOMawait page.waitForSelector(".loading-spinner", { state: "detached"});// Wait for element to become hiddenawait page.waitForSelector(".modal", { state: "hidden"});// Wait for element inside an iframeawait page.waitForSelector("iframe#checkout >> .pay-button");// Wait for element in shadow DOM (enabled by default)await page.waitForSelector("#shadow-button", { pierceShadow: true});// Wait for element with XPathawait page.waitForSelector("/html/div/button");
// Set viewport sizeawait page.setViewportSize(1920, 1080);// Set mobile viewport with device scaleawait page.setViewportSize(375, 667, { deviceScaleFactor: 2});// Then take a screenshot at this sizeconst screenshot = await page.screenshot();
import { Stagehand } from "@browserbasehq/stagehand";const stagehand = new Stagehand({ env: "LOCAL" });await stagehand.init();const page = stagehand.context.pages()[0];// Set authorization headers for requests from this pageawait page.setExtraHTTPHeaders({ Authorization: "Bearer my-api-token",});// Navigate — the headers are sent with every request from this pageawait page.goto("https://api.example.com/dashboard");// Replace headers (previous headers are removed)await page.setExtraHTTPHeaders({ Authorization: "Bearer refreshed-token", "X-Request-Id": "abc-123",});// Clear all extra headersawait page.setExtraHTTPHeaders({});await stagehand.close();
// Capture the page's accessibility tree snapshotconst { formattedTree, xpathMap, urlMap } = await page.snapshot();// The formattedTree shows the page structure:// [0-1] RootWebArea: Example Domain// [0-3] heading: Example Domain// [0-8] link: More information...console.log(formattedTree);// Use xpathMap to get the XPath selector for any element by IDconst linkXpath = xpathMap["0-8"];console.log("Link XPath:", linkXpath); // "/html/body/div/p[2]/a"// Use urlMap to get URLs associated with link elementsconst linkUrl = urlMap["0-8"];console.log("Link URL:", linkUrl); // "https://www.iana.org/domains/example"// Exclude iframe content from the snapshotconst mainPageOnly = await page.snapshot({ includeIframes: false });