WebDriver BiDi vs CDP is the choice now facing every team that automates browsers. Classic WebDriver offered a standardized command interface but limited real-time visibility. The Chrome DevTools Protocol (CDP) offered deep, event-driven control but tied advanced workflows closely to Chromium. WebDriver BiDi is a W3C standards-track specification designed to close that gap with a bidirectional protocol that browsers can implement consistently. This guide compares the two, shows minimal Selenium and Puppeteer sessions, and explains what the shift means for cross-browser network infrastructure.
The short version
CDP does not disappear. BiDi becomes the portable core, and CDP becomes a deliberate extension. Start separating portable automation logic from browser-specific diagnostics: use BiDi where portability is the value, keep CDP for Chrome-only capabilities such as tracing, and put the choice behind a capability adapter instead of scattering protocol calls through application code.
Key takeaways
- CDP is deep and mature but evolves with Chromium. Other browsers are not required to reproduce its protocol surface.
- WebDriver BiDi adds a persistent WebSocket channel to WebDriver, so the browser can push subscribed events instead of being polled.
- A protocol migration is a capability migration. Inventory every direct CDP dependency before changing anything.
- Keep protocol choice out of business logic. Tasks request capabilities, and an adapter picks the protocol and browser.
- The automation protocol controls the browser. It does not decide where the browser connects from. That stays a network-architecture decision.
- Treat BiDi support as a tested capability matrix, with browser and library versions pinned.
The practical conclusion is not that CDP disappears. It is that engineering teams can begin separating portable automation logic from browser-specific diagnostics. That matters for testing, data collection, synthetic monitoring, and AI agents that must observe browser events as they happen.
What CDP Actually Provides
Depth, with a portability costCDP is the protocol used by Chrome DevTools to communicate with Chromium-based browsers. Its domain-oriented API exposes the network stack, runtime, DOM, performance data, tracing, storage, emulation and many Chrome-specific capabilities. Tools such as Puppeteer built powerful automation layers on top of it. Our explainer on why modern web automation runs on Chromium covers that ecosystem in more detail.
That depth is CDP’s advantage and its portability problem. CDP evolves with Chromium. Another browser can implement similar features, but it is not required to reproduce Chrome’s protocol surface or release cadence.
What WebDriver BiDi Changes
From polling to subscribed eventsClassic WebDriver is primarily command and response: send an instruction, receive a result. BiDi adds a persistent WebSocket channel through which the browser can emit subscribed events. A client can receive the following without repeatedly polling the browser:
- console messages;
- navigation changes;
- script events;
- network activity;
- browsing-context updates.
WebDriver vs CDP vs WebDriver BiDi Compared
Three protocols side by side| Capability | Classic WebDriver | CDP | WebDriver BiDi |
|---|---|---|---|
| Control model | Command and response | Bidirectional events | Bidirectional events |
| Governance | W3C Recommendation | Chromium project | W3C Working Draft |
| Browser scope | Cross browser | Chromium centered | Cross browser goal |
| Network visibility | Historically limited | Deep and mature | Standardized and expanding |
| Vendor features | Limited | Extensive Chrome features | Portable core with extensions |
A Minimal BiDi Session in Selenium
Request a WebSocket URL at session creationSelenium enables BiDi by requesting a WebSocket URL as part of session creation.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.enable_bidi = True
driver = webdriver.Chrome(options=options)
print("BiDi endpoint:", driver.capabilities.get("webSocketUrl"))
driver.get("https://example.com")
print(driver.title)
driver.quit()
Pin your versions. The exact event APIs continue to evolve across Selenium bindings, so production code should pin Selenium and browser versions and test the capabilities it depends on.
If you route Selenium through a proxy, our guide to Selenium proxy setup with ChromeDriver and Python covers authentication.
One Puppeteer API, Two Protocols
Change the transport, keep the codePuppeteer supports Chrome and Firefox over WebDriver BiDi while retaining CDP for Chrome-specific workloads. That makes it useful for migration experiments, because the application can keep a familiar high-level API while the transport changes underneath.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
browser: "firefox",
protocol: "webDriverBiDi",
headless: true,
});
const page = await browser.newPage();
page.on("console", event => console.log(event.text()));
page.on("response", response => {
console.log(response.status(), response.url());
});
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
await browser.close();
For proxy configuration in Puppeteer itself, see how to use authenticated proxies in Puppeteer.
Do Not Migrate by Replacing a Protocol String
A protocol migration is a capability migrationInventory every direct CDP session, domain command, raw event and assumption about Chrome internals. Then classify each one:
The high-level methods that already work across protocols are the safest place to start. From there, the recommended path depends on the workload:
| Workload | Recommended path | Reason |
|---|---|---|
| Cross-browser navigation and extraction | BiDi-first | Portability is the primary value |
| Console and network event collection | Evaluate BiDi | Standard event model is increasingly capable |
| Chrome tracing or experimental domains | Keep CDP | The capability is intentionally browser-specific |
| Mixed fleet | Capability adapter | Select protocol per browser and task |
The Protocol Does Not Define the Network Identity
Control channel versus egress pathWebDriver BiDi defines a standards-track way for the controller to communicate bidirectionally with the browser. It does not decide where the browser connects from, how long an exit identity persists, or which geography the destination observes. Those remain network-architecture decisions.
ProxyEmpire belongs at this boundary. A worker can select a country, region, city or ISP profile and choose rotation or a sticky session according to the task. The browser protocol remains responsible for control and telemetry; the proxy route supplies the intended egress path.
const route = {
country: "DE",
locale: "de-DE",
timezone: "Europe/Berlin",
proxyServer: process.env.PROXYEMPIRE_SERVER,
proxyUser: process.env.PROXYEMPIRE_USER,
proxyPassword: process.env.PROXYEMPIRE_PASSWORD,
};
// Pass the route through the browser launcher supported by your stack.
// Keep credentials outside logs and source control.
Design a Capability Adapter
Tasks ask for capabilities, not protocolsKeep protocol choice out of business logic. A task should request capabilities such as network events, console capture, request interception or tracing. The adapter chooses the protocol and browser combination that can satisfy them.
type BrowserProtocol = "cdp" | "webDriverBiDi";
type Job = {
browser: "chrome" | "firefox";
needsChromeTracing: boolean;
};
function chooseProtocol(job: Job): BrowserProtocol {
if (job.needsChromeTracing) return "cdp";
return "webDriverBiDi";
}
function requireCapability(name: string, available: Set<string>) {
if (!available.has(name)) {
throw new Error(`Missing browser capability: ${name}`);
}
}
Observability for a Mixed Protocol Fleet
Know which protocol produced which resultWhen some workers run over BiDi and others over CDP, record enough context to compare them:
- Record browser name and version, automation library version, and selected protocol.
- Measure session creation failures separately from navigation failures.
- Tag network events with the intended ProxyEmpire route profile and session policy.
- Compare feature parity using task outcomes, not event counts alone.
- Retain a CDP fallback only for named capabilities with owners and tests.
For the scheduling and capacity side of a large fleet, see our guide to designing a browser cluster for 10,000 concurrent Chromium sessions.
Security and Operational Boundaries
A bidirectional control channel is privilegedTreat the BiDi WebSocket endpoint as privileged infrastructure:
- Protect the WebSocket endpoint and restrict network access to it.
- Isolate browser workers.
- Terminate sessions deterministically.
- Never expose remote-control endpoints to untrusted page content or public networks.
Keep proxy credentials out of artifacts. Inject them at runtime and exclude them from traces, screenshots, HAR files and exception messages.
Current Support and Production Readiness
A capability matrix, not a yes-or-no flagModern automation tooling already exposes WebDriver BiDi for Chrome/Chromium and Firefox workflows, but support is still capability-specific. Feature parity is not complete, and behavior can vary by browser and library version. Treat BiDi support as a tested capability matrix rather than a single yes-or-no browser flag.
For production systems:
- pin browser and automation-library versions;
- run compatibility tests for the events and commands you depend on;
- keep named CDP fallbacks only where a Chrome-specific capability is genuinely required.
Will WebDriver BiDi Replace CDP?
A portable core with deliberate extensionsFor portable browser automation, BiDi is becoming the more important abstraction. For Chrome-specific instrumentation, CDP remains valuable, and Puppeteer explicitly continues to support it. The likely architecture is not a sudden replacement but a portable BiDi core with deliberate CDP extensions.
Teams that model capabilities now will gain cross-browser flexibility without giving up advanced diagnostics. Teams that scatter raw protocol calls through application code will experience every protocol change as a rewrite.
Frequently Asked Questions
WebDriver BiDi vs CDP, in shortIs WebDriver BiDi production ready?
For workloads that use capabilities supported by your pinned browser and automation-library versions, it can be. The specification and implementations are still evolving, so production readiness should be established per capability with tests rather than assumed from protocol support alone.
Does Chrome support WebDriver BiDi?
Yes, modern Chrome/Chromium automation stacks expose BiDi support. CDP remains the deeper Chrome-specific interface for capabilities such as low-level tracing and experimental Chromium domains.
Will WebDriver BiDi replace CDP?
Not completely. BiDi is the stronger portability layer for cross-browser automation, while CDP remains useful when a workload intentionally depends on Chromium-specific instrumentation.
Is BiDi faster than CDP?
There is no universal performance winner that applies to every automation stack. Protocol choice should be driven first by required capabilities and portability. Benchmark representative workloads if transport overhead or event volume matters to your system.
Give every browser session the right egress path
Whichever protocol drives the browser, ProxyEmpire supplies the route: country, region, city or ISP targeting with rotating or sticky sessions.














