Resource library

QA Interview

Selenium BiDi Coding Interview Questions in Python (2026)

Practice selenium bidi coding interview questions python candidates face, with runnable request, failure, authentication, cleanup, and CI examples.

25 min read | 3,960 words

TL;DR

Strong candidates can enable Selenium BiDi in Python, intercept a narrow request, continue or fail it safely, handle authentication, and clean up session state. They also know that BiDi is standards-oriented, CDP is Chromium-specific, and network evidence should be paired with a user-visible assertion.

Key Takeaways

  • Enable BiDi before driver creation and verify the returned WebSocket capability.
  • Register request handlers before the action that produces traffic.
  • Resolve every intercepted request exactly once by continuing or failing it.
  • Match exact hosts and paths instead of counting all browser traffic.
  • Remove handlers in teardown and isolate driver state per parallel test.
  • Separate transport failures from HTTP error responses in test design.
  • Explain protocol trade-offs as clearly as you write the callback code.

Selenium bidi coding interview questions python candidates receive in 2026 test more than API recall. Interviewers want to see whether you can open a BiDi-capable session, subscribe before traffic starts, resolve intercepted requests, synchronize without sleeps, protect secrets, and explain what the browser-level evidence proves.

This interview hub contains 50 distinct questions, runnable Python examples, and model answers sized for a live technical round. The examples use Selenium's public high-level network API rather than invented response helpers. For a longer implementation walkthrough, read the Selenium BiDi network Python guide, then use QA interview practice to rehearse the explanations aloud.

TL;DR

Topic Interview-ready point Python surface
Session setup Request BiDi before driver creation options.enable_bidi = True
Request interception Install the callback before navigation or click driver.network.add_request_handler
Resolution Every intercepted request must finish exactly once continue_request() or fail_request()
Authentication Browser auth is not a DOM login form add_auth_handler
Synchronization Wait for specific evidence, never a fixed delay WebDriverWait plus a predicate
Cleanup Handler state belongs to one session and scenario remove_request_handler or clear_request_handlers
Portability BiDi targets interoperable browser automation Verify each browser and Grid image

1. Selenium BiDi Coding Interview Questions Python Fundamentals

Q: What is WebDriver BiDi, and why does Selenium need it?

WebDriver BiDi is a bidirectional browser automation protocol that lets the remote end publish events while a session is running. Classic WebDriver mainly sends a command and receives its result, which is awkward for asynchronous network, log, and browsing-context activity. Selenium uses the BiDi connection to expose live features such as request interception and console events. Normal clicks, locators, and navigation still use WebDriver commands, so BiDi extends the session rather than replacing it.

Q: How is WebDriver BiDi different from Chrome DevTools Protocol?

CDP is Chromium's debugging protocol and follows Chromium-specific domains and versions. WebDriver BiDi is a W3C-oriented automation protocol intended for interoperable browser implementations. A Selenium framework should prefer a public high-level BiDi feature when it satisfies the requirement, especially when portability matters. CDP can remain a deliberate escape hatch for Chromium-only capabilities, but a candidate should label that dependency accurately.

Q: What capability proves that a session can carry BiDi events?

The returned capabilities should include a webSocketUrl when BiDi was requested and supported. Checking that value early turns an obscure callback timeout into a clear environment failure. The option must be set before driver construction because capabilities are negotiated during session creation. On Grid, inspect the returned session capabilities rather than assuming the node honored the request.

Q: Is BiDi automatically enabled for every Selenium Python driver?

No. Set enable_bidi on the browser options passed into the driver constructor. Creating the driver first and setting an attribute later cannot renegotiate the session. Support also depends on the Selenium client, remote end, browser, and driver combination. A small smoke test should run on every claimed browser image.

Q: When is browser network interception the wrong test layer?

Use a direct API test when the question concerns only status codes, schemas, or service business rules. BiDi is valuable when a real browser action must be connected to emitted traffic or when the UI must react to a browser-level failure. Browser interception does not prove that a mocked payload remains compatible with the real provider. Contract and integration tests cover that separate risk.

2. Session Setup and First Runnable Program

Q: Write the smallest Python program that enables BiDi and verifies the session.

Create browser options, enable BiDi before driver creation, and assert the returned capability. Always quit in finally so a failed assertion does not leak a browser. This program is runnable with a current Selenium 4 release and locally installed Chrome.

from selenium import webdriver

options = webdriver.ChromeOptions()
options.enable_bidi = True

driver = webdriver.Chrome(options=options)
try:
    assert driver.capabilities.get("webSocketUrl")
    driver.get("https://www.selenium.dev/")
    assert "Selenium" in driver.title
finally:
    driver.quit()

Verify it with python bidi_smoke.py. A successful run exits with code 0; a missing WebSocket capability raises AssertionError before the network questions begin.

Q: What packages would you pin for an interview exercise?

Pin Selenium to the version used by the exercise and use a supported Python release. Selenium Manager normally resolves a compatible local browser driver, so manually downloading a binary is not the first step. A minimal requirements file can contain selenium==4.46.0 and pytest>=8.0. The exact project lock matters more than claiming that any floating future version will behave identically.

Q: Why wrap driver creation and teardown carefully?

A browser process consumes memory and may retain a live WebSocket connection. If setup partially succeeds and the test then raises, unconditional cleanup prevents stranded sessions in local runs and CI. Framework fixtures should own the lifecycle because individual tests frequently forget exceptional paths. Teardown must not hide the original test failure, so cleanup code should stay small.

Q: How would you fail fast on an unsupported Grid node?

After session creation, assert webSocketUrl and include the browser name, version, and Grid node image in the failure message. Run a known public-page request callback as a capability smoke test before executing a BiDi-heavy suite. Do not wait thirty seconds for every scenario to discover the same missing feature. Route unsupported nodes away from that test group through Grid configuration or CI labels.

Q: Can the same setup be used for Firefox?

Use the Firefox options class and request BiDi during session creation, but verify the exact high-level feature against the supported matrix. A shared client method does not guarantee identical event coverage in every browser release. Keep the test intent portable and isolate browser-specific workarounds. Report a real support gap instead of silently skipping the assertion inside the callback.

3. Request Capture and Precise Filtering

Q: Code a handler that captures Selenium documentation requests without blocking navigation.

The handler records matching URLs and continues every intercepted request in a finally block. Registration occurs before navigation, and a bounded wait replaces a fixed sleep. Cleanup uses the returned handler ID.

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

options = webdriver.ChromeOptions()
options.enable_bidi = True
driver = webdriver.Chrome(options=options)
seen: list[str] = []

def capture(request) -> None:
    try:
        if request.url and "selenium.dev" in request.url:
            seen.append(request.url)
    finally:
        request.continue_request()

handler_id = driver.network.add_request_handler("before_request", capture)
try:
    driver.get("https://www.selenium.dev/")
    WebDriverWait(driver, 10).until(lambda _: bool(seen))
    assert any(url.startswith("https://www.selenium.dev/") for url in seen)
finally:
    driver.network.remove_request_handler("before_request", handler_id)
    driver.quit()

Run python capture_requests.py; code 0 verifies subscription, observation, continuation, waiting, and cleanup.

Q: Why must an observation callback still call continue_request()?

A high-level request handler creates an interception point, so matching traffic pauses for a decision. Merely appending a URL does not release the request. Every callback branch must continue or fail it exactly once. A missing decision often appears as a navigation timeout, which can mislead someone into debugging page readiness instead of the handler.

Q: Why is an exact host and path safer than a substring?

A substring such as api can match analytics, third-party scripts, or another endpoint with a similar name. Parsing the URL lets the test compare netloc and path as separate contracts. This prevents an unrelated request from satisfying the wait or receiving a mutation. Query parameters can then be checked independently when they are part of the business requirement.

Q: Should a test assert the total number of page requests?

Usually not. Fonts, analytics, feature flags, retries, and browser behavior can change the total without changing the feature. Collect only the target endpoint and assert its required properties. An exact count is appropriate only when call cardinality itself is the product contract, such as proving that a debounced save issued one request.

Q: What optional request fields require defensive code?

Fields such as headers, cookies, resource type, body size, and timing metadata can depend on the event and browser. Check for None before iterating or comparing them. Treat the URL and the chosen action as the most stable first contract. Prove cross-browser availability in the actual support matrix before making optional metadata a release gate.

4. Selenium BiDi Coding Interview Questions Python Interception

Q: How do you add a test-only request header?

Copy the existing headers, append a protocol-shaped value, and pass the complete collection to continue_request. Limit the change to a test-owned host and path because adding a custom header can trigger a CORS preflight. The server or a controlled echo endpoint should verify that the header arrived.

from urllib.parse import urlparse

def add_run_header(request) -> None:
    parsed = urlparse(request.url) if request.url else None
    if parsed and parsed.netloc == "app.example.test" and parsed.path == "/api/cart":
        headers = list(request.headers or [])
        headers.append({
            "name": "x-test-run",
            "value": {"type": "string", "value": "cart-smoke"},
        })
        request.continue_request(headers=headers)
    else:
        request.continue_request()

The verification is an assertion in the controlled service log or echo response for x-test-run: cart-smoke, not merely proof that the callback executed.

Q: What is wrong with replacing every request header collection globally?

It can remove cookies, content negotiation, cache validators, authorization, and browser-generated headers needed by unrelated resources. It may also send an internal marker to third-party hosts. Preserve existing values and mutate the narrowest endpoint possible. If the intent is to test missing authorization, remove that one header explicitly and document the security scenario.

Q: Can continue_request change more than headers?

The high-level request object can accept supported overrides such as method, URL, body, cookies, and headers. Each change alters semantics, so it needs its own targeted assertion. Changing GET to POST, for example, affects routing, caching, and possibly CORS. An interview answer should not list options without explaining their behavioral cost.

Q: How do you prevent an intercepted page from hanging when callback logic raises?

Keep diagnostic work inside try and release an observational request from finally. For a mutation callback, validate replacement data before registration or catch the error, record it, and continue the original request. Surface the recorded callback error on the test thread so the test fails clearly. Never call both continue_request and fail_request during error recovery.

Q: What makes a network mutation assertion meaningful?

Assert the downstream behavior owned by the mutation. For a routing header, prove the controlled backend received it and the UI rendered a unique fixture value from that route. A list showing that the callback ran proves only test code execution. Pair protocol evidence with a visible or service-side result to avoid false positives.

5. Failure Injection and Recovery Coding

Q: Write a callback that fails only the recommendations endpoint.

Branch on the exact target, fail that request, and continue everything else. Save evidence for diagnostics but assert the application's recovery state separately. The callback resolves every path once.

from urllib.parse import urlparse

failed: list[str] = []

def fail_recommendations(request) -> None:
    parsed = urlparse(request.url) if request.url else None
    if parsed and parsed.path == "/api/recommendations":
        failed.append(request.url)
        request.fail_request()
    else:
        request.continue_request()

Register it before the click that loads recommendations. Verify with a bounded wait for the UI alert and assert failed, then remove the handler before testing Retry.

Q: What is the difference between fail_request() and an HTTP 500?

fail_request() creates a transport-level failure, so browser fetch code generally rejects the promise. An HTTP 500 is a completed exchange whose response status must be inspected by application code. Error handling often has separate branches for those conditions. Mature resilience tests cover both, but the public high-level Python API should not be credited with a synthetic-response helper unless the pinned version actually exposes one.

Q: How would you test a retry button?

Install the failure handler, trigger the request, and assert that a useful error plus Retry control appears. Remove the failure handler, click Retry, and wait for the success content. Optionally add a narrow observer for the successful second call. This sequence proves both recovery messaging and actual retry behavior rather than only the first injected fault.

Q: Why should failure injection target a stable endpoint?

A broad rule can break documents, styles, or telemetry before the application reaches the state under test. Exact targeting makes the resulting UI failure attributable to one dependency. It also keeps the page usable enough to display recovery controls. If several hosts serve the same path, compare both host and path.

Q: Should you use time.sleep() after failing a request?

No. Sleep is simultaneously too long on fast machines and too short on overloaded CI nodes. Wait for an observable alert, retry control, state change, or captured event with a timeout. Include the expected endpoint and a sanitized sample of seen URLs in a timeout message. That evidence makes a synchronization failure diagnosable.

6. Authentication and Security Questions

Q: Code a browser authentication handler with guaranteed cleanup.

Use the network authentication API for browser Basic or Digest challenges, not for an HTML login form. Read real credentials from environment or CI secrets. This public demonstration endpoint accepts sample values.

from selenium import webdriver

options = webdriver.ChromeOptions()
options.enable_bidi = True
driver = webdriver.Chrome(options=options)
auth_id = driver.network.add_auth_handler("admin", "admin")
try:
    driver.get("https://the-internet.herokuapp.com/basic_auth")
    assert "Congratulations" in driver.page_source
finally:
    driver.network.remove_auth_handler(auth_id)
    driver.quit()

Run python basic_auth.py; a zero exit code verifies that the browser challenge was handled. Production credentials must never appear in source, logs, screenshots, or exception text.

Q: Why is browser authentication different from a login page?

Basic and Digest prompts belong to browser network handling rather than the page DOM. A product login form is HTML and should be automated with locators, input actions, and visible assertions. Using an auth handler for a DOM form misunderstands both layers. Conversely, Selenium cannot locate elements inside a native browser prompt.

Q: What sensitive data can network diagnostics expose?

URLs may contain tokens or personal identifiers, while headers and cookies can hold credentials and session state. Bodies can contain customer data. Collect only fields required by the assertion and redact before attaching artifacts. Default CI logging should never dump full request objects.

Q: Why remove an authentication handler immediately after the scenario?

The handler is session state and can answer later challenges unexpectedly. A subsequent test might pass with credentials it never configured, creating order dependence and hiding an authorization defect. Function-scoped fixtures reduce that risk. Explicit removal also documents the intended authentication window.

Q: How would you test invalid browser credentials?

Register deliberately invalid disposable credentials against a controlled environment, navigate, and assert the expected rejection behavior. Limit retries so the test cannot lock a real account. Confirm that failure artifacts redact the credential values. Clean up the handler even when navigation throws or the browser repeats the challenge.

7. Pytest Fixtures, Cleanup, and Parallelism

Q: Write a pytest fixture that guarantees handler cleanup.

The fixture owns driver creation and clears handlers before quitting. Tests still own their narrow callbacks and evidence. Function scope provides fresh session state for parallel workers.

import pytest
from selenium import webdriver

@pytest.fixture
def bidi_driver():
    options = webdriver.ChromeOptions()
    options.enable_bidi = True
    driver = webdriver.Chrome(options=options)
    assert driver.capabilities.get("webSocketUrl")
    try:
        yield driver
    finally:
        driver.network.clear_request_handlers()
        driver.quit()

def test_homepage_uses_bidi(bidi_driver):
    bidi_driver.get("https://www.selenium.dev/")
    assert "Selenium" in bidi_driver.title

Verify with pytest -q test_bidi.py; one passing test and no leftover browser process confirm the basic lifecycle.

Q: Why avoid a session-scoped driver for network tests?

Handlers, authentication decisions, cookies, and browsing contexts accumulate within a session. Sharing them makes tests depend on order and complicates parallel execution. Function scope costs more startup time but gives a strong isolation boundary. If performance forces reuse, implement explicit state reset and prove it with randomized ordering.

Q: Is appending to a Python list always enough for callback synchronization?

A small CPython example often uses list append successfully, but framework utilities should state their concurrency assumptions. Compound read-modify-write operations need a lock or thread-safe queue. The test thread should use a bounded wait rather than spin continuously. Each driver session must have its own collector.

Q: How do you remove one handler without disturbing another test concern?

Save the ID returned by add_request_handler and pass it with the same event name to remove_request_handler. This is preferable when an observer must remain active after a failure injector is removed. clear_request_handlers is appropriate during fixture teardown when the fixture owns all handlers. Ownership determines which cleanup operation is safe.

Q: What should happen if teardown itself fails?

Preserve the primary test failure and report cleanup as secondary diagnostics. Keep removal and quit defensive, but do not silently swallow repeated infrastructure defects. A framework can log browser identity and session information without secrets. CI should detect leaked processes or exhausted Grid slots as infrastructure failures.

8. Synchronization, Grid, and Debugging

Q: A handler never fires on Grid. What do you inspect first?

Confirm that BiDi was enabled before session creation and that returned capabilities contain webSocketUrl. Verify that registration preceded navigation, then run a minimal known-URL callback on the same node image. Record Selenium client, Grid, browser, and driver versions. Only after those checks should you investigate application routing or service workers.

Q: How do you make a callback timeout actionable?

Report the expected host and path, browser identity, BiDi capability status, and a small sanitized sample of observed URLs. State whether the triggering UI action completed. Avoid printing authorization headers or bodies. The message should distinguish no events, wrong endpoint, and correct event with missing UI behavior.

Q: Can service workers affect network interception?

Yes. A service worker may satisfy traffic through a path that differs from an ordinary page request, depending on browser behavior and application architecture. Test the exact browser and deployed worker configuration. Do not generalize one local result to every engine. When interception ownership is essential, include service-worker behavior in the test design and diagnostics.

Q: How should parallel tests label captured traffic?

Use a unique, non-secret correlation value per test and restrict it to test-owned endpoints. Store artifacts under that test's result directory. Never share a driver, handler collection, or mutable global list across workers. Correlation is useful only if the backend and logs preserve it safely.

Q: What is a good Grid smoke gate for BiDi?

Create a session, assert the WebSocket capability, register a narrow callback, visit a stable page, wait for one known request, remove the handler, and quit. Run that gate once per browser image before the larger suite. Its failure should quarantine the incompatible node or stop the BiDi job. This saves many identical downstream timeouts.

9. Architecture and Scenario-Based Questions

Q: Where should BiDi code live in a test framework?

Put session setup and cleanup in a fixture or driver factory. Keep endpoint-specific interception near the scenario or in a small helper whose name describes the test intent. Do not hide every request behind a global recorder. A thin adapter reduces upgrade impact without creating a second undocumented protocol abstraction.

Q: How do you prevent a network mock from drifting from the backend?

Validate shared fixtures against an API schema or consumer contract in CI. Retain integrated journeys against the real service. Use unique fixture values so the UI assertion proves which data source was consumed. Browser interception and contract testing complement each other because they answer different questions.

Q: When would you choose an external proxy instead of BiDi?

Choose a proxy when full HTTP capture, certificate control, or response manipulation exceeds the supported high-level binding and the operational cost is justified. A proxy adds TLS trust, routing, and deployment complexity. BiDi is simpler when the required behavior is already exposed in the browser automation session. A direct API client remains better for service-only assertions.

Q: How would you migrate a CDP-based Selenium network helper?

Inventory the actual behaviors, such as request observation, header mutation, or failure injection. Replace each with a public BiDi feature only after a representative browser-matrix spike passes. Keep unsupported CDP behavior isolated and label it Chromium-specific rather than forcing a fake portable abstraction. The Selenium DevTools Python guide helps identify legacy CDP boundaries.

Q: How do you decide whether a network assertion belongs in a page object?

A page object may expose the user action and stable UI result, but protocol expectations often belong to the test or a dedicated observability helper. Embedding listeners invisibly in every page method creates hidden session state. Keep network intent explicit at the scenario level. Centralize only stable endpoint names and lifecycle mechanics.

10. Advanced Selenium BiDi Coding Interview Questions Python Trade-offs

Q: Why should callbacks stay small?

They execute on Selenium's event-processing path, so blocking I/O or heavy parsing can delay traffic and other events. Capture minimal sanitized evidence, resolve the request, and perform expensive analysis on the test thread. Small callbacks also reduce the chance that an exception strands an intercept. Their single responsibility should be obvious during code review.

Q: How do you test request cardinality without flakiness?

Define the product condition that makes the count meaningful, such as one save request after rapid edits. Filter to an exact endpoint and correlation value, wait until the UI reaches a settled state, then assert the count. Account for documented retries separately rather than treating them as random noise. Do not include assets or unrelated background polling.

Q: What would you review before upgrading Selenium?

Compile and run a focused BiDi compatibility suite against the pinned browser images. Check option negotiation, handler signatures, typed header values, removal methods, authentication behavior, and Grid transport. Read public release notes for changes to high-level features. A lockfile update should not merge on a normal UI smoke test alone.

Q: What evidence proves a failed request affected the user journey?

The test should show the targeted request was failed and that the UI displayed the intended fallback, retained usable controls, and offered recovery where required. Removing the handler and succeeding on retry provides stronger evidence. A callback list by itself says nothing about customer behavior. A screenshot without protocol evidence may capture an unrelated error.

Q: How would you explain Selenium BiDi versus Playwright interception?

Selenium BiDi aligns with the WebDriver ecosystem and a standards-oriented protocol, while Playwright provides runner-native routing with concise fulfillment and response-patching workflows. Existing framework investment, required browsers, mock density, and API maturity should drive the choice. The Selenium BiDi versus Playwright network comparison provides a scenario matrix. Migrating a healthy suite for syntax alone is rarely justified.

11. How Interviewers Grade Your Answers

Interviewers first score correctness: you enable BiDi before session creation, subscribe before the trigger, and resolve every intercepted request. They then look for determinism, including exact URL matching, bounded waits, unique evidence, and cleanup. A solution that prints all traffic and sleeps for five seconds may demonstrate the event stream, but it is not production-quality test design.

They also grade judgment. Strong answers separate transport failure from HTTP failure, browser auth from DOM login, BiDi from CDP, and UI validation from API contract validation. Security awareness matters when requests can expose tokens and personal data. Senior candidates connect callback code to Grid support, parallel isolation, failure diagnostics, upgrade control, and a clear reason for choosing the browser layer.

Use Selenium interview questions for experienced testers to broaden framework topics, and review Python API automation framework design for complementary service-layer choices. You can also compare your experience to a target SDET role in Resume Studio.

12. Common Mistakes

  • Enabling BiDi after constructing the driver, when capability negotiation is already complete.
  • Registering a handler after navigation or the click that emitted the target request.
  • Recording an intercepted request without continuing or failing it.
  • Resolving one request twice by calling continue_request() after fail_request().
  • Matching broad substrings and accidentally changing third-party or static traffic.
  • Asserting total request counts when background traffic is not a product contract.
  • Using time.sleep() instead of waiting for exact network or UI evidence.
  • Treating transport failure as equivalent to an HTTP 500 response.
  • Logging complete headers, cookies, query strings, or bodies in CI artifacts.
  • Sharing a driver or mutable evidence collection across parallel tests.
  • Leaving request or authentication handlers active for later scenarios.
  • Assuming every request field and feature behaves identically across browsers.
  • Claiming an unsupported Python response-body or fulfillment convenience API exists.
  • Proving only that the callback ran while ignoring visible application behavior.
  • Using browser interception as a substitute for provider contract testing.

Conclusion

The best answers to selenium bidi coding interview questions python teams ask combine executable Selenium code with protocol judgment. Enable the channel during session creation, install narrow handlers before the trigger, resolve every intercepted request, use bounded synchronization, protect secrets, and clean up state.

Practice each example as a two-part response: write the callback, then explain what it proves and what it does not. That pattern shows the interviewer you can build reliable browser tests rather than merely recall method names.

Interview Questions and Answers

What is WebDriver BiDi?

WebDriver BiDi adds a bidirectional event channel to browser automation. The browser can publish asynchronous activity such as network events while the session runs. Selenium layers public high-level features over that protocol while ordinary interactions still use WebDriver commands.

How do you enable BiDi in Selenium Python?

Set enable_bidi to True on the browser options before driver construction. Pass those options into the driver, then verify that returned capabilities contain webSocketUrl. Capability negotiation cannot be repaired after the session exists.

Why must a request handler call continue_request?

The handler intercepts and pauses matching traffic. Continuing releases an observational or unchanged request, while failing deliberately creates transport failure. Leaving a branch unresolved can stall navigation until timeout.

How do you make a BiDi network assertion deterministic?

Register before the trigger, match an exact host and path, and wait for specific evidence with a bounded timeout. Avoid global traffic counts and fixed sleeps. Pair network evidence with the visible feature outcome.

What is the difference between fail_request and an HTTP 500?

fail_request models transport failure and usually causes browser fetch code to reject. HTTP 500 is a completed response whose status application code must inspect. They exercise different error branches and should be tested separately.

How would you test a retry flow?

Fail only the target request and assert that the retry UI appears. Remove the failure handler, trigger Retry, and wait for a successful visible state. A narrow observer can confirm that the second request occurred.

How do you protect secrets in network diagnostics?

Collect only fields needed by the assertion and redact URLs, headers, cookies, and bodies before persistence. Read test credentials from a secret store and never print complete request objects by default. Isolate sanitized artifacts by test.

How do you avoid handler leakage between pytest tests?

Use a function-scoped driver fixture, retain handler IDs, and remove handlers when their behavior window closes. During fixture teardown, clear fixture-owned handlers and quit the driver. Do not share mutable callback collections across workers.

How would you debug BiDi on Selenium Grid?

Confirm enablement before session creation and inspect the returned WebSocket capability. Run a minimal known-URL callback on the same node, then record client, Grid, browser, and driver versions. Verify that handler registration preceded the triggering action.

When should you choose an API test instead of BiDi?

Choose an API test for service-only status, schema, and business-rule risks. Use BiDi when the real browser action or UI reaction to network behavior matters. Maintain contract coverage because intercepted browser fixtures can drift.

Frequently Asked Questions

How do I enable Selenium BiDi in Python?

Set options.enable_bidi = True before creating the driver, then pass those options to the constructor. Verify that the returned capabilities include webSocketUrl so unsupported environments fail early.

Why does a Selenium BiDi request handler make my page hang?

A request handler pauses intercepted traffic. Every callback path must call continue_request(), fail_request(), or another resolution supported by the pinned API exactly once.

Is WebDriver BiDi the same as Chrome DevTools Protocol?

No. CDP is Chromium's debugging protocol, while WebDriver BiDi is a standards-oriented browser automation protocol intended for interoperable implementations. Selenium may expose both, but their portability and versioning differ.

Can Selenium BiDi modify request headers in Python?

Yes. Preserve the existing headers, append the protocol-shaped value, and pass the collection to request.continue_request(headers=...). Restrict mutation to an exact test-owned host and path.

How do I test network failure with Selenium BiDi?

Register a before_request handler and call request.fail_request() only for the target endpoint. Continue all other traffic, then assert the visible error and recovery behavior.

How should Selenium BiDi handlers be cleaned up?

Save the returned handler ID and remove it with the same event name when its scenario ends. A fixture that owns all request handlers can call clear_request_handlers during teardown before quitting the driver.

Does Selenium BiDi replace API contract testing?

No. BiDi proves browser traffic or UI behavior under controlled network conditions. Schema, contract, and integration tests prove compatibility with the real service.

Related Guides