VLearnVibium

How to Run Vibium Headless on a Server

Run Vibium headless on a Linux server or CI — launch with headless=True, install Chrome's system libraries, and automate browsers with no display.

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

To run Vibium headless on a server, launch with browser.launch(headless=True) so Chrome runs without a visible window, and install Chrome's shared system libraries on the host once. Vibium ships as a single Go binary and auto-downloads its own Chrome for Testing on first run, so there is no driver to match and no system Chrome to manage — the only host setup is the handful of shared libraries Chrome itself links against (libnss3, libgbm1, libasound2, and friends). Modern headless Chrome renders without an X display, so you do not need Xvfb. This makes Vibium a clean fit for CI runners, cron jobs, and containerized scrapers: pip install vibium, set headless=True, install the libs, and the same script you ran on your laptop runs unattended on the box.

What is the headless script?

from vibium import browser_sync as browser
 
vibe = browser.launch(headless=True)
vibe.go("https://example.com")
 
png = vibe.screenshot(full_page=True)
with open("/tmp/page.png", "wb") as f:
    f.write(png)
 
print(vibe.find("h1").text())
 
vibe.quit()

The only difference from a desktop script is headless=True. Chrome runs invisibly, the page loads, and you capture a screenshot and read text exactly as you would locally. Everything else — find(), type(), click(), auto-wait — behaves identically.

How does each step work?

  1. browser.launch(headless=True) — starts Chrome over WebDriver BiDi with no on-screen window. Vibium downloads Chrome for Testing automatically the first time.
  2. vibe.go(url) — navigates and waits for the load event, just as in your first Vibium script.
  3. vibe.screenshot(full_page=True) — captures PNG bytes; on a server this is your main way to "see" what happened.
  4. vibe.find("h1").text() — reads content to log or assert against.
  5. vibe.quit() — closes Chrome and cleans up the process so nothing lingers between runs.

What system libraries does the server need?

On Debian or Ubuntu, install the shared libraries Chrome links against. Vibium brings its own browser binary, but the OS still has to provide these:

sudo apt-get update
sudo apt-get install -y \
  libnss3 libatk-bridge2.0-0 libgbm1 libasound2 \
  libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 \
  libxrandr2 libdrm2 libpango-1.0-0 libcairo2

Then install Vibium and (optionally) pre-fetch Chrome so the first real run is fast:

pip install vibium
vibium install   # pre-download Chrome for Testing

Pre-downloading during your image build or provisioning step keeps the first request from paying the download cost.

How do I run Vibium in a Docker container?

A slim Python base plus the shared libraries above is enough — no system Chrome, because Vibium downloads its own. Pre-fetch the browser at build time so containers start fast:

FROM python:3.12-slim
 
RUN apt-get update && apt-get install -y --no-install-recommends \
    libnss3 libatk-bridge2.0-0 libgbm1 libasound2 \
    libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 \
    libxrandr2 libdrm2 libpango-1.0-0 libcairo2 \
    && rm -rf /var/lib/apt/lists/*
 
RUN pip install --no-cache-dir vibium && vibium install
 
COPY scrape.py /app/scrape.py
CMD ["python", "/app/scrape.py"]

Because the browser is fetched in the image layer, the container does not download Chrome on every cold start.

Why does headless on a server "just work" with Vibium?

Two design choices make this painless. First, Vibium is a single Go binary that bundles the WebDriver BiDi engine and pulls a known-good Chrome for Testing — so there is no driver version to align with the browser, the classic source of CI breakage in older tools. Second, headless mode is a launch flag, not a separate code path, so the script you debugged locally is byte-for-byte the one that runs in CI. For more on the architecture behind this, see how Vibium works.

Tips for reliable server runs

  • Always quit() in a finally block so a crashed script does not leak Chrome processes.
  • Set a sane viewport with window_size=(1280, 800) so headless layout matches what you expect.
  • Capture a screenshot on failure — on a server it is the fastest way to diagnose what the page actually showed.
  • Pin your dependencies so a CI upgrade does not silently change behavior.

Next steps

Frequently asked questions

How do I run Vibium headless on a server?

Pass headless=True to browser.launch() so Chrome runs with no visible window, then deploy your script to the server. Vibium auto-downloads Chrome for Testing on first run, so you only need to install Chrome's shared system libraries on the host before it works.

What dependencies does Vibium need on a headless Linux box?

Vibium ships as a single Go binary and downloads its own Chrome, but Chrome still needs system shared libraries such as libnss3, libgbm1, and libasound2. Install them with your package manager once, after which headless runs work without a display server or Xvfb.

Do I need Xvfb to run Vibium on a server?

No. Modern headless Chrome renders without an X display, so launching with headless=True is enough on a typical Linux server. Xvfb is only needed for the rare tool that demands a real display; Vibium's headless mode does not.

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

Related guides