import { type FrameEvalResult } from './actions/evaluate.js'; import type { LaunchOptions, ConnectOptions, SnapshotResult, SnapshotOptions, AriaSnapshotResult, BrowserTab, FormField, ClickOptions, TypeOptions, WaitOptions, ScreenshotOptions, ConsoleMessage, PageError, NetworkRequest, CookieData, StorageKind, SsrfPolicy, DownloadResult, DialogOptions, ResponseBodyResult, TraceStartOptions, ColorScheme, GeolocationOptions, HttpCredentials } from './types.js'; /** * Represents a single browser page/tab with ref-based automation. * * The workflow is: **snapshot → read refs → act on refs**. * * @example * ```ts * const page = await browser.open('https://example.com'); * * // 1. Take a snapshot to get refs * const { snapshot, refs } = await page.snapshot(); * // snapshot: AI-readable text tree * // refs: { "e1": { role: "link", name: "More info" }, ... } * * // 2. Act on refs * await page.click('e1'); * await page.type('e3', 'hello'); * ``` */ export declare class CrawlPage { private readonly cdpUrl; private readonly targetId; private readonly ssrfPolicy; /** @internal */ constructor(cdpUrl: string, targetId: string, ssrfPolicy?: SsrfPolicy); /** The CDP target ID for this page. Use this to identify the page in multi-tab scenarios. */ get id(): string; /** * Take an AI-readable snapshot of the page. * * Returns a text tree with numbered refs (`e1`, `e2`, ...) that map to * interactive elements. Use these refs with actions like `click()` and `type()`. * * @param opts - Snapshot options (mode, filtering, depth limits) * @returns Snapshot text, ref map, and statistics * * @example * ```ts * // Default snapshot (aria mode) * const { snapshot, refs } = await page.snapshot(); * * // Interactive elements only, compact * const result = await page.snapshot({ interactive: true, compact: true }); * * // Role-based mode (uses getByRole resolution) * const result = await page.snapshot({ mode: 'role' }); * ``` */ snapshot(opts?: SnapshotOptions): Promise; /** * Take a raw ARIA accessibility tree snapshot via CDP. * * Unlike `snapshot()`, this returns structured node data rather than * an AI-readable text tree. Useful for programmatic accessibility analysis. * * @param opts - Options (limit: max nodes to return, default 500) * @returns Array of accessibility tree nodes */ ariaSnapshot(opts?: { limit?: number; }): Promise; /** * Click an element by ref. * * @param ref - Ref ID from a snapshot (e.g. `'e1'`) * @param opts - Click options (double-click, button, modifiers) * * @example * ```ts * await page.click('e1'); * await page.click('e2', { doubleClick: true }); * await page.click('e3', { button: 'right' }); * await page.click('e4', { modifiers: ['Control'] }); * ``` */ click(ref: string, opts?: ClickOptions): Promise; /** * Type text into an input element by ref. * * By default, uses Playwright's `fill()` for instant input. Use `slowly: true` * to simulate real keystroke typing with a 75ms delay per character. * * @param ref - Ref ID of the input element (e.g. `'e3'`) * @param text - Text to type * @param opts - Type options (submit, slowly) * * @example * ```ts * await page.type('e3', 'hello world'); * await page.type('e3', 'slow typing', { slowly: true }); * await page.type('e3', 'search query', { submit: true }); // press Enter after * ``` */ type(ref: string, text: string, opts?: TypeOptions): Promise; /** * Hover over an element by ref. * * @param ref - Ref ID from a snapshot * @param opts - Timeout options */ hover(ref: string, opts?: { timeoutMs?: number; }): Promise; /** * Select option(s) in a `` element. * * @param ref - Ref ID of the file input element * @param paths - Array of file paths to upload */ uploadFile(ref: string, paths: string[]): Promise; /** * Arm a one-shot dialog handler (alert, confirm, prompt). * * Returns a promise — store it (don't await), trigger the dialog, then await it. * * @param opts - Dialog options (accept/dismiss, prompt text, timeout) * * @example * ```ts * const dialogDone = page.armDialog({ accept: true }); // don't await here * await page.click('e5'); // triggers confirm() * await dialogDone; // wait for dialog to be handled * ``` */ armDialog(opts: DialogOptions): Promise; /** * Arm a one-shot file chooser handler. * * Returns a promise — store it (don't await), trigger the file picker, then await it. * * @param paths - File paths to set when the chooser appears (empty to clear) * @param opts - Timeout options * * @example * ```ts * const uploadDone = page.armFileUpload(['/path/to/file.pdf']); // don't await here * await page.click('e3'); // triggers file picker * await uploadDone; // wait for files to be set * ``` */ armFileUpload(paths?: string[], opts?: { timeoutMs?: number; }): Promise; /** * Press a keyboard key or key combination. * * Uses Playwright's key names. Supports combinations with `+`. * * @param key - Key to press (e.g. `'Enter'`, `'Tab'`, `'Control+a'`, `'Meta+c'`) * @param opts - Options (delayMs: hold time between keydown and keyup) * * @example * ```ts * await page.press('Enter'); * await page.press('Control+a'); * await page.press('Meta+Shift+p'); * ``` */ press(key: string, opts?: { delayMs?: number; }): Promise; /** * Get the current URL of the page. */ url(): Promise; /** * Get the page title. */ title(): Promise; /** * Navigate to a URL. * * @param url - The URL to navigate to * @param opts - Timeout options * @returns The final URL after navigation (may differ due to redirects) */ goto(url: string, opts?: { timeoutMs?: number; }): Promise<{ url: string; }>; /** * Reload the current page. * * @param opts - Timeout options */ reload(opts?: { timeoutMs?: number; }): Promise; /** * Navigate back in browser history. * * @param opts - Timeout options */ goBack(opts?: { timeoutMs?: number; }): Promise; /** * Navigate forward in browser history. * * @param opts - Timeout options */ goForward(opts?: { timeoutMs?: number; }): Promise; /** * Wait for various conditions on the page. * * Multiple conditions can be specified — they are checked in order. * * @param opts - Wait conditions (text, URL, load state, selector, etc.) * * @example * ```ts * await page.waitFor({ loadState: 'networkidle' }); * await page.waitFor({ text: 'Welcome back' }); * await page.waitFor({ url: '**\/dashboard' }); * await page.waitFor({ timeMs: 1000 }); // sleep * ``` */ waitFor(opts: WaitOptions): Promise; /** * Run JavaScript in the browser page context. * * The function string is evaluated in the browser's sandbox, not in Node.js. * Pass a `ref` to receive the element as the first argument. * * @param fn - JavaScript function body as a string * @param opts - Options (ref: scope evaluation to a specific element) * @returns The return value of the evaluated function * * @example * ```ts * const title = await page.evaluate('() => document.title'); * const text = await page.evaluate('(el) => el.textContent', { ref: 'e1' }); * const count = await page.evaluate('() => document.querySelectorAll("img").length'); * ``` */ evaluate(fn: string, opts?: { ref?: string; timeoutMs?: number; signal?: AbortSignal; }): Promise; /** * Run JavaScript in ALL frames on the page (including cross-origin iframes). * * Playwright can access cross-origin frames via CDP, bypassing the same-origin policy. * This is essential for filling payment iframes (Stripe, etc.). * * @param fn - JavaScript function body as a string * @returns Array of results from each frame where evaluation succeeded * * @example * ```ts * const results = await page.evaluateInAllFrames(`() => { * const el = document.querySelector('input[name="cardnumber"]'); * return el ? 'found' : null; * }`); * ``` */ evaluateInAllFrames(fn: string): Promise; /** * Take a screenshot of the page or a specific element. * * @param opts - Screenshot options (fullPage, ref, element, type) * @returns PNG or JPEG image as a Buffer * * @example * ```ts * const screenshot = await page.screenshot(); * const fullPage = await page.screenshot({ fullPage: true }); * const element = await page.screenshot({ ref: 'e1' }); * ``` */ screenshot(opts?: ScreenshotOptions): Promise; /** * Export the page as a PDF. * * Only works in headless mode. * * @returns PDF document as a Buffer */ pdf(): Promise; /** * Take a screenshot with numbered labels overlaid on referenced elements. * * Useful for visual debugging — each ref gets a numbered badge and border. * * @param refs - Array of ref IDs to label * @param opts - Options (maxLabels: limit, type: image format) * @returns Screenshot buffer, label positions, and any skipped refs * * @example * ```ts * const { buffer, labels, skipped } = await page.screenshotWithLabels(['e1', 'e2', 'e3']); * fs.writeFileSync('labeled.png', buffer); * ``` */ screenshotWithLabels(refs: string[], opts?: { maxLabels?: number; type?: 'png' | 'jpeg'; }): Promise<{ buffer: Buffer; labels: Array<{ ref: string; index: number; box: { x: number; y: number; width: number; height: number; }; }>; skipped: string[]; }>; /** * Start recording a Playwright trace. * * Traces capture screenshots, DOM snapshots, and network activity. * Stop with `traceStop()` to save the trace file. * * @param opts - Trace options (screenshots, snapshots, sources) */ traceStart(opts?: TraceStartOptions): Promise; /** * Stop recording a trace and save it to a file. * * @param path - File path to save the trace (e.g. `'trace.zip'`) * @param opts - Options (allowedOutputRoots: constrain output to specific directories) */ traceStop(path: string, opts?: { allowedOutputRoots?: string[]; }): Promise; /** * Wait for a network response matching a URL pattern and return its body. * * @param url - URL string or pattern to match * @param opts - Options (timeoutMs, maxChars) * @returns Response body, status, headers, and truncation info * * @example * ```ts * const resp = await page.responseBody('/api/data'); * console.log(resp.status, resp.body); * ``` */ responseBody(url: string, opts?: { timeoutMs?: number; maxChars?: number; }): Promise; /** * Get console messages captured from the page. * * Messages are buffered automatically. Use `level` to filter by minimum severity. * * @param opts - Filter options (level, clear) * @returns Array of captured console messages */ consoleLogs(opts?: { level?: string; clear?: boolean; }): Promise; /** * Get uncaught errors from the page. * * @param opts - Options (clear: reset the error buffer after reading) * @returns Array of captured page errors */ pageErrors(opts?: { clear?: boolean; }): Promise; /** * Get network requests captured from the page. * * @param opts - Options (filter: URL substring match, clear: reset the buffer) * @returns Array of captured network requests * * @example * ```ts * const all = await page.networkRequests(); * const apiCalls = await page.networkRequests({ filter: '/api/' }); * const fresh = await page.networkRequests({ clear: true }); // read and clear * ``` */ networkRequests(opts?: { filter?: string; clear?: boolean; }): Promise; /** * Resize the browser viewport. * * @param width - Viewport width in pixels * @param height - Viewport height in pixels */ resize(width: number, height: number): Promise; /** * Get all cookies for the current browser context. * * @returns Array of cookie objects */ cookies(): Promise>>; /** * Set a cookie in the browser context. * * @param cookie - Cookie data (must include `name`, `value`, and either `url` or `domain`+`path`) * * @example * ```ts * await page.setCookie({ * name: 'token', * value: 'abc123', * url: 'https://example.com', * }); * ``` */ setCookie(cookie: CookieData): Promise; /** Clear all cookies in the browser context. */ clearCookies(): Promise; /** * Get values from localStorage or sessionStorage. * * @param kind - `'local'` for localStorage, `'session'` for sessionStorage * @param key - Optional specific key to retrieve (returns all if omitted) * @returns Key-value map of storage entries */ storageGet(kind: StorageKind, key?: string): Promise>; /** * Set a value in localStorage or sessionStorage. * * @param kind - `'local'` for localStorage, `'session'` for sessionStorage * @param key - Storage key * @param value - Storage value */ storageSet(kind: StorageKind, key: string, value: string): Promise; /** * Clear all entries in localStorage or sessionStorage. * * @param kind - `'local'` for localStorage, `'session'` for sessionStorage */ storageClear(kind: StorageKind): Promise; /** * Click a ref and save the resulting file download. * * @param ref - Ref ID of the element that triggers the download * @param path - Local file path to save the download to * @param opts - Timeout options * @returns Download result with URL, suggested filename, and saved path * * @example * ```ts * const result = await page.download('e7', '/tmp/report.pdf'); * console.log(result.suggestedFilename); // 'report.pdf' * ``` */ download(ref: string, path: string, opts?: { timeoutMs?: number; allowedOutputRoots?: string[]; }): Promise; /** * Wait for the next download event (without clicking). * * Returns a promise — store it (don't await), trigger the download, then await it. * * @param opts - Options (path: save location, timeoutMs) * @returns Download result with URL, suggested filename, and saved path */ waitForDownload(opts?: { path?: string; timeoutMs?: number; allowedOutputRoots?: string[]; }): Promise; /** * Set the browser to offline or online mode. * * @param offline - `true` to go offline, `false` to go online */ setOffline(offline: boolean): Promise; /** * Set extra HTTP headers for all requests. * * @param headers - Headers to add to every request * * @example * ```ts * await page.setExtraHeaders({ 'X-Custom': 'value' }); * ``` */ setExtraHeaders(headers: Record): Promise; /** * Set HTTP authentication credentials. * * @param opts - Credentials (username, password) or `{ clear: true }` to remove */ setHttpCredentials(opts: HttpCredentials): Promise; /** * Emulate a geolocation. * * @param opts - Geolocation coordinates or `{ clear: true }` to clear * * @example * ```ts * await page.setGeolocation({ latitude: 48.8566, longitude: 2.3522 }); // Paris * await page.setGeolocation({ clear: true }); // reset * ``` */ setGeolocation(opts: GeolocationOptions): Promise; /** * Emulate a preferred color scheme. * * @param opts - Color scheme options * * @example * ```ts * await page.emulateMedia({ colorScheme: 'dark' }); * ``` */ emulateMedia(opts: { colorScheme: ColorScheme; }): Promise; /** * Override the browser locale. * * @param locale - BCP-47 locale string (e.g. `'fr-FR'`, `'ja-JP'`) */ setLocale(locale: string): Promise; /** * Override the browser timezone. * * @param timezoneId - IANA timezone ID (e.g. `'America/New_York'`, `'Asia/Tokyo'`) */ setTimezone(timezoneId: string): Promise; /** * Emulate a specific device (viewport + user agent). * * @param name - Playwright device name (e.g. `'iPhone 13'`, `'Pixel 5'`) * * @example * ```ts * await page.setDevice('iPhone 13'); * ``` */ setDevice(name: string): Promise; } /** * Main entry point for browserclaw. * * Launch or connect to a browser, then open pages and automate them * using the snapshot + ref pattern. * * @example * ```ts * import { BrowserClaw } from 'browserclaw'; * * const browser = await BrowserClaw.launch({ headless: false }); * const page = await browser.open('https://example.com'); * * const { snapshot, refs } = await page.snapshot(); * console.log(snapshot); // AI-readable page tree * console.log(refs); // { "e1": { role: "link", name: "More info" }, ... } * * await page.click('e1'); * await browser.stop(); * ``` */ export declare class BrowserClaw { private readonly cdpUrl; private readonly ssrfPolicy; private chrome; private constructor(); /** * Launch a new Chrome instance and connect to it. * * Automatically detects Chrome, Brave, Edge, or Chromium on the system. * Creates a dedicated browser profile to avoid conflicts with your daily browser. * * @param opts - Launch options (headless, executablePath, cdpPort, etc.) * @returns A connected BrowserClaw instance * * @example * ```ts * // Default: visible Chrome window * const browser = await BrowserClaw.launch(); * * // Headless mode * const browser = await BrowserClaw.launch({ headless: true }); * * // Specific browser * const browser = await BrowserClaw.launch({ * executablePath: '/usr/bin/google-chrome', * }); * ``` */ static launch(opts?: LaunchOptions): Promise; /** * Connect to an already-running Chrome instance via its CDP endpoint. * * The Chrome instance must have been started with `--remote-debugging-port`. * * @param cdpUrl - CDP endpoint URL (e.g. `'http://localhost:9222'`) * @returns A connected BrowserClaw instance * * @example * ```ts * // Chrome started with: chrome --remote-debugging-port=9222 * const browser = await BrowserClaw.connect('http://localhost:9222'); * ``` */ static connect(cdpUrl: string, opts?: ConnectOptions): Promise; /** * Open a URL in a new tab and return the page handle. * * @param url - URL to navigate to * @returns A CrawlPage for the new tab * * @example * ```ts * const page = await browser.open('https://example.com'); * const { snapshot, refs } = await page.snapshot(); * ``` */ open(url: string): Promise; /** * Get a CrawlPage handle for the currently active tab. * * @returns CrawlPage for the first/active page */ currentPage(): Promise; /** * List all open tabs. * * @returns Array of tab information objects */ tabs(): Promise; /** * Bring a tab to the foreground. * * @param targetId - CDP target ID of the tab (from `tabs()` or `page.id`) */ focus(targetId: string): Promise; /** * Close a tab. * * @param targetId - CDP target ID of the tab to close */ close(targetId: string): Promise; /** * Get a CrawlPage handle for a specific tab by its target ID. * * Unlike `open()`, this doesn't create a new tab — it wraps an existing one. * * @param targetId - CDP target ID of the tab * @returns CrawlPage for the specified tab */ page(targetId: string): CrawlPage; /** The CDP endpoint URL for this browser connection. */ get url(): string; /** PID of the Chrome process (null if connected to external Chrome). */ get chromePid(): number | null; /** * Stop the browser and clean up all resources. * * If the browser was launched by `BrowserClaw.launch()`, the Chrome process * will be terminated. If connected via `BrowserClaw.connect()`, only the * Playwright connection is closed. */ stop(): Promise; }