Skip to content

Quick Start

import { ChromeWebView } from "webotron";
const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
headless: true,
initialUrl: "about:blank",
});
await view.navigate("https://example.com");
await view.waitForDocumentReady({ state: "complete", timeoutMs: 15000 });
await view.click("button");
await view.close();
  1. The facade starts Chrome and connects over CDP.
  2. waitForDocumentReady makes sure navigation is finished before automation begins.
  3. The DOM, input, and evaluation APIs stay available through the same instance.

ChromeWebView stores browser state in a Chrome profile directory. You can let the library manage that directory, or choose your own.

When you do not provide userDataDir, ChromeWebView uses a stable shared temp profile by default. That means cookies, local storage, and login state can persist across runs.

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
});

Use this when you want a convenient reusable profile without managing a path yourself.

If you want a fresh generated profile for that instance, set profile.isolation to "isolated".

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
},
});

Use this when you want test-style isolation or do not want one run to reuse another run’s browser state.

Generated isolated profiles are removed on close() by default.

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
},
});

This only applies to generated isolated profiles. The default shared temp profile is not auto-deleted.

If you want to keep an isolated generated profile after close(), set cleanupEphemeral: false.

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
cleanupEphemeral: false,
},
});

If you want full control, pass userDataDir.

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
userDataDir: "./browser-profile",
});

userDataDir always wins over profile, so use it when you need a specific directory.

You can inspect the actual profile directory at runtime with getUserDataDir().

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
},
});
console.log("Profile path:", view.getUserDataDir());
console.log("Is ephemeral:", view.isEphemeralUserDataDir());
await view.close();

This is useful when the library generated the path for you and you want to log it, inspect it, or clean it up later.

If you want isolated generated profiles to auto-delete, you do not need any extra option because that is already the default.

const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
},
});
await view.close();

If you want to manage cleanup yourself, disable automatic cleanup first, then read the resolved path and remove it after close().

import { rmSync } from "node:fs";
const view = new ChromeWebView({
chromePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
profile: {
isolation: "isolated",
cleanupEphemeral: false,
},
});
const profilePath = view.getUserDataDir();
await view.close();
if (view.isEphemeralUserDataDir()) {
rmSync(profilePath, { recursive: true, force: true });
}

Avoid manually deleting a shared profile that you intend to reuse across runs.