Vibium vs Selenium 4 (WebDriver BiDi)
Vibium vs Selenium 4 WebDriver BiDi compared — protocol depth, drivers, AI/MCP, and DX. An honest look at when to choose each in 2026.
Vibium and Selenium 4 both speak WebDriver BiDi, but at very different depths. Selenium 4 keeps its two-decade-old classic WebDriver core — HTTP + JSON, a separate driver binary — and layers a BiDi module on top for real-time events like network interception and console logs. Vibium is BiDi-native: WebDriver BiDi over WebSocket is its primary protocol, it ships as a single Go binary that auto-downloads Chrome, needs no chromedriver, and bundles an MCP server so AI agents can drive the browser with zero glue. Both were touched by the same mind — Jason Huggins co-created Selenium, then built Vibium. Choose Selenium 4 when you need Grid, Java/C#/Ruby bindings, or a proven enterprise suite. Choose Vibium when you want a lean, BiDi-first, AI-native setup with no driver to manage. Here is the honest, technical breakdown.
Vibium
Selenium 4 BiDi
What is WebDriver BiDi, and why does it matter here?
WebDriver BiDi is a W3C standard that adds bidirectional, WebSocket-based communication to browser automation. Classic WebDriver (the 2018 W3C standard) is one-way and HTTP-based: the client sends a request, the browser answers. That works for clicks and navigation, but it cannot push events — you have to poll for console logs, network activity, or DOM changes.
BiDi fixes that. Like the Chrome DevTools Protocol, it lets the browser stream events to the client in real time. Unlike CDP, it is a cross-browser W3C standard with buy-in from Chrome, Firefox, and Edge, rather than a Chrome-internal protocol. If you want the deeper history, see the Vibium glossary and what is Vibium.
The key distinction for this comparison: BiDi can be your whole protocol, or just an add-on module. Vibium takes the first path; Selenium 4 takes the second.
To make the mechanics concrete, a single BiDi message is just JSON over a WebSocket. A navigate command looks like this:
{ "id": 1, "method": "browsingContext.navigate", "params": { "url": "https://example.com" } }The browser replies with a matching id, and — crucially — it can also push unsolicited event messages (a log.entryAdded for a console error, a network.responseCompleted for a finished request) without the client asking. That push capability is exactly what classic HTTP WebDriver lacks and what both tools tap into for real-time features. The difference is whether that WebSocket is the main road (Vibium) or a service lane beside the HTTP highway (Selenium 4).
How does Selenium 4 use WebDriver BiDi?
Selenium 4 adds BiDi as an enhancement on top of its existing WebDriver architecture, not as a replacement. Your everyday commands — driver.get(), find_element(), click(), send_keys() — still travel over classic HTTP WebDriver to a driver binary. The BiDi WebSocket connection runs alongside that session and powers the newer real-time features.
That layered design is deliberate. It means every existing Selenium 4 script keeps working while you opt into BiDi where it helps. The BiDi-powered capabilities in Selenium 4 include:
- Network interception — stub responses, capture requests, and read response bodies.
- Console and log listeners — subscribe to
console.logoutput and JavaScript exceptions as they happen. - DOM mutation and auth handlers — react to page changes and basic-auth prompts.
Coverage and API shape differ across the Java, JavaScript, Python, and .NET bindings, and the surface is still expanding release to release. So "Selenium 4 supports BiDi" is true, but it means "Selenium 4 exposes selected BiDi features," not "Selenium 4 runs entirely on BiDi."
How is Vibium's BiDi approach different?
Vibium treats WebDriver BiDi as the primary protocol, not an add-on. Every command — navigation, finding elements, clicking, screenshots — is issued over the same BiDi WebSocket connection to the browser. There is no classic-WebDriver HTTP layer underneath and no driver binary in the path.
Concretely, that removes moving parts. A Selenium 4 setup involves your client library, a driver binary (chromedriver), and the browser; Selenium Manager now auto-resolves the driver, but it is still a component that must version-match the browser. Vibium collapses this into a single Go binary that connects straight to a Chrome it auto-downloads on first run.
Because it is BiDi-first, real-time features are not a separate subsystem in Vibium — they are the same channel everything else uses. That is also what makes the built-in MCP server natural: an AI agent and a find().click() call are talking to the browser the same way.
| Vibium | Selenium 4 (BiDi) | |
|---|---|---|
| BiDi role | Primary protocol | Add-on module over classic WebDriver |
| Everyday commands (click, find, go) | Over BiDi WebSocket | Over classic HTTP WebDriver |
| Driver binary | None | chromedriver / geckodriver (auto-fetched) |
| Distribution | Single Go binary + auto Chrome | Client lib + driver + browser |
| Created by | Jason Huggins | Jason Huggins and community |
| Maturity | New (v1, Dec 2025) | Very mature, 20+ years |
| Languages | Python, JavaScript/TS | Java, C#, Python, Ruby, JS |
| AI agents / MCP | Built-in MCP server | None built in |
| Distributed grid | Not yet | Selenium Grid (proven) |
| Ecosystem | Emerging | Huge |
What does the code look like side by side?
The everyday API tells the story better than the protocol diagram. Here is a minimal open-navigate-screenshot script in each tool.
# Vibium — BiDi-native, no driver binary
from vibium import browser_sync as browser
vibe = browser.launch() # auto-downloads Chrome on first run
vibe.go("https://example.com")
open("out.png", "wb").write(vibe.screenshot())
vibe.quit()# Selenium 4 — classic WebDriver core (Selenium Manager fetches the driver)
from selenium import webdriver
driver = webdriver.Chrome() # driver binary in the path
driver.get("https://example.com")
driver.save_screenshot("out.png")
driver.quit()Vibium's JavaScript client mirrors the same shape. Note the page object and short verbs (go, find, text) — Vibium favors its own terse idiom over Playwright or Selenium naming:
// Vibium (JavaScript, sync)
const { browser } = require('vibium/sync')
const bro = browser.launch()
const page = bro.page()
page.go('https://example.com')
const link = page.find('a')
console.log(link.text())
link.click()
bro.close()For element finding, Vibium unifies CSS and semantic strategies into one find() method. Where Selenium uses find_element(By.CSS_SELECTOR, ...), Vibium takes a plain string or a structured object:
// CSS string (the 80% case)
page.find('#email')
// Semantic + combinable — one method, no chaining
page.find({ role: 'button', text: 'Sign In' })See the find-element command and the screenshot command for the full API.
Where BiDi events change the DX
The clearest practical gap between the two is real-time data. Reading network traffic or console logs shows how "BiDi-native" versus "BiDi-add-on" feels in day-to-day code.
In Selenium 4 this lives in a dedicated BiDi API you set up alongside the driver session — powerful, but a distinct subsystem with binding-specific syntax. In Vibium the same channel that runs your clicks also carries these events, exposed through discoverable on* methods:
// Vibium — same connection, event listeners
const { browser } = require('vibium')
const bro = await browser.launch()
const page = await bro.page()
page.onConsole((msg) => console.log('page log:', msg.text))
page.onResponse((res) => console.log(res.status(), res.url()))
await page.go('https://example.com')
await bro.close()Network interception — stubbing a response so a test never hits the real backend — is a first-class BiDi feature in both tools. It is one of the biggest wins BiDi brought to Selenium 4, and it is native in Vibium via page.route(). This is the category where BiDi genuinely leaves classic WebDriver behind.
How does waiting and flakiness compare?
Flaky tests usually trace back to timing, and the two tools handle waiting differently. Classic Selenium exposes explicit waits (WebDriverWait with expected conditions) and an implicit wait applied globally to every find_element. You choose and tune those waits per project, and getting them wrong is a common source of intermittent failures.
Vibium builds waiting into actions. Its find() and interaction commands auto-wait for actionability — an element must be attached, visible, stable, and able to receive events before a click() or fill() proceeds. You do not sprinkle explicit waits before each action; the engine holds until the element is ready or the timeout elapses.
// Vibium — no explicit wait needed; click waits for actionability
const button = page.find({ role: 'button', text: 'Submit' })
button.click()# Selenium 4 — explicit wait is the idiomatic way to avoid flakiness
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type=submit]")))
button.click()Neither model is objectively correct. Selenium's explicit waits give you fine-grained control and are well understood by large teams. Vibium's auto-waiting removes boilerplate and a whole class of "element not interactable" errors, at the cost of some explicitness. If your Selenium suite leans heavily on custom expected conditions, budget time to rethink them during a migration.
Vibium's AI-native layer: the real differentiator
The protocol comparison is close on paper; the AI layer is where Vibium diverges hardest. Vibium ships a built-in MCP (Model Context Protocol) server, so tools like Claude Code or Gemini CLI can drive a real browser without any bridge code. Selenium 4 has no built-in MCP server — you would wire up an external integration yourself.
Vibium also exposes AI-native commands that have no Selenium equivalent. page.check() runs a plain-English assertion against the live page, and page.do() performs a natural-language action by planning real find/click/fill calls under the hood:
// Plain-English verification — no selectors
await page.check('the shopping cart shows 0 items')
// Natural-language action, executed via Vibium's own deterministic API
await page.do('close the cookie consent banner')These sit on top of the deterministic API rather than replacing it — you still write el.text() when you know exactly what you want. To connect it to an agent, see set up Vibium MCP in Claude Code.
What about setup and CI footprint?
Setup effort is where a BiDi-native, single-binary design pays off most visibly. Selenium 4 improved this a lot: Selenium Manager now discovers and downloads the correct driver automatically, so the old ritual of manually version-matching chromedriver to your Chrome build is largely gone. You still install a client library for your language, and a driver process still sits between the client and the browser at runtime.
Vibium reduces the moving parts to one. pip install vibium or npm install vibium pulls a single Go binary; on first launch() it downloads a compatible Chrome for Testing and connects to it over BiDi directly. There is no separate driver to install, launch, or keep on your PATH.
In continuous integration this difference compounds. A Selenium job typically provisions a browser, ensures a matching driver is available, and may stand up a Grid node for parallelism. A Vibium job installs the package and runs — Chrome and the connection are handled for you. For simple pipelines that is meaningfully less YAML and fewer version-drift failures. For complex, highly parallel or cross-browser matrices, Selenium Grid still gives you orchestration that Vibium does not yet match.
| Concern | Vibium | Selenium 4 (BiDi) |
|---|---|---|
| Install | pip/npm — one binary | Client lib + Selenium Manager |
| Driver management | None | Auto-resolved by Selenium Manager |
| Browser provisioning | Auto-downloads Chrome | You provide the browser |
| Parallelism at scale | Contexts per browser process | Selenium Grid |
| Setup surface | Minimal | Moderate |
Cross-browser reality in 2026
Cross-browser breadth is currently Selenium's advantage, and it is worth being precise about why. Because Selenium 4 keeps classic WebDriver underneath, it drives every browser that ships a compliant driver — Chrome, Firefox, Edge, and Safari — with mature, battle-tested support across all of them. That coverage is a decade-plus in the making.
Vibium's reach is bounded by BiDi support in the browsers themselves. WebDriver BiDi is fully shipping in Chromium and Firefox, with Safari support still maturing, and Vibium is Chromium-focused today. As browser vendors complete their BiDi implementations, a BiDi-native tool inherits that breadth "for free" without reverse-engineering per-browser protocols — but that is a forward-looking benefit, not today's state.
So if your requirement is "run this suite on Safari and Firefox in production right now," Selenium 4 is the answer. If you are automating Chromium and care more about DX and AI integration, Vibium's narrower footprint is rarely a blocker.
Pros and cons, honestly
Neither tool is strictly better. Here is a fair accounting for teams weighing the switch.
Vibium strengths
- BiDi-native protocol with no classic-WebDriver HTTP layer or driver binary.
- Single Go binary that auto-downloads Chrome — trivial setup and CI footprint.
- Built-in MCP server plus
check()/do()for agentic and AI-assisted automation. - One unified
find()for CSS and semantic locators, with auto-waiting (actionability).
Vibium limitations
- New (v1 shipped December 2025) with a small, emerging ecosystem.
- Only Python and JavaScript/TypeScript clients today — no Java, C#, or Ruby yet.
- No distributed grid equivalent to Selenium Grid.
- Chromium-focused as broader BiDi browser support matures.
Selenium 4 strengths
- Two decades of maturity, integrations, and community knowledge.
- Bindings for Java, C#, Python, Ruby, and JavaScript.
- Selenium Grid for distributed and cross-browser execution at scale.
- BiDi already adds modern real-time events (network, console, DOM) to a stable core.
Selenium 4 limitations
- BiDi is layered on classic WebDriver, so everyday commands still use HTTP.
- A driver binary remains in the stack (even if Selenium Manager fetches it).
- No built-in AI/MCP layer or plain-English assertions.
- More moving parts to configure than a single-binary tool.
When to choose each
Choose Selenium 4 (with BiDi) when:
- You need Java, C#, or Ruby bindings today.
- You rely on Selenium Grid or distributed/remote execution.
- You have a large, established suite and want to adopt BiDi's real-time features incrementally without a rewrite.
- Cross-browser breadth on a battle-tested foundation is a hard requirement.
Choose Vibium when:
- You are building AI agents that browse the web — the built-in MCP server means zero integration work.
- You want a BiDi-first, single-binary setup with no driver binaries to manage.
- You are starting a new, lean project and value modern DX like unified
find()and auto-waiting. - You want plain-English
check()/do()alongside deterministic commands.
Is migration from Selenium hard?
Vibium's documented migration design is a Selenium compatibility layer that acts as a bridge. You swap the import and keep most existing scripts running — no chromedriver binary needed:
# Before
from selenium import webdriver
driver = webdriver.Chrome()
# After — routed through Vibium's BiDi engine
from vibium.compat.selenium import webdriver
driver = webdriver.Chrome()The compat layer maps the common Selenium surface (get, find_element, click, send_keys, quit) onto Vibium's native API. It is a migration bridge, not a 100% bug-for-bug clone — edge cases around implicit waits and stale-element references can differ, so expect to fix a few timing-sensitive tests. For new code, prefer Vibium's native bro/page API and structure it with a page object model. A full walkthrough lives in migrate from Selenium to Vibium.
The verdict
Selenium 4 with BiDi is the pragmatic, enterprise-safe choice: it modernizes a proven 20-year-old core with real-time events while preserving every existing script, grid, and language binding. If you depend on Java, C#, Ruby, or distributed testing, it remains the right answer in 2026.
Vibium is the cleaner expression of where BiDi points: a BiDi-native, single-binary tool with no driver and an AI layer built in. It is young and Python/JS-only, but for agentic automation and greenfield projects it is a genuinely fresh foundation — fitting, since it comes from the person who started Selenium in the first place. Many teams will keep Selenium 4 for their legacy suite and reach for Vibium when they wire a browser up to an AI agent.
Next steps
Frequently asked questions
What is the difference between Vibium and Selenium 4 WebDriver BiDi?
Selenium 4 adds a BiDi module on top of its classic WebDriver core, so it still ships with a driver binary and uses HTTP for most commands. Vibium is BiDi-native — WebDriver BiDi over WebSocket is its primary protocol, it needs no driver binary, and it bundles an MCP server for AI agents.
Does Selenium 4 fully support WebDriver BiDi?
Selenium 4 exposes a growing BiDi API for events like network, console logs, and DOM mutations, but classic commands (navigate, click, find) still travel over HTTP WebDriver. BiDi in Selenium 4 augments the classic protocol rather than replacing it, and coverage varies by language binding.
Is Vibium a replacement for Selenium 4?
For AI-agent automation and lean new projects, Vibium can replace Selenium 4. It is BiDi-first, needs no chromedriver, and ships a built-in MCP server. Selenium 4 remains the safer choice for Grid-based distributed testing and Java, C#, or Ruby suites.
Do I still need chromedriver with Selenium 4 BiDi?
Yes. Selenium 4's BiDi features run through the same session a driver binary manages, so chromedriver or geckodriver is still required — though Selenium Manager now downloads it automatically. Vibium removes the driver entirely by speaking BiDi directly to a Chrome it auto-downloads.
Which is faster, Vibium or Selenium 4?
For event-driven work — capturing console logs, network traffic, or DOM changes — BiDi-native tools avoid HTTP round-trips per command, which can feel snappier. Selenium 4 mixes HTTP WebDriver with BiDi events, so latency depends on the operation. Benchmark your own flows before deciding.
Did the same person create Vibium and Selenium?
Yes. Jason Huggins co-created Selenium in 2004 and later Appium, then built Vibium as an AI-native rethink of browser automation. Selenium 4 is maintained by a large open-source community; Vibium is a newer single-binary project he describes as what he would build starting over today.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
The Best Cypress Alternatives in 2026
The best Cypress alternatives in 2026 — Vibium, Playwright, Selenium, and Puppeteer compared on run model, languages, AI/MCP support, and use cases.
13 min read→ComparisonsVibium vs Chrome DevTools Protocol (CDP)
Vibium vs Chrome DevTools Protocol (CDP): a high-level, AI-native tool built on WebDriver BiDi versus Chrome's raw low-level automation protocol.
14 min read→ComparisonsVibium vs Katalon Studio: 2026 Comparison
Vibium vs Katalon Studio compared for 2026 — code-first BiDi automation with a built-in MCP server vs a low-code all-in-one testing IDE.
10 min read→ComparisonsVibium vs mabl: AI Testing Compared
Vibium vs mabl compared: an open-source AI-native code library vs a low-code AI testing SaaS platform. An honest 2026 guide to choosing.
14 min read→