skip to content

Why can't classic WebDriver's HTTP contract in Selenium report a console error at the moment it happens?

level: juniorimportance: should knowfreq 51%

answer

  1. Ask who is allowed to speak first
  2. The browser never gets a turn
  3. Polling narrows the window, never closes it
  4. Shape of the protocol, not its speed
  5. A subscribed socket beside the same session

basics

~10 s

Classic WebDriver is client-initiated request and response: the remote end only answers, never speaks first. A browser event can only be asked for afterwards, which is why Selenium 4 adds the BiDi socket.

solid answer

~50 s

Under the classic WebDriver contract every exchange starts with the client. The test sends an HTTP request, the remote end answers it, and the exchange ends; there is no way for the browser to originate a message. So anything that happens *in* the browser — a console error thrown while a hotel booking calendar re-renders its date grid, a request the page fired on its own — can only be discovered by the client asking afterwards, and only if the browser still holds a record of it. That gives you no timing, no ordering against your own steps, and nothing at all for anything transient. **WebDriver BiDi** in Selenium 4 fixes the shape rather than the polling interval: the `webSocketUrl` capability opens a socket alongside the same session, and after `session.subscribe` the browser pushes `log.entryAdded` and `network.beforeRequestSent` as they occur.

go deeper

for a junior

Be ready to state the direction rule: under classic WebDriver only the client starts an exchange, so the browser cannot report anything on its own. Naming the BiDi socket as what changes that is enough here.

for a middle

Explain why polling is not an answer, what is lost when a record is only available in retrospect, and how the socket, the subscribe step and the classic commands coexist on one session.

for a senior

Demonstrate the diagnostic instinct: distinguish an event that was never pushed from one that was pushed and not read, and recognise a subscription registered after the observed action as the cause of an empty capture.

for a principal

Own the framing for the team: which observations genuinely require a pushed channel, what a standing subscription costs on every run, and where retrospective questioning is still the simpler and cheaper answer.

## Who is allowed to speak first Classic **WebDriver** is a request/response protocol over HTTP. The local end — your test — sends a request such as `POST /session/{id}/element`, the remote end answers it, and the exchange is over. The important property is not the speed of that round trip but its **direction**: every exchange is started by the client. The remote end has no way to originate a message, because there is no exchange for it to originate one in. That is fine for driving a page. "Click this", "read this text", "go to this URL" are all things the client wants to do at a moment it chooses. It is the wrong shape for anything the *browser* decides to do. ## What that costs on a real page Consider a hotel room-booking calendar. A tester pages from September to October; the page fetches that month's nightly rates on its own, re-renders the date grid, and something in the render writes an error to the console. None of that was requested by the test. Under the classic contract: - The client can only find out by **asking afterwards**, and only if the browser still holds a record of what happened. - The record arrives without a useful relationship to the test's own steps, so "did the error happen before or after the next-month click?" is not answerable from it. - Anything the browser does not retain is simply gone. A request that was fired and failed leaves nothing to ask for once the moment has passed. - Asking more often does not fix it. Polling narrows the window and multiplies round trips; it never turns the browser into something that can speak first. ## The two shapes side by side | | Classic WebDriver over HTTP | WebDriver BiDi socket | |---|---|---| | Who starts an exchange | the client, always | either end, at any time | | How the client learns of a browser event | by asking after the fact | the browser pushes it | | Timing relative to the event | whenever the client next asks | as it happens | | Transient events | may be lost before anyone asks | delivered when subscribed | | Cost of watching closely | more round trips | one subscription | ## Why polling is not the same answer It is worth being precise about this, because "just poll faster" is the first thing most candidates reach for. A poll is still a client-initiated round trip that reports whatever the browser is holding at that instant. Shortening the interval: 1. Reduces, but never removes, the window in which something can happen and be discarded. 2. Adds traffic to a session that is simultaneously being driven by the test's own commands, so the two compete. 3. Still yields no event ordering — you learn that something exists, not when it happened relative to your click. 4. Costs more the closer you try to get, which is the opposite of how a subscription behaves. The limit is structural. No interval turns a protocol in which only one side may speak into one in which both may. ## What Selenium 4 changes BiDi does not make the HTTP contract faster; it adds a **second channel with a different shape**. The sequence is short: 1. Request the `webSocketUrl` capability when the session is created. 2. Read the `ws://` address back from the capabilities the response returned, and connect to it. 3. Send `session.subscribe`, naming the events you want — `log.entryAdded` for console and script records, `network.beforeRequestSent` for outgoing requests, `browsingContext.load` for navigation milestones. 4. Drive the calendar over the ordinary HTTP commands while the socket delivers pushed frames. Both channels belong to the same session and run at the same time. Your clicks and waits do not move; what moves is how the browser's own activity reaches you. ## Two things this does not mean - **It is not a replacement.** Classic WebDriver commands are still the right shape for client-initiated work, and Selenium 4 still sends them over HTTP. - **It is not automatic.** Opening the socket delivers nothing on its own; the remote end pushes only what a subscription has named, and only from the moment that subscription is registered. Events from before it are not replayed. ## The line to say in an interview The honest phrasing is that this is a **protocol-shape limit, not a performance limit**. HTTP request/response gives the browser no turn to speak, so a console error can only ever be reported in retrospect. WebDriver BiDi in Selenium 4 gives the browser a turn — that is the whole point of the second channel.

  • If the client polled the browser every 50 milliseconds, would that be equivalent to BiDi?
    No. Polling changes the window, not the shape. Each poll is still a client-initiated round trip that reports whatever the browser happens to be holding at that instant, so anything the browser did not retain is lost between polls, and nothing carries the event's own timing. It also multiplies traffic against a session that is meanwhile being driven, which makes the test slower and the ordering harder to reason about, not easier.
  • Does adding the BiDi channel change how your booking-calendar test clicks and waits?
    No. BiDi is a second channel on the same session. Navigation, element lookup, clicks and waits still travel over the classic WebDriver HTTP endpoints exactly as before. What is added is code that connects to the socket, subscribes to events and reads pushed frames while the test runs. The two channels operate concurrently and neither replaces the other.

Classic WebDriver is a hotel phone line where only the guest may dial: to learn that a room freed up you have to keep calling the front desk. BiDi is leaving the line open so the desk can call you the moment it happens.

saying these in an interview costs you the question

  • Calling this a speed problem rather than a protocol shape
  • Believing frequent polling is equivalent to a pushed event
  • Saying the remote end can open a connection back to the client
  • Assuming BiDi replaces the classic HTTP commands
  • Expecting pushed events without any subscription