VeilBrowserDocs

Automation

Drive VeilBrowser profiles with Puppeteer, Playwright and Selenium over CDP.

Once a profile is launched, VeilBrowser gives you a Chrome DevTools Protocol (CDP) endpoint. Any CDP-compatible framework can connect to it.

Field name

The Local API launch response returns the CDP URL as webSocketDebuggerUrl. Worker endpoints authenticate with an X-API-Key header. For a one-step, load-balanced launch over a single socket, see Cluster mode.

Launch once, then reuse webSocketDebuggerUrl in the examples below:

launch.ts
const res = await fetch("http://localhost:3000/sessions/profile", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.WORKER_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ profileId: "<profile-uuid>" }),
});
const { data } = await res.json();
const webSocketDebuggerUrl: string = data.webSocketDebuggerUrl;
puppeteer.ts
import puppeteer from "puppeteer-core";

const browser = await puppeteer.connect({
  browserWSEndpoint: webSocketDebuggerUrl,
});
const page = await browser.newPage();
await page.goto("https://example.com");
playwright.ts
import { chromium } from "playwright-core";

const browser = await chromium.connectOverCDP(webSocketDebuggerUrl);
const context = browser.contexts()[0];
const page = await context.newPage();
await page.goto("https://example.com");

Selenium attaches via debuggerAddress. Parse host and port from webSocketDebuggerUrl (for example ws://127.0.0.1:9222/devtools/...127.0.0.1:9222):

selenium.py
from urllib.parse import urlparse
from selenium import webdriver

# webSocketDebuggerUrl from the Local API launch response
ws = "ws://127.0.0.1:9222/devtools/browser/..."
parsed = urlparse(ws)
debugger_address = f"{parsed.hostname}:{parsed.port}"

options = webdriver.ChromeOptions()
options.add_experimental_option("debuggerAddress", debugger_address)
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")

Orchestration

Provision profiles through the cloud API / dashboard (session auth). Launch and stop on workers via the Local API (POST /sessions/profile, DELETE /sessions/:id) or cluster /launch, then attach your automation framework to each webSocketDebuggerUrl.

Keep sessions short and idempotent

Design automation so a session can be retried safely. Launch, do one unit of work, stop — then move to the next profile.

Was this page helpful?

On this page