VLearnVibium

Inside Vibium's Single Go Binary Architecture

Vibium ships as one ~10MB Go binary bundling browser management, a WebDriver BiDi proxy, auto-wait, and an MCP server. Here's the architecture.

By Pramod Dutta··5 min read·Verified with Vibium 26.2
▶ Animated overview · made with Remotion

Vibium ships as a single ~10MB Go binary — internally called the Clicker — that does everything: it detects and launches Chrome with WebDriver BiDi enabled, runs a WebSocket proxy that routes commands to the browser, performs server-side auto-wait (actionability) checks, captures screenshots, and serves a built-in MCP server over stdio for AI agents. The thin Python and JavaScript clients are deliberately dumb: they send a command and wait for success or an error. All the hard logic lives in the Go binary, so every client behaves identically. Created by Jason Huggins (co-creator of Selenium and Appium), Vibium leans on this design to be invisible — you pip install vibium or npm install vibium, the right binary ships with the package, Chrome for Testing auto-downloads on first run, and it just works with no separate driver to manage.

What lives inside the Vibium binary?

The single binary bundles five responsibilities that older tools split across multiple processes. Each one is a job a typical automation stack would hand to chromedriver, a client library, or a separate MCP package.

ComponentWhat it doesHow you reach it
Browser managementDetects and launches Chrome with BiDi enabledAutomatic on launch
BiDi proxyWebSocket server that routes commands to the browserWebSocket (e.g. :9515)
Auto-waitPolls for element actionability before actingBuilt into every action
ScreenshotsViewport capture as PNG bytesvibe.screenshot()
MCP serverstdio interface for AI agentsvibium mcp

The design goal is that the binary is invisible. Developers never invoke it directly — the client package does, behind the scenes.

How do the client and binary talk?

The client library is a thin layer over the binary, which is itself a proxy in front of the browser. There are two hops, and both are local.

┌──────────────┐        ┌─────────────────────┐        ┌──────────┐
│ Python / JS  │  cmd   │  Vibium Go binary   │  BiDi  │  Chrome  │
│   client     │───────▶│  (proxy + auto-wait)│───────▶│ (BiDi on)│
└──────────────┘        └─────────────────────┘        └──────────┘

When you call a method, the client serializes a command and sends it to the binary's WebSocket proxy. The binary translates it into one or more raw WebDriver BiDi messages, runs any required waiting, and returns a single success or error. Here is what that looks like from Python, using the verified sync API:

from vibium import browser_sync as browser
 
vibe = browser.launch()
vibe.go("https://example.com")
 
el = vibe.find("a")
print(el.text())
el.click()
 
vibe.quit()

Every one of those calls — go, find, text, click, quit — is just a command sent to the Go binary. The client does no DOM work and no timing logic of its own.

Why put auto-wait in the binary instead of the client?

Vibium runs its actionability (auto-wait) logic server-side, in Go, so it is written once and shared by every client. Before any action, the binary polls until the element is visible, stable, receiving events, and enabled — up to a default 30-second timeout — instead of asking the client to retry.

This has four concrete payoffs:

  • Single implementation. The waiting logic is written once in Go, not duplicated across Python, JavaScript, and future clients.
  • Lower latency. Polling happens over the local proxy-to-browser WebSocket, not a client → proxy → browser round trip on every poll.
  • Simpler clients. A client just sends a command and waits for a result; no retry loops to maintain.
  • Consistent behavior. Every language client gets identical timing, so a flaky test in Python behaves the same in JS.

This is why your scripts don't need sleeps or manual retries — the binary blocks until the element is genuinely ready. (See how actionability works for the full check list.)

How does install ship the right binary?

Each platform package carries its own prebuilt binary, so installation needs no compiler and no Go toolchain. The Python and JS packages are platform-aware wrappers around per-platform binary packages (darwin-arm64, darwin-x64, linux-arm64, linux-x64, win32-x64).

# Python
pip install vibium
 
# JavaScript / TypeScript
npm install vibium

On first run, the binary downloads a matching build of Chrome for Testing, so there is nothing else to configure. You can also pre-fetch Chrome:

vibium install

Because the binary is self-contained, the same executable also powers the built-in MCP server — there is no separate package to install for AI-agent control. You just point your agent at vibium mcp.

Where does the MCP server fit in?

The MCP server is not a bolt-on; it is one of the binary's five built-in roles, exposed over stdio. Because browser management, BiDi proxying, and auto-wait already live in the same process, the MCP interface gets all of that for free. An AI agent like Claude connects to the binary, issues high-level browser actions, and benefits from the same actionability waiting that the Python and JS clients use.

That tight coupling is the architectural payoff: one binary, one implementation of the hard parts, and three front doors — Python, JavaScript, and MCP — all behaving the same way.

Key takeaways

The single-binary model is what makes Vibium feel frictionless. There is no driver to download, no version mismatch between a client and a driver, and no per-language reimplementation of waiting or finding. The binary owns the complexity; the clients stay thin.

Next steps

Frequently asked questions

What is Vibium's single Go binary?

Vibium ships as one small Go binary (around 10MB) called the Clicker. It launches Chrome with WebDriver BiDi enabled, runs a WebSocket proxy that routes commands to the browser, performs auto-wait actionability checks, and exposes a built-in MCP server — all in a single executable.

Why did Vibium choose a single binary architecture?

A single binary means zero external dependencies and no driver to manage. When you run pip install vibium or npm install vibium, the matching binary ships with the package, auto-downloads Chrome for Testing on first run, and just works. The thin Python and JS clients only send commands.

What does the Vibium binary actually do?

The binary handles browser management, acts as a WebDriver BiDi WebSocket proxy, runs server-side actionability auto-wait, captures screenshots, and serves an MCP interface over stdio for AI agents. Logic lives in Go so every client library gets identical behavior.

Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.

Related guides