Back to Knowledge Hub
Comparison

WebDriver vs CDP: What Each Connection Can Do

Choose WebDriver, BiDi, or CDP for a browser task by checking the operation, client support, and limits of the actual connection.

BotBrowser Team

WebDriver vs CDP: What Each Connection Can Do
Documentation

Want the structured docs for Documentation?

This article lives in the editorial library. For step-by-step setup, reference material, and ongoing updates, jump into the docs section.

WebDriver vs CDP becomes a concrete decision when a test needs a specific command or event. BotBrowser supports documented automation integrations, but it does not add missing client operations or decide which connection your suite requires.

WebDriver commands, BiDi events and CDP domains require checking the browser, driver and client.

TL;DR

WebDriver, WebDriver BiDi, and Chrome DevTools Protocol (CDP) are different protocol contracts, not three names for one browser feature. Choose by the operation you need, then verify that your browser, driver, library, and connection mode support it. Selenium can expose classic WebDriver, BiDi, and CDP integrations; a library name alone does not identify the active protocol.

Contents

A library is not a protocol

The phrase “WebDriver vs CDP” sounds like a binary choice, but it compresses several decisions into two labels. WebDriver is a W3C standard for controlling a user agent through a remote end. WebDriver BiDi is a separate W3C protocol for bidirectional commands and events. CDP is Chromium's DevTools protocol, with browser and JavaScript domains. A language library is yet another layer: it may expose one protocol, several protocols, or a framework-specific connection on top of one of them.

The practical question is not “which protocol can see more?” It is “which supported connection exposes the operation this test needs, with the behavior and portability it requires?” A test that clicks a button and waits for a heading may need only standard WebDriver commands. A test that records network lifecycle events may need BiDi or a browser-specific CDP path. Neither fact makes one choice universally superior.

Selenium documents its classic WebDriver API, its WebDriver BiDi APIs, and CDP examples. Its CDP support page calls that support temporary until WebDriver BiDi is implemented. Playwright offers its native browser protocol connection and a separate Chromium CDP connection, which its documentation describes as lower fidelity. These examples show why “I use Selenium” or “I use Playwright” is not enough information to choose a protocol. Teams that need event setup and subscription details can continue with the WebDriver BiDi event workflow; teams considering a framework change should use the separate Selenium migration inventory.

Capability map

The table describes protocol-level shapes, not a guarantee that every browser or client implements every operation. “Can express” means the protocol defines a command or event family; check the chosen implementation and version before relying on it.

TaskClassic WebDriverWebDriver BiDiCDPWhat to verify
Find elements, click, type, navigateStandard command model for element and browsing-context operationsBrowsing-context commands are defined, but client support variesPage and DOM domains offer Chromium-specific controlsLocator semantics, browsing context, and command availability in the selected client
Read console outputNot the core classic request/response workflowThe log module defines event reportingRuntime and Log domains expose console-related eventsWhich event is enabled, how context IDs are mapped, and whether arguments are retained
Observe network activityNot a universal classic WebDriver event streamThe network module defines request and response eventsNetwork.enable enables tracking and network eventsEvent coverage, request-body policy, redaction, and support in this driver/browser pair
Evaluate page JavaScriptScript execution is part of WebDriver's command modelScript commands target realms and browsing contextsRuntime.evaluate evaluates an expression on a global objectExecution realm, permissions, CSP behavior, and whether the client returns values by value
Set user-agent or device metricsCapabilities and browser-specific options may configure a session, but are not a universal live overrideNo general promise that every browser-specific override existsCDP includes Network.setUserAgentOverride and a device-metrics override in its emulation domainBrowser-specific behavior, metadata coherence, and differences that remain outside the override
Change a browser permissionMay be exposed through a browser-specific capability or library APIPermission behavior depends on the defined command support and implementationCDP has Browser.setPermission, marked experimental in the protocol definitionExact permission name, origin scope, context, and experimental status

This is a map of places to investigate, not a scorecard. Classic WebDriver's strength is a standardized control surface intended to work across implementations. BiDi adds a specified bidirectional event model. CDP exposes Chromium-oriented domains that can be useful for debugging and browser controls, but those methods do not become cross-browser guarantees because a wrapper makes them convenient to call.

Protocol specifications also have different levels of stability. A named command can be experimental, optional, unsupported in a particular browser, or exposed differently by an older driver. Even a successful session handshake says only that a session was created; it does not prove that every later command or event is implemented. In the table, the permission example is deliberately labeled experimental, while CDP network tracking requires enabling the domain before expecting events.

Choose by the operation

Start with an operation inventory rather than a protocol preference. Write down the evidence the test needs, not just the API method the current library happens to provide.

“We need more visibility” is too vague to select a connection. Name the missing record: a console entry, a response status, a permission state, a viewport dimension, or a user-visible assertion. Then write the smallest condition that would prove the test received it. This avoids adopting a lower-level protocol just because its domain list looks longer. A large surface area is useful only when the needed command exists in the actual runtime and its output answers the test's question.

NeedFirst path to evaluateQualification
Portable navigation and element interactionClassic WebDriver or a framework's documented native connectionConfirm the supported browsers and the exact command semantics
Subscribe to browser events while commands continueWebDriver BiDiConfirm the event module, subscription scope, and driver implementation
Inspect Chromium network details or use a Chromium-only emulation commandCDPPin Chromium and the client; treat the operation as Chromium-specific
Move an existing Selenium suite without changing its frameworkKeep WebDriver first; add BiDi or CDP only for a named gapA protocol change can affect event timing, support, and debugging artifacts even if the test language stays fixed
Run the same suite across browser enginesPrefer standardized paths where they satisfy the needA Chromium CDP endpoint does not establish Firefox or WebKit equivalence

For a concrete example, consider a test that must assert a confirmation page and preserve the failed request's status. The user-visible assertion belongs to the page workflow. Network evidence can help diagnose why it failed, but an observed response is not proof that the application rendered success. A BiDi or CDP event should therefore supplement the semantic page assertion, not replace it. If only Chromium is in scope, CDP may provide an operation that the selected driver does not expose through BiDi yet; record that dependency instead of describing the suite as protocol-neutral.

The same separation applies to JavaScript evaluation. WebDriver has script execution commands, BiDi defines script realms and evaluation operations, and CDP provides Runtime.evaluate. Those entry points do not imply identical realm selection, serialization, lifecycle, or error behavior. If an assertion depends on a page global, specify which browsing context or realm owns that global and inspect how the client returns the value.

For script results, record whether the code runs in the top-level document, a child frame, or an isolated execution world. A successful expression in the wrong frame can produce a plausible but irrelevant value. Also distinguish a thrown page exception from a transport failure and from a serialization problem in the client. The same JavaScript text can behave differently when a page navigates between command dispatch and result delivery. The test should bind the result to a context or realm identifier when that protocol exposes one, and should fail clearly if that context disappears.

Avoid treating “can set” as “can make equivalent.” A device-metrics override can change selected viewport and screen values, but does not recreate a physical device's graphics path, installed fonts, input hardware, or every media capability. A user-agent override changes a header or related browser value according to the command, but it does not automatically align all client hints or every document surface. State the measured surface and the remaining differences.

An operation matrix should also record its portability cost. If the test runs on Chromium only, a CDP dependency can be an explicit and reasonable tradeoff. If the same assertion must run on multiple browser engines, ask whether a standard WebDriver or BiDi operation is sufficient before adopting a Chromium-specific method. Do not duplicate a test under two protocols unless the duplicated observation can catch a real regression; otherwise the suite gains maintenance without gaining evidence.

When an operation has no equivalent path in another browser, mark that cell as unsupported or unverified rather than silently changing what the test means. A fallback can be valid if it observes the same user outcome, but it is not automatically equivalent because it returns a similarly named field. For example, a console event and a visible error banner are different evidence. Record the outcome, the collection method, and any fallback rule together so a later reader can tell what was actually established.

Verify the connection you actually run

Before adding a protocol-specific operation to a test suite, record four facts: browser and version, driver or remote endpoint, client library and version, and the connection method. “Selenium with Chrome” is not enough. “Selenium 4, pinned Chrome build, local ChromeDriver, BiDi WebSocket enabled for network.responseCompleted” is a testable description. If the connection is CDP, record that explicitly, including whether the library created the browser or attached to an existing endpoint.

Keep this record near the test configuration rather than only in a runbook. A package update can change the endpoint or protocol defaults while the test source remains unchanged. In CI, print the effective browser version and selected connection mode at session creation. If a remote service supplies the browser, record its advertised capabilities and the requested options that it accepted. A configured option is not evidence that a remote end honored it; the session result or a direct observation must confirm the effective behavior.

Use a small support check before the full workflow:

  1. Create a fresh session using the exact CI launch path.
  2. Issue the smallest command or event subscription required by the test.
  3. Record the negotiated capabilities, returned command result, and any unsupported-operation error.
  4. Trigger one owned fixture request or console message and verify the expected event and context identifier.
  5. Close the session and confirm that listeners, browser processes, and fixture state are cleaned up.

Do not infer support from a protocol page alone. The protocol definition answers whether a method or event exists in that published schema. The browser, driver, remote service, and client determine whether the method is available in your run. Pin a protocol schema or release reference when repeatability matters; the CDP “tot” viewer and the repository's master JSON are moving targets.

A useful record keeps command output separate from the claim it supports:

browser=Chrome <pinned version>
client=Selenium <pinned version>
connection=WebDriver BiDi
operation=subscribe to network.responseCompleted
result=subscription acknowledged; one fixture response observed
scope=owned local fixture, one browsing context
not established=all browsers support this event identically

Replace placeholders with the actual environment before treating this as evidence. If the subscription fails, that is a support result for that stack, not proof that BiDi as a whole lacks the feature. If the event arrives but the page assertion fails, keep those outcomes separate. A protocol trace can explain a test; it does not decide whether the product workflow succeeded.

Repeat the check after changing one component at a time. First hold the browser constant and change the client or driver. Then restore the original client and change the browser version. This isolates which part of the stack changed support. If a managed browser endpoint is involved, changing the service at the same time makes attribution harder: the browser build, network hop, session owner and protocol bridge may all differ. A small change log is more valuable than a broad “works on my machine” note.

For event-based tests, keep event capture narrow. Subscribe only to the event type and browsing context needed by the case, cap retained records, and remove listeners during teardown. Network and console records can contain URLs, headers, page text, or user data. The choice of protocol does not supply a retention policy. Redact sensitive values before saving artifacts and keep enough metadata to correlate the event with the test step without storing unrelated traffic.

For a command-based test, record the request identifier or command name, the response category, and the page state that follows. A command acknowledgment means the remote end accepted a command; it does not necessarily mean the page reached its intended state. Wait for a semantic completion condition, such as a confirmation region becoming visible, and retain protocol details as diagnostic context. If the test times out, distinguish a missing protocol response from a missing page result.

The browser core remains below both

Protocols expose operations and observations; they do not define every value produced by the browser engine. A script evaluation can read a DOM value, while a network event can report a request. A rendering result may still depend on fonts, graphics backend, browser build, operating system, and profile. Likewise, setting one emulated value does not change all related surfaces. The protocol layer and the browser core answer different questions.

BotBrowser documents browser values and automation integrations, but it does not translate WebDriver commands into CDP, implement a missing BiDi event in a client, or certify parity across protocol modes. The automation consistency reference describes the browser-side boundary; it is not a protocol conformance matrix. The browser target can be held constant while a team evaluates a supported connection; the team must still verify its own exact client and operation. This boundary is useful when a behavior differs: first classify whether the difference comes from the requested command, protocol support, client mapping, or the browser environment.

Do not turn a protocol comparison into an identity verdict. Observing a value through JavaScript or changing it through a browser command does not establish what another system will infer from a whole session. It also does not establish that the same command is available in another engine. Keep conclusions limited to the recorded browser, connection, operation, and fixture.

The protocol is only one part of a browser test's environment. The automation client may add defaults, the driver may translate calls, a remote endpoint may mediate the session, and the browser core produces the document and rendering values. When a page reports an unexpected value, use those boundaries to localize the question: did the test issue the intended operation; did the endpoint accept it; did the client expose the result correctly; and did the browser produce the expected page state? This sequence does not assume that one layer is at fault. It prevents a protocol label from standing in for evidence.

The same caution applies to comparisons. If two protocol paths return the same DOM value, that only shows equality for that value in that run. It does not establish that their event ordering, error handling, timing, or unsupported operations match. If a project needs equivalence, list the required operations and compare each relevant result under controlled conditions. If it only needs a reliable test, choose the narrowest supported path and assert the user outcome.

Frequently asked questions

Is CDP the same thing as WebDriver?

No. CDP is Chromium's DevTools protocol. WebDriver is a W3C browser-control standard, and WebDriver BiDi is a separate bidirectional protocol specification. Libraries can expose more than one path, so inspect the connection mode rather than guessing from the package name.

Does Selenium only use WebDriver?

No. Selenium's main control API is WebDriver, and Selenium also documents BiDi and CDP integrations. Its documentation describes CDP support as temporary while BiDi implementation continues. Availability still depends on Selenium, browser, and driver versions.

Is CDP a better choice for every task?

That conclusion is too broad. CDP has Chromium-specific domains and commands that can be valuable for a particular test, while WebDriver and BiDi provide standardized contracts. The relevant comparison is whether the exact operation is supported in the pinned stack and whether its portability tradeoff is acceptable.

Does a device emulation command make headless Chrome equivalent to a phone?

No. A command can override specified metrics or values. It does not recreate every physical sensor, font, GPU, codec, input device, or operating-system behavior. Describe the emulated fields and the unmodeled environment separately.

Can I rely on an operation listed in the protocol schema?

Not without checking the implementation. A schema is evidence that the protocol defines a method, not that a particular browser, driver, remote service, or client version implements it. Run a bounded support check in the same connection mode used by CI.

Sources

Practical conclusion

Choose a connection from the operation backward: name the command or event, confirm the browser/client/driver support, record the version and connection mode, and preserve a semantic assertion for the user-visible result. Use WebDriver for the standardized interactions it already covers, BiDi when its event contract is supported, and CDP when a Chromium-specific operation justifies that dependency. Keep the protocol, library, and browser environment as separate rows in the test record; none is a substitute for verifying the others.

#WebDriver#Chrome DevTools Protocol#WebDriver BiDi#Browser Automation

Run the same check in BotBrowser

Load a profile, keep the signals you just read about consistent inside the browser, and confirm the result on your own machine before a rollout.