### 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(),
]);
```