skip to content

In Selenium 4, why does a cross-browser hotel booking-calendar suite prefer WebDriver BiDi to the Chromium-only DevTools bridge?

level: seniorimportance: should knowfreq 42%

answer

  1. Two push channels, only one is standard
  2. Which browsers can honour the subscription
  3. Bindings pinned to a browser major version
  4. W3C specification versus a vendor debugging protocol
  5. The webSocketUrl capability negotiates the standard one

basics

~10 s

WebDriver BiDi is a W3C-specified channel that Chromium browsers and Firefox both speak, so one subscription covers the whole matrix. The DevTools bridge is Chromium-only and pinned to browser versions.

solid answer

~50 s

In Selenium 4 both push channels exist, but they are not equivalent. The Chromium DevTools bridge is a browser-vendor debugging protocol: it only exists for Chromium-based browsers, and Selenium wraps it in version-pinned bindings that have to track the browser's major version. WebDriver BiDi is a W3C specification written beside the WebDriver spec, negotiated with the `webSocketUrl` capability, and carrying a fixed catalogue of modules and events such as `log.entryAdded`, `network.beforeRequestSent` and `browsingContext.load`. For a booking-calendar suite that runs the same month-switch scenario on Chrome and Firefox, that difference is decisive: BiDi gives one subscription that both browsers honour, while the vendor bridge leaves the Firefox half of the matrix with no equivalent and forces a second code path. The tradeoff is surface area, since the vendor protocol still exposes more than the spec has standardised.

code

java · 18 lines
java
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;

public final class BookingCalendarBiDiOptions {

    public static Capabilities chrome() {
        ChromeOptions options = new ChromeOptions();
        options.setCapability("webSocketUrl", true);
        return options;
    }

    public static Capabilities firefox() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        return options;
    }
}

go deeper

for a junior

Recall that Selenium 4 has two ways to receive pushed browser events, and that only WebDriver BiDi is a W3C standard the different browsers implement. Naming the other one as Chromium-only is enough at this stage.

for a middle

Explain the mechanics: the capability that negotiates the socket, the fixed module and event catalogue the specification defines, and why version-pinned vendor bindings drift when a browser auto-updates.

for a senior

Show production judgement. Talk about a browser matrix where one branch of the capture code is dead, about a green pipeline broken by an overnight browser upgrade, and about verifying the channel exists rather than assuming it.

for a principal

Own the migration strategy: which captures move first, how vendor-only needs stay isolated behind a removable helper, what the team accepts as reduced surface area, and how you decide the vendor path is finally deletable.

## Two channels attached to one session Classic **WebDriver** is a request/response contract: the client sends an HTTP request such as `POST /session/{id}/url`, and the remote end answers. Nothing arrives that the client did not ask for. **WebDriver BiDi** adds a second channel to the *same* session — a WebSocket, opened after the new-session call — over which the browser may send messages the client never requested. In Selenium 4 both are live at once; BiDi does not replace the HTTP endpoints behind `driver.get(...)` or `findElement(...)`. Before BiDi existed, the only way to get pushed browser events out of Selenium was the **Chrome DevTools Protocol** bridge, a browser-vendor debugging protocol that Selenium wrapped for Chromium-based browsers. BiDi is a **W3C specification** developed beside the WebDriver spec, and it is where Selenium's own effort now goes. ## What actually differs | | Chromium DevTools bridge | WebDriver BiDi | |---|---|---| | Who defines it | a single browser vendor | the **W3C**, beside the WebDriver spec | | Browser reach | Chromium-based browsers only | implemented across browser engines, Firefox included | | How it is opened | a Selenium-specific bridge on a Chromium driver | the `webSocketUrl` capability in the new-session request | | Stability of the client surface | Selenium ships version-pinned bindings that chase browser majors | one module and event catalogue fixed by the specification | | Breadth | a large vendor debugging surface | the modules the spec defines: `session`, `browsingContext`, `network`, `log`, `script`, `input`, `storage`, `browser` | ## Why the browser matrix decides it Take a hotel room-booking calendar exercised on both Chrome and Firefox. The scenario is the same on each: open the calendar, page from September to October, assert that the newly fetched nightly rates render. To record what the page fetched during that month switch, or to see a console error the date grid throws while re-rendering, you need pushed events. - With the vendor bridge, the capture works in the Chrome run and is **dead code** in the Firefox run. The suite grows a browser conditional, and the two branches drift. - With BiDi, the client requests `webSocketUrl`, subscribes once to `network.beforeRequestSent` and `log.entryAdded`, and both browsers deliver the same event shapes. - Event names and payload members come from the specification rather than from whatever the vendor's protocol happens to call them this release, so the parsing code has one shape. ## The version-pinning tax The vendor bridge's bindings are tied to the browser's major version, and browsers auto-update. That produces a familiar operational pattern: 1. The pipeline is green; the browser image updates overnight. 2. The bridge's pinned bindings no longer match the browser's major version and fall back or fail. 3. The failure surfaces as a broken capture — not a broken booking-calendar assertion — so triage starts in the wrong place. 4. The fix is a Selenium upgrade, on the browser's release cadence rather than yours. BiDi removes that coupling. The event names you subscribe to are defined by the spec, so a browser upgrade does not silently change the identifier your code names. ## What you give up, and how to phase the move Being honest about the cost matters in an interview answer: - The standardised surface is **narrower** than the vendor protocol. Some vendor-only capabilities have no BiDi equivalent yet. - Per-browser BiDi implementation completeness differs and moves release to release, so verify on the browsers you actually run rather than assuming parity. - A remote end that does not implement BiDi simply returns no `webSocketUrl` string, so the client must handle the absent-channel case rather than assuming the socket is there. A workable sequence is to move the events that exist in both — logs, navigation, request and response records — onto BiDi first, keep any vendor-only need isolated behind a single Chromium-only helper, and delete that helper when the spec covers it. ## How the channel is switched on BiDi is negotiated, not bolted on afterwards. The client puts `webSocketUrl` in the capabilities of the new-session request; if the remote end supports it, the capabilities it returns contain `webSocketUrl` as a `ws://` URL. The client connects there and issues `session.subscribe` before any event is delivered. Because the address comes back in the response, an intermediary in front of the browser can hand back an address pointing at itself, which is how a socket survives not being on the client's machine. The short version for an interviewer: **the vendor bridge is one browser family and a moving target; BiDi is the standard channel, negotiated through a capability, with a stable catalogue.**

  • The booking-calendar suite needs something the BiDi specification has not standardised yet. How do you handle it?
    Keep it isolated. Put the vendor-only need behind one small Chromium-only helper with a clear name, guard it so the Firefox run skips it instead of failing, and treat it as debt with a removal trigger: delete the helper when the equivalent BiDi module lands. What you must not do is let the vendor protocol become the suite's default capture path again, because that re-couples every run to one browser family.
  • Your Chrome run gets BiDi events and the Firefox run silently gets none. Where do you look first?
    At the capabilities the new-session response returned for the Firefox session. If `webSocketUrl` came back as a string, the channel exists and the problem is the subscription or the event names; if the capability is absent, the remote end did not honour the request and there is no socket to connect to. That check separates a negotiation failure from a subscription bug in one step, before anyone reads calendar assertions.
  • Does moving to BiDi change how your test navigates and clicks in the booking calendar?
    No. BiDi is an additional channel on the same session, not a replacement protocol. Navigation, element lookup and clicks still travel over the classic WebDriver HTTP endpoints, and the socket carries pushed events beside them. That is why enabling BiDi is a capability change plus new subscription code, rather than a rewrite of the page interactions.

saying these in an interview costs you the question

  • Claiming BiDi replaces the classic WebDriver HTTP endpoints entirely
  • Treating the Chromium DevTools bridge as a cross-browser standard
  • Assuming every browser exposes a BiDi socket automatically
  • Believing BiDi covers everything the vendor protocol exposes
  • Thinking the socket opens without any capability being requested