Connect with WebDriver

View as Markdown

The WebDriver connection is a Run-scoped browser connection. When a browser Runtime starts, BCTRL returns a webDriverUrl for the same browser as its CDP connection. Pass that URL to Selenium Remote WebDriver.

The Runtime owns the browser process and configuration. Selenium attaches to the existing browser; it does not launch a second browser. The URL is valid only while its Run is active, so treat it as a credential.

Get the WebDriver URL

An ephemeral Runtime starts during creation:

1const runtime = await bctrl.runtimes.create({
2 name: "checkout-job",
3});
4
5if (!runtime.connection) throw new Error("Runtime did not start");
6const { webDriverUrl, runId } = runtime.connection;

For a reusable profile-backed Runtime, start it when you need a session:

1const runtime = await bctrl.runtimes.create({
2 name: "customer-portal",
3 profile: true,
4});
5
6const started = await bctrl.runtimes.start(runtime.id);
7const { webDriverUrl, runId } = { ...started.connection, runId: started.runId };

The connection fields are:

FieldTypeAlways presentMeaning
connection.webDriverUrlstringYesRun-scoped Selenium endpoint for the active browser Run.
connection.cdpUrlstringYesCDP endpoint for the same browser.
runIdstringYesRun that owns both connections.
connection.recording{ enabled: boolean }YesWhether Run recording is enabled.

Both endpoints remain stable for the lifetime of the Run and stop working when the Run ends. Do not log, persist, or expose them to page code.

JavaScript

Install selenium-webdriver, then use webDriverUrl as the remote server:

1import { Builder, By } from "selenium-webdriver";
2
3const driver = await new Builder()
4 .usingServer(webDriverUrl)
5 .forBrowser("chrome")
6 .build();
7
8try {
9 await driver.get("https://example.com");
10 console.log(await driver.findElement(By.css("h1")).getText());
11} finally {
12 await driver.quit();
13}

driver.quit() closes the Selenium session. Stop the BCTRL Runtime separately when the automation is complete.

Python

1from selenium import webdriver
2
3options = webdriver.ChromeOptions()
4driver = webdriver.Remote(
5 command_executor=webdriver_url,
6 options=options,
7)
8
9try:
10 driver.get("https://example.com")
11 print(driver.title)
12finally:
13 driver.quit()

Coordinate controllers

Selenium, the external CDP client, and hosted Agents can connect to the same browser Run. BCTRL does not serialize page-level actions between controllers. Coordinate navigation, clicks, and page ownership in your application so two controllers do not overwrite each other’s work.

The external CDP endpoint allows one external CDP controller at a time. CDP and WebDriver have separate connection endpoints; Views, recordings, traces, and events do not consume the external CDP slot.

Runtime-owned configuration

Configure browser arguments, browser version, profile, extensions, proxy, certificate policy, and other launch settings on the BCTRL Runtime. WebDriver capabilities do not replace Runtime launch configuration.

Remote file upload through Selenium is not supported. Use the Runtime file Tools to stage a durable File into the Runtime workspace, then upload it from the workspace path:

1await bctrl.tools.call("runtime.files.stage", {
2 fileId,
3 path: "input.csv",
4}, { runtimeId: runtime.id });

See Stage Runtime file and Collect Runtime file for the file transfer methods.

End the session

Stopping the Runtime ends the active Run and invalidates the WebDriver URL:

1const stopped = await bctrl.runtimes.stop(runtime.id);
2console.log(stopped.runId, stopped.status, stopped.stopped);

Use runId with Runs to inspect trace spans, raw events, recordings, usage, and files from the Selenium session.

Next

  • Connect with CDP — attach Playwright or Puppeteer
  • Runtimes — configure browser identity and launch options
  • Runs — inspect what happened during the session