### Run Navigation Example Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/navigation.md Execute the navigation example script using Deno. ```bash deno run -A https://deno.land/x/astral/examples/navigation.ts ``` -------------------------------- ### Run Astral Screenshot Example Source: https://github.com/lino-levan/astral/blob/main/docs/pages/index.md Command to execute the Astral screenshot example script. ```bash deno run -A https://deno.land/x/astral/examples/screenshot.ts ``` -------------------------------- ### Run Astral Evaluation Example Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/evaluate.md Execute the Astral evaluation example script using Deno. Ensure the Deno environment is set up. ```bash deno run -A https://deno.land/x/astral/examples/evaluate.ts ``` -------------------------------- ### Set Browser Binary Path Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/env_vars.md Use ASTRAL_BIN_PATH to specify the location of an already installed browser binary. This is useful in containerized environments. ```dockerfile RUN apt-get install -y google-chrome-stable ENV ASTRAL_BIN_PATH=/usr/bin/google-chrome-stable ``` -------------------------------- ### Set and Get Page HTML Source: https://context7.com/lino-levan/astral/llms.txt Replace the entire HTML content of a page with a provided string, or retrieve the complete HTML, including the DOCTYPE. This is useful for testing or manipulating page content directly. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.setContent( "" "

Hello, Astral!

" ); const html = await page.content(); console.log(html); // Full HTML with DOCTYPE const text = await page.evaluate(() => (document.getElementById("title") as HTMLElement).innerText ); console.log(text); // "Hello, Astral!" ``` -------------------------------- ### Wait for Page Navigation Source: https://context7.com/lino-levan/astral/llms.txt Use this method to wait for a navigation event to complete. It's typically used in conjunction with actions that trigger navigation, such as clicking a link or submitting a form. Ensure to start the wait and the action concurrently to avoid missing the navigation event. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); const link = await page.$("a[href='/blog']"); // Start both at the same time to avoid missing the event await Promise.all([ page.waitForNavigation({ waitUntil: "networkidle2" }), link!.click(), ]); console.log(page.url); // "https://deno.land/blog" ``` -------------------------------- ### Race-condition-safe Element Interaction Source: https://context7.com/lino-levan/astral/llms.txt Use `page.locator` to get a `Locator` object that automatically waits for elements before interacting, making automation more robust against timing issues. Recommended over `page.$()` for reliable interactions. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); // Click safely — waits for button to exist await page.locator("button").click(); // Fill a form input await page.locator("#search-input").fill("astral"); // Evaluate in context of a located element const href = await page.locator("a.hero-cta").evaluate( (el) => el.href, ); console.log(href); // Chain locators for scoped queries const nav = page.locator("nav"); const firstNavLink = await nav.locator("a").$("span"); ``` -------------------------------- ### Define and use an HTTP interceptor Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/interceptor.md Define an interceptor function to handle requests. Throw an InterceptorError to fail the request, return a Response object to fulfill it, or return nothing to let the request continue. This example intercepts requests to '/blocked' and fails them, while fulfilling all other requests with custom HTML. ```typescript await using browser = await launch(); await using page = await browser.newPage("http://example.com", { interceptor(request: Request) { if (new URL(request.url).pathname === "/blocked") { throw new InterceptorError("BlockedByClient"); } return new Response( "Intercepted request!", { status: 200, headers: { "content-type": "text/html" } }, ); }, }); ``` -------------------------------- ### Launch Browser and Open Sandboxed Pages Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/sandbox.md Launches a browser instance and opens two pages with sandbox mode enabled. The first page is for a network request to 'example.com', and the second is for a local file. This code will throw a `Deno.errors.PermissionDenied` if the necessary permissions are not granted. ```typescript import { launch } from "jsr:@astral/astral"; import { fromFileUrl } from "@std/path/from-file-url"; // Launch browser const browser = await launch(); // Open the page if permission granted, or throws Deno.errors.PermissionDenied { const { state } = await Deno.permissions.query({ name: "net", path: "example.com", }); await browser.newPage("https://example.com", { sandbox: true }); } // Open the page if permission granted, or throws Deno.errors.PermissionDenied { const { state } = await Deno.permissions.query({ name: "read", path: fromFileUrl(import.meta.url), }); await browser.newPage(fromFileUrl(import.meta.url), { sandbox: true }); } // Close browser await browser.close(); ``` -------------------------------- ### `launch(opts?)` — Launch a browser instance Source: https://context7.com/lino-levan/astral/llms.txt Spawns a new local Chromium browser process and returns a `Browser` instance. Auto-downloads the browser binary if not present. Supports headless/headful mode, custom binary path, extra args, and launch presets. ```APIDOC ## `launch(opts?)` — Launch a browser instance ### Description Spawns a new local Chromium browser process (or Firefox) and returns a `Browser` instance. Auto-downloads the browser binary if not present. Supports headless/headful mode, custom binary path, extra args, and launch presets. ### Method ```ts await using browser = await launch(); // Launch headful with a custom window size await using browser2 = await launch({ headless: false, launchPresets: { windowSize: { width: 1280, height: 800 }, }, }); // Launch with a specific cached binary directory await using browser3 = await launch({ product: "chrome", cache: "/tmp/my-browser-cache", }); ``` ### Example Usage ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); console.log(await browser.version()); // e.g. "HeadlessChrome/124.0.6367.60" ``` ``` -------------------------------- ### Sandbox Page with Specific Network Permissions Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/sandbox.md Opens a new page with sandbox mode enabled, restricting network access to only 'example.com'. This requires the `--unstable-worker-options` flag to be enabled. ```typescript await using browser = await launch(); await using page = await browser.newPage("https://example.com", { sandbox: { permissions: { net: ["example.com"] } }, }); ``` -------------------------------- ### Get All Attributes from an Element Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/attributes.md Use `getAttributes()` to retrieve all attributes of a selected element. This method returns an object containing key-value pairs of the element's attributes. Ensure the element is correctly selected before calling this method. ```typescript import { launch } from "jsr:@astral/astral"; const browser = await launch(); const page = await browser.newPage("https://deno.land"); const element = await page.$("img"); const attributes = await element.getAttributes(); console.log(attributes); /* { class: "max-w-[28rem] hidden lg:block", src: "/runtime/deno-looking-up.svg?__frsh_c=6f92b045bc7486e03053e1977adceb7e4aa071f4", alt: "", width: "670", height: "503" } */ await browser.close(); ``` -------------------------------- ### Set Browser Arguments Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/env_vars.md Use ASTRAL_BIN_ARGS to pass additional arguments to the browser binary. These arguments are appended to any provided in launch() calls, useful for containerized environments. ```dockerfile ENV ASTRAL_BIN_ARGS="--no-sandbox" ``` -------------------------------- ### Get a Specific Attribute from an Element Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/attributes.md Use `getAttribute(attributeName)` to retrieve the value of a specific attribute from a selected element. Pass the name of the desired attribute as a string argument. This is useful when you only need one piece of information from an element. ```typescript import { launch } from "jsr:@astral/astral"; const browser = await launch(); const page = await browser.newPage("https://deno.land"); const element = await page.$("img"); const src = await element.getAttribute("src"); console.log(src); /* "/runtime/deno-looking-up.svg?__frsh_c=6f92b045bc7486e03053e1977adceb7e4aa071f4" */ await browser.close(); ``` -------------------------------- ### Touch event simulation Source: https://context7.com/lino-levan/astral/llms.txt The Touchscreen instance on each page dispatches touchstart, touchend, touchMove, and compound tap() events for mobile interaction testing. ```APIDOC ## `page.touchscreen` — Touch event simulation The `Touchscreen` instance on each page dispatches `touchstart`, `touchend`, `touchMove`, and compound `tap()` events for mobile interaction testing. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.setViewportSize({ width: 390, height: 844 }); await page.goto("https://example.com"); // Simple tap await page.touchscreen.tap(200, 400); // Swipe gesture (touch move) await page.touchscreen.touchStart(200, 600); await page.touchscreen.touchMove(200, 200); await page.touchscreen.touchEnd(); ``` ``` -------------------------------- ### page.goto(url, options?) Source: https://context7.com/lino-levan/astral/llms.txt Navigates the browser page to a specified URL and waits for the page to fully load. It supports various `waitUntil` strategies for controlling when the navigation is considered complete. ```APIDOC ## `page.goto(url, options?)` — Navigate to a URL Navigates the page to the given URL and waits for the page to load. Accepts `waitUntil` strategies: `"load"`, `"networkidle0"`, `"networkidle2"`, or `"none"`. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.goto("https://example.com", { waitUntil: "networkidle2" }); console.log(page.url); // "https://example.com/" await page.goto("https://deno.land", { waitUntil: "load" }); console.log(await page.evaluate(() => document.title)); ``` ``` -------------------------------- ### Navigate to a URL Source: https://context7.com/lino-levan/astral/llms.txt Use `page.goto` to navigate to a URL and wait for the page to load. Supports different `waitUntil` strategies for controlling when navigation is considered complete. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.goto("https://example.com", { waitUntil: "networkidle2" }); console.log(page.url); // "https://example.com/" await page.goto("https://deno.land", { waitUntil: "load" }); console.log(await page.evaluate(() => document.title)); ``` -------------------------------- ### Reuse Existing Browser Instance with Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Demonstrates how to connect to an already launched browser instance by obtaining its WebSocket endpoint. ```typescript const browser = await launch(); const anotherBrowser = await connect({ endpoint: browser.wsEndpoint() }); ``` -------------------------------- ### Launch Astral Page with Coverage Enabled Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/coverage.md This code demonstrates how to launch a browser page with code coverage enabled using Astral. Ensure the necessary environment variables (`DENO_DIR`, `DENO_COVERAGE_DIR`) are set and the `--allow-sys=inspector` permission is granted. ```typescript // Import Astral import { launch } from "jsr:@astral/astral"; import { fromFileUrl } from "@std/path/from-file-url"; // Launch a browser page with coverage enabled await using browser = await launch(); await using page = await browser.newPage("http://example.com", { coverage: true, }); // Run your code await page.evaluate(() => { console.log("foo"); console.log("bar"); }); ``` -------------------------------- ### Launch a browser instance with Astral Source: https://context7.com/lino-levan/astral/llms.txt Launches a new local Chromium browser process. Supports headless/headful mode, custom binary path, and launch presets. Auto-downloads the browser binary if not present. ```typescript import { launch } from "jsr:@astral/astral"; // Launch headless (default) await using browser = await launch(); // Launch headful with a custom window size await using browser2 = await launch({ headless: false, launchPresets: { windowSize: { width: 1280, height: 800 }, }, }); // Launch with a specific cached binary directory await using browser3 = await launch({ product: "chrome", cache: "/tmp/my-browser-cache", }); console.log(await browser.version()); // e.g. "HeadlessChrome/124.0.6367.60" ``` -------------------------------- ### Configure Sandbox Permissions for Network Access Source: https://context7.com/lino-levan/astral/llms.txt Enable sandbox mode to control page network, file, and script import access via Deno permissions. Can inherit all permissions, specify subsets, or deny all network access. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); // Inherit all Deno permissions (sandbox: true) await using page1 = await browser.newPage("https://example.com", { sandbox: true, }); // Only allow requests to example.com await using page2 = await browser.newPage("https://example.com", { sandbox: { permissions: { net: ["example.com"], }, }, }); // No network access at all await using page3 = await browser.newPage("https://example.com", { sandbox: { permissions: "none", }, }); ``` -------------------------------- ### `browser.newPage(url?, options?)` — Open a new page/tab Source: https://context7.com/lino-levan/astral/llms.txt Creates a new browser tab, optionally navigating to a URL. Accepts options for sandbox permissions, HTTP interceptor, coverage, user agent, and navigation wait strategy. ```APIDOC ## `browser.newPage(url?, options?)` — Open a new page/tab ### Description Creates a new browser tab, optionally navigating to a URL. Accepts options for sandbox permissions, HTTP interceptor, coverage, user agent, and navigation wait strategy. ### Method ```ts // Open a blank page const blank = await browser.newPage(); // Open a URL and wait for network to be idle const page = await browser.newPage("https://example.com", { waitUntil: "networkidle2", userAgent: "MyBot/1.0", }); ``` ### Example Usage ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); // Open a blank page const blank = await browser.newPage(); // Open a URL and wait for network to be idle const page = await browser.newPage("https://example.com", { waitUntil: "networkidle2", userAgent: "MyBot/1.0", }); console.log(page.url); // "https://example.com/" console.log(browser.pages.length); // 2 await page.close(); await blank.close(); ``` ``` -------------------------------- ### Take a Page Screenshot Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/screenshot.md Launches a browser, navigates to a URL, takes a screenshot, and saves it to a file. Ensure Astral is imported correctly. ```typescript // Import Astral import { launch } from "jsr:@astral/astral"; // Launch the browser const browser = await launch(); // Open a new page const page = await browser.newPage("https://deno.land"); // Take a screenshot of the page and save that to disk const screenshot = await page.screenshot(); Deno.writeFileSync("screenshot.png", screenshot); // Close the browser await browser.close(); ``` -------------------------------- ### Simulate Touchscreen Events with page.touchscreen Source: https://context7.com/lino-levan/astral/llms.txt Dispatch touch events like touchstart, touchend, touchMove, and compound tap() for mobile interaction testing. Requires setting viewport size. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.setViewportSize({ width: 390, height: 844 }); await page.goto("https://example.com"); // Simple tap await page.touchscreen.tap(200, 400); // Swipe gesture (touch move) await page.touchscreen.touchStart(200, 600); await page.touchscreen.touchMove(200, 200); await page.touchscreen.touchEnd(); ``` -------------------------------- ### Complex Navigation with Astral Source: https://github.com/lino-levan/astral/blob/main/docs/pages/guides/navigation.md This script demonstrates launching a browser, navigating to a page, interacting with elements like buttons and inputs, and waiting for network activity before proceeding. It includes clicking links and waiting for navigation to complete. ```typescript // Import Astral import { launch } from "jsr:@astral/astral"; // Launch browser in headfull mode const browser = await launch({ headless: false }); // Open the webpage const page = await browser.newPage("https://deno.land"); // Click the search button const button = await page.$("button"); await button!.click(); // Type in the search input const input = await page.$("#search-input"); await input!.type("pyro", { delay: 1000 }); // Wait for the search results to come back await page.waitForNetworkIdle({ idleConnections: 0, idleTime: 1000 }); // Click the 'pyro' link const xLink = await page.$("a.justify-between:nth-child(1)"); await Promise.all([ page.waitForNavigation(), xLink!.click(), ]); // Click the link to 'pyro.deno.dev' const dLink = await page.$( ".markdown-body > p:nth-child(8) > a:nth-child(1)", ); await Promise.all([ page.waitForNavigation(), dLink!.click(), ]); // Close browser await browser.close(); ``` -------------------------------- ### Emulate CPU Throttling with page.emulateCPUThrottling() Source: https://context7.com/lino-levan/astral/llms.txt Simulates a slower CPU for performance profiling. Use a factor greater than 1 to slow down JavaScript execution. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); await page.emulateCPUThrottling(4); // 4x slowdown const start = Date.now(); await page.evaluate(() => { let sum = 0; for (let i = 0; i < 1_000_000; i++) sum += i; return sum; }); console.log(`Took ${Date.now() - start}ms under 4x CPU throttle`); ``` -------------------------------- ### Sandbox Permissions — Restrict page network access Source: https://context7.com/lino-levan/astral/llms.txt Enable sandbox mode to gate all page network, file, and script imports through Deno's permission system. Pass true to inherit current permissions, or specify a subset explicitly. ```APIDOC ## Sandbox Permissions — Restrict page network access Enable `sandbox` mode to gate all page network, file, and script imports through Deno's permission system. Pass `true` to inherit current permissions, or specify a subset explicitly. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); // Inherit all Deno permissions (sandbox: true) await using page1 = await browser.newPage("https://example.com", { sandbox: true, }); // Only allow requests to example.com await using page2 = await browser.newPage("https://example.com", { sandbox: { permissions: { net: ["example.com"], }, }, }); // No network access at all await using page3 = await browser.newPage("https://example.com", { sandbox: { permissions: "none", }, }); ``` ``` -------------------------------- ### Take a Screenshot with Astral Source: https://github.com/lino-levan/astral/blob/main/docs/pages/index.md Launches a browser, opens a page, takes a screenshot, and saves it to disk. Ensure Astral is imported correctly. ```typescript import { launch } from "jsr:@astral/astral"; // Launch the browser const browser = await launch(); // Open a new page const page = await browser.newPage("https://deno.land"); // Take a screenshot of the page and save that to disk const screenshot = await page.screenshot(); Deno.writeFileSync("screenshot.png", screenshot); // Close the browser await browser.close(); ``` -------------------------------- ### Simulate Keyboard Input with page.keyboard Source: https://context7.com/lino-levan/astral/llms.txt Use type(), press(), down(), and up() for full keyboard simulation, including modifier keys. Specify a delay option for typing. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); // Click search button and type a query const btn = await page.$("button"); await btn!.click(); await page.keyboard.type("deno deploy", { delay: 80 }); // Press Enter to submit await page.keyboard.press("Enter"); // Keyboard shortcut: Ctrl+A to select all await page.keyboard.down("Control"); await page.keyboard.press("KeyA"); await page.keyboard.up("Control"); ``` -------------------------------- ### Deno Coverage With Astral Enabled Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/coverage.md This diff illustrates the improved coverage achieved when Astral's coverage feature is enabled, showing 100% coverage. ```diff + cover file:///workspaces/astral/tests/coverage.ts ... 100.000% (13/13) ``` -------------------------------- ### page.emulateCPUThrottling(factor) Source: https://context7.com/lino-levan/astral/llms.txt Simulates slow CPUs by throttling JavaScript execution. A higher factor results in slower execution, useful for performance profiling. ```APIDOC ## `page.emulateCPUThrottling(factor)` — Simulate slow CPUs Throttles the browser's JavaScript CPU execution. A factor of `4` means 4× slower than normal, useful for performance profiling. ### Parameters #### Path Parameters - **factor** (number) - Required - The throttling factor (e.g., 4 for 4x slower). ### Request Example ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); await page.emulateCPUThrottling(4); // 4x slowdown const start = Date.now(); await page.evaluate(() => { let sum = 0; for (let i = 0; i < 1_000_000; i++) sum += i; return sum; }); console.log(`Took ${Date.now() - start}ms under 4x CPU throttle`); ``` ``` -------------------------------- ### page.emulateMediaFeatures(features) Source: https://context7.com/lino-levan/astral/llms.txt Enables emulation of CSS media features, such as color scheme and reduced motion, which is useful for testing responsive designs and accessibility. ```APIDOC ## `page.emulateMediaFeatures(features)` — Emulate CSS media features Overrides the browser's CSS media features such as `prefers-color-scheme` or `prefers-reduced-motion` for testing responsive designs. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); // Emulate dark mode await page.emulateMediaFeatures([ { name: "prefers-color-scheme", value: "dark" }, ]); // Emulate reduced motion await page.emulateMediaFeatures([ { name: "prefers-reduced-motion", value: "reduce" }, ]); const screenshot = await page.screenshot(); Deno.writeFileSync("dark-mode.png", screenshot); ``` ``` -------------------------------- ### Navigate Browser History with page.goBack() and page.goForward() Source: https://context7.com/lino-levan/astral/llms.txt Navigates backward or forward in the browser's session history. This is equivalent to clicking the browser's Back or Forward buttons. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); await page.goto("https://deno.land/blog", { waitUntil: "networkidle2" }); console.log(page.url); // https://deno.land/blog await page.goBack(); console.log(page.url); // https://deno.land/ await page.goForward(); console.log(page.url); // https://deno.land/blog ``` -------------------------------- ### Take Website Screenshot with Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Launches a browser, navigates to a URL, takes a screenshot, and saves it to disk. Automatic cleanup is handled. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); const screenshot = await page.screenshot(); Deno.writeFileSync("screenshot.png", screenshot); ``` -------------------------------- ### Listen to Page Events with page.addEventListener() Source: https://context7.com/lino-levan/astral/llms.txt Listens for various page-level events such as console output, dialogs, file choosers, and page errors. Requires importing 'launch' from '@astral/astral'. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); // Listen to console output from the page page.addEventListener("console", (e) => { console.log(`[Browser ${e.detail.type}]:`, e.detail.text); }); // Handle JS alert dialogs automatically page.addEventListener("dialog", async (e) => { const dialog = e.detail; console.log("Dialog:", dialog.type, "-", dialog.message); await dialog.accept("my input"); // or dialog.dismiss() }); // Catch page-level errors page.addEventListener("pageerror", (e) => { console.error("Uncaught page error:", e.detail.message); }); await page.goto("https://example.com"); await page.evaluate(() => { console.log("Hello from browser!"); alert("Please confirm"); }); ``` -------------------------------- ### `connect(opts)` — Connect to a remote browser Source: https://context7.com/lino-levan/astral/llms.txt Connects Astral to an already-running browser instance via WebSocket or HTTP endpoint. Useful for remote services like browserless.io or for reusing a browser spawned by Astral itself. ```APIDOC ## `connect(opts)` — Connect to a remote browser ### Description Connects Astral to an already-running browser instance via WebSocket or HTTP endpoint. Useful for remote services like [browserless.io](https://www.browserless.io/) or for reusing a browser spawned by Astral itself. ### Method ```ts const browser = await connect({ endpoint: "wss://chrome.browserless.io?token=MY_TOKEN", }); // Reuse a browser already launched by Astral const localBrowser = await launch(); const wsEndpoint = localBrowser.wsEndpoint(); const secondConnection = await connect({ endpoint: wsEndpoint }); ``` ### Example Usage ```ts import { connect, launch } from "jsr:@astral/astral"; // Connect to a remote service const browser = await connect({ endpoint: "wss://chrome.browserless.io?token=MY_TOKEN", }); const page = await browser.newPage("https://example.com"); console.log(await page.evaluate(() => document.title)); await browser.close(); // Reuse a browser already launched by Astral const localBrowser = await launch(); const wsEndpoint = localBrowser.wsEndpoint(); const secondConnection = await connect({ endpoint: wsEndpoint }); const page2 = await secondConnection.newPage("https://deno.land"); console.log(page2.url); await secondConnection.disconnect(); // disconnect without killing the process await localBrowser.close(); ``` ``` -------------------------------- ### page.goBack() / page.goForward() Source: https://context7.com/lino-levan/astral/llms.txt Navigates backward or forward in the browser's session history, mimicking the behavior of browser navigation buttons. ```APIDOC ## `page.goBack()` / `page.goForward()` — Browser history navigation Navigate backward or forward in the browser's session history, equivalent to clicking the browser's Back/Forward buttons. ### Method - `goBack()`: Navigates to the previous page in history. - `goForward()`: Navigates to the next page in history. ### Request Example ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); await page.goto("https://deno.land/blog", { waitUntil: "networkidle2" }); console.log(page.url); // https://deno.land/blog await page.goBack(); console.log(page.url); // https://deno.land/ await page.goForward(); console.log(page.url); // https://deno.land/blog ``` ``` -------------------------------- ### Low-level keyboard control Source: https://context7.com/lino-levan/astral/llms.txt The Keyboard instance on each page exposes type(), press(), down(), up(), and sendCharacter() for simulating full keyboard input including modifier keys. ```APIDOC ## `page.keyboard` — Low-level keyboard control The `Keyboard` instance on each page exposes `type()`, `press()`, `down()`, `up()`, and `sendCharacter()` for simulating full keyboard input including modifier keys. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); // Click search button and type a query const btn = await page.$("button"); await btn!.click(); await page.keyboard.type("deno deploy", { delay: 80 }); // Press Enter to submit await page.keyboard.press("Enter"); // Keyboard shortcut: Ctrl+A to select all await page.keyboard.down("Control"); await page.keyboard.press("KeyA"); await page.keyboard.up("Control"); ``` ``` -------------------------------- ### page.waitForNavigation(options?) Source: https://context7.com/lino-levan/astral/llms.txt Waits for a page navigation to complete. This is useful when triggering actions that lead to a new page load, such as clicking links or submitting forms. ```APIDOC ## `page.waitForNavigation(options?)` — Wait for page navigation Returns a promise that resolves once the page has navigated. Use together with actions that trigger navigation (clicking links, form submits). ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); const link = await page.$("a[href='/blog']"); // Start both at the same time to avoid missing the event await Promise.all([ page.waitForNavigation({ waitUntil: "networkidle2" }), link!.click(), ]); console.log(page.url); // "https://deno.land/blog" ``` ``` -------------------------------- ### page.authenticate(credentials) Source: https://context7.com/lino-levan/astral/llms.txt Configures HTTP Basic Authentication by setting an Authorization header for all subsequent requests made by the page. ```APIDOC ## `page.authenticate(credentials)` — HTTP Basic Auth Sets an `Authorization: Basic …` header on all subsequent requests made by the page, enabling access to HTTP-authenticated resources. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.authenticate({ username: "postman", password: "password" }); await page.goto("https://postman-echo.com/basic-auth", { waitUntil: "networkidle2", }); const body = await page.evaluate(() => document.body.innerText); console.log(body); // {"authenticated":true} ``` ``` -------------------------------- ### `page.screenshot(opts?)` — Capture a page screenshot Source: https://context7.com/lino-levan/astral/llms.txt Captures the current page as a PNG (or other format) and returns raw `Uint8Array` bytes. Supports format, quality, full-page, and clip options passed directly to the CDP `Page.captureScreenshot` command. ```APIDOC ## `page.screenshot(opts?)` — Capture a page screenshot ### Description Captures the current page as a PNG (or other format) and returns raw `Uint8Array` bytes. Supports format, quality, full-page, and clip options passed directly to the CDP `Page.captureScreenshot` command. ### Method ```ts // Default PNG screenshot const png = await page.screenshot(); // JPEG screenshot with quality setting const jpg = await page.screenshot({ format: "jpeg", quality: 80 }); ``` ### Example Usage ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); // Default PNG screenshot const png = await page.screenshot(); Deno.writeFileSync("deno-land.png", png); // JPEG screenshot with quality setting const jpg = await page.screenshot({ format: "jpeg", quality: 80 }); Deno.writeFileSync("deno-land.jpg", jpg); ``` ``` -------------------------------- ### `page.pdf(opts?)` — Generate a PDF Source: https://context7.com/lino-levan/astral/llms.txt Prints the page to a PDF and returns `Uint8Array` bytes. Accepts standard CDP `Page.printToPDF` options such as `printBackground`, `paperWidth`, `paperHeight`, and margins. ```APIDOC ## `page.pdf(opts?)` — Generate a PDF ### Description Prints the page to a PDF and returns `Uint8Array` bytes. Accepts standard CDP `Page.printToPDF` options such as `printBackground`, `paperWidth`, `paperHeight`, and margins. ### Method ```ts const pdf = await page.pdf({ printBackground: true, paperWidth: 8.5, paperHeight: 11, marginTop: 0.5, marginBottom: 0.5, }); ``` ### Example Usage ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); const pdf = await page.pdf({ printBackground: true, paperWidth: 8.5, paperHeight: 11, marginTop: 0.5, marginBottom: 0.5, }); Deno.writeFileSync("output.pdf", pdf); ``` ``` -------------------------------- ### page.$(selector) and page.$$(selector) Source: https://context7.com/lino-levan/astral/llms.txt Queries the DOM for elements using CSS selectors. `page.$()` returns a single `ElementHandle` for the first matching element, while `page.$$()` returns an array of `ElementHandle`s for all matching elements. ```APIDOC ## `page.$(selector)` and `page.$$(selector)` — Query DOM elements Runs `document.querySelector` or `document.querySelectorAll` and returns one or more `ElementHandle` objects for further interaction. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); // Single element const btn = await page.$("button"); if (btn) { await btn.click(); } // All matching elements const links = await page.$$("a[href]"); for (const link of links) { console.log(await link.getAttribute("href")); } ``` ``` -------------------------------- ### Generate a PDF from a page with Astral Source: https://context7.com/lino-levan/astral/llms.txt Prints the page to a PDF and returns `Uint8Array` bytes. Accepts standard CDP `Page.printToPDF` options such as `printBackground`, `paperWidth`, `paperHeight`, and margins. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); const pdf = await page.pdf({ printBackground: true, paperWidth: 8.5, paperHeight: 11, marginTop: 0.5, marginBottom: 0.5, }); Deno.writeFileSync("output.pdf", pdf); ``` -------------------------------- ### Low-Level Mouse Control with page.mouse Source: https://context7.com/lino-levan/astral/llms.txt Provides precise mouse control through methods like move(), click(), down(), up(), and wheel(). Coordinates are in CSS pixels. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com"); // Move mouse and click at a coordinate await page.mouse.move(400, 300); await page.mouse.click(400, 300); // Smooth drag simulation (10 steps) await page.mouse.move(100, 100); await page.mouse.down(); await page.mouse.move(300, 300, { steps: 10 }); await page.mouse.up(); // Scroll down await page.mouse.wheel({ deltaY: 500 }); ``` -------------------------------- ### Connect to BYOB Browser Endpoint with Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Connects to a browser instance launched manually with specific flags, using its remote debugging port. Allows specifying headless mode and other options. ```typescript import { connect } from "jsr:@astral/astral"; const browser = await connect({ endpoint: "localhost:1337", headless: false, }); console.log(browser.wsEndpoint()); const page = await browser.newPage("http://example.com"); console.log(await page.evaluate(() => document.title)); await browser.close(); ``` -------------------------------- ### Enable Code Coverage Collection Source: https://context7.com/lino-levan/astral/llms.txt Set coverage: true on a page to capture V8 code coverage for functions executed via page.evaluate(). Results are merged into Deno's coverage output. ```typescript import { launch } from "jsr:@astral/astral"; // Run with: deno test --coverage=cov_profile --allow-sys=inspector -A await using browser = await launch(); await using page = await browser.newPage("https://example.com", { coverage: true, }); await page.evaluate(() => { function greet(name: string) { return `Hello, ${name}!`; } console.log(greet("world")); }); // Coverage data written to DENO_COVERAGE_DIR automatically ``` -------------------------------- ### Open a new page/tab with Astral Source: https://context7.com/lino-levan/astral/llms.txt Creates a new browser tab, optionally navigating to a URL. Accepts options for sandbox permissions, HTTP interceptor, coverage, user agent, and navigation wait strategy. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); // Open a blank page const blank = await browser.newPage(); // Open a URL and wait for network to be idle const page = await browser.newPage("https://example.com", { waitUntil: "networkidle2", userAgent: "MyBot/1.0", }); console.log(page.url); // "https://example.com/" console.log(browser.pages.length); // 2 await page.close(); await blank.close(); ``` -------------------------------- ### page.addEventListener(event, listener) Source: https://context7.com/lino-levan/astral/llms.txt Listens for page-level events such as console output, dialogs, file choosers, and page errors. ```APIDOC ## `page.addEventListener(event, listener)` — Page events Listen to page-level events: `"console"` (browser console output), `"dialog"` (JS dialogs), `"filechooser"` (file input dialogs), and `"pageerror"` (uncaught exceptions). ### Parameters #### Path Parameters - **event** (string) - Required - The name of the event to listen for (e.g., `"console"`, `"dialog"`). - **listener** (function) - Required - The callback function to execute when the event is fired. ### Request Example ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); // Listen to console output from the page page.addEventListener("console", (e) => { console.log(`[Browser ${e.detail.type}]:`, e.detail.text); }); // Handle JS alert dialogs automatically page.addEventListener("dialog", async (e) => { const dialog = e.detail; console.log("Dialog:", dialog.type, "-", dialog.message); await dialog.accept("my input"); // or dialog.dismiss() }); // Catch page-level errors page.addEventListener("pageerror", (e) => { console.error("Uncaught page error:", e.detail.message); }); await page.goto("https://example.com"); await page.evaluate(() => { console.log("Hello from browser!"); alert("Please confirm"); }); ``` ``` -------------------------------- ### HTTP Authentication with Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Provides credentials for HTTP basic authentication on a given URL and navigates to the page. Requires username and password. ```typescript const page = await browser.newPage(); const url = "https://postman-echo.com/basic-auth"; await page.authenticate({ username: "postman", password: "password" }); await page.goto(url, { waitUntil: "networkidle2" }); ``` -------------------------------- ### page.setContent(html) / page.content() Source: https://context7.com/lino-levan/astral/llms.txt Allows setting the entire HTML content of a page programmatically or retrieving the current full HTML, including the DOCTYPE declaration. ```APIDOC ## `page.setContent(html)` / `page.content()` — Set and get page HTML Replaces the entire page HTML with a provided string, or retrieves the full HTML including `DOCTYPE`. ```ts import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage(); await page.setContent(`

Hello, Astral!

`); const html = await page.content(); console.log(html); // Full HTML with DOCTYPE const text = await page.evaluate(() => (document.getElementById("title") as HTMLElement).innerText ); console.log(text); // "Hello, Astral!" ``` ``` -------------------------------- ### Code Coverage — Collect browser-side coverage Source: https://context7.com/lino-levan/astral/llms.txt Enable coverage: true on a page to capture V8 code coverage for functions passed to page.evaluate(), merging results back into Deno's coverage output. ```APIDOC ## Code Coverage — Collect browser-side coverage Enable `coverage: true` on a page to capture V8 code coverage for functions passed to `page.evaluate()`, merging results back into Deno's coverage output. ```ts import { launch } from "jsr:@astral/astral"; // Run with: deno test --coverage=cov_profile --allow-sys=inspector -A await using browser = await launch(); await using page = await browser.newPage("https://example.com", { coverage: true, }); await page.evaluate(() => { function greet(name: string) { return `Hello, ${name}`; } console.log(greet("world")); }); // Coverage data written to DENO_COVERAGE_DIR automatically ``` ``` -------------------------------- ### Deno Coverage Before Astral Source: https://github.com/lino-levan/astral/blob/main/docs/pages/advanced/coverage.md This diff shows typical Deno coverage output where functions within `Page.evaluate()` are not covered. ```diff - cover file:///workspaces/astral/tests/coverage.ts ... 33.333% (4/12) - 7 | await page.evaluate(() => { - 8 | console.log("foo"); - 9 | console.log("bar"); - 10 | }); ``` -------------------------------- ### Connect to a remote browser instance with Astral Source: https://context7.com/lino-levan/astral/llms.txt Connects Astral to an already-running browser instance via WebSocket or HTTP endpoint. Useful for remote services like browserless.io or for reusing a browser spawned by Astral itself. ```typescript import { connect, launch } from "jsr:@astral/astral"; // Connect to a remote service const browser = await connect({ endpoint: "wss://chrome.browserless.io?token=MY_TOKEN", }); const page = await browser.newPage("https://example.com"); console.log(await page.evaluate(() => document.title)); await browser.close(); // Reuse a browser already launched by Astral const localBrowser = await launch(); const wsEndpoint = localBrowser.wsEndpoint(); const secondConnection = await connect({ endpoint: wsEndpoint }); const page2 = await secondConnection.newPage("https://deno.land"); console.log(page2.url); await secondConnection.disconnect(); // disconnect without killing the process await localBrowser.close(); ``` -------------------------------- ### HTTP Interceptor — Mock and block network requests Source: https://context7.com/lino-levan/astral/llms.txt Pass an interceptor function to browser.newPage() to intercept every network request. Return a Response to mock it, null/undefined to allow it through, or throw InterceptorError to block it. ```APIDOC ## HTTP Interceptor — Mock and block network requests Pass an `interceptor` function to `browser.newPage()` to intercept every network request. Return a `Response` to mock it, `null`/`undefined` to allow it through, or throw `InterceptorError` to block it. ```ts import { InterceptorError, launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://example.com", { interceptor(request: Request, { resourceType }) { const url = new URL(request.url); // Block ad/tracking domains if (url.hostname.includes("analytics.google.com")) { throw new InterceptorError("BlockedByClient"); } // Mock a specific API endpoint if (url.pathname === "/api/user") { return new Response(JSON.stringify({ id: 1, name: "Alice" }), { status: 200, headers: { "content-type": "application/json" }, }); } // Allow everything else return null; }, }); const user = await page.evaluate(async () => { const res = await fetch("/api/user"); return await res.json(); }); console.log(user); // { id: 1, name: "Alice" } ``` ``` -------------------------------- ### Evaluate JavaScript in Browser Context with Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Launches a browser, navigates to a URL, and executes JavaScript within the browser's context. Supports passing arguments to the evaluated function. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch(); await using page = await browser.newPage("https://deno.land"); const value = await page.evaluate(() => { return document.body.innerHTML; }); console.log(value); const result = await page.evaluate((x, y) => { return `The result of adding ${x}+${y} = ${x + y}`; }, { args: [10, 15], }); console.log(result); ``` -------------------------------- ### Interact with Web Page Elements using Astral Source: https://github.com/lino-levan/astral/blob/main/README.md Launches a browser in headful mode, navigates to a URL, and performs actions like clicking buttons, typing into input fields, and waiting for network activity or navigation. ```typescript import { launch } from "jsr:@astral/astral"; await using browser = await launch({ headless: false }); await using page = await browser.newPage("https://deno.land"); const button = await page.$("button"); await button!.click(); const input = await page.$("#search-input"); await input!.type("pyro", { delay: 1000 }); await page.waitForNetworkIdle({ idleConnections: 0, idleTime: 1000 }); const xLink = await page.$("a.justify-between:nth-child(1)"); await Promise.all([ page.waitForNavigation(), xLink!.click(), ]); const dLink = await page$( ".markdown-body > p:nth-child(8) > a:nth-child(1)", ); await Promise.all([ page.waitForNavigation(), dLink!.click(), ]); ```