VLearnVibium

How Vibium's Actionability (Auto-Wait) Works

Vibium's actionability auto-wait runs checks (visible, stable, receives events, enabled, editable) server-side in Go before each action — skip sleeps.

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

Vibium's actionability is its auto-wait system: before performing any action, the Go binary polls until the target element satisfies a set of conditions — visible, stable, receives events, enabled, and (for fills) editable — up to a default 30-second timeout. Borrowed from Playwright and implemented server-side in Go, these checks mean you almost never write sleep() or retry loops. When you call el.click(), Vibium waits for the button to actually be clickable: not hidden, not still animating, not covered by a loading spinner, and not disabled. If the conditions are met, it acts; if the timeout passes first, it raises a clear timeout error instead of clicking the wrong thing. Because the logic lives in the single Go binary, every client — Python, JavaScript, and the MCP server — gets identical timing behavior.

What are the actionability checks?

Vibium verifies up to five conditions, and different actions require different subsets. Each check exists to prevent a specific class of flaky failure.

CheckWhat it meansWhy it matters
VisibleNon-zero size, not display:none or visibility:hiddenYou can't interact with invisible things
StableBounding box unchanged over 50msClicking a moving target misses
Receives eventsThe element (or a child) is what's at its center pointClicks would hit a covering overlay
EnabledNot disabled, aria-disabled, or in a disabled <fieldset>Disabled controls ignore input
EditableAccepts text and isn't read-only (fills only)Only relevant for typing into fields

Which actions run which checks?

Each action runs only the checks that make sense for it, so Vibium doesn't over-wait. A click needs the element to receive pointer events; a fill (which sets the value programmatically) does not.

ActionChecks applied
Click, double-click, tap, check, typeVisible + Stable + Receives events + Enabled
Hover, dragVisible + Stable + Receives events
FillVisible + Enabled + Editable
Select optionVisible + Enabled
Scroll into viewStable

Typing actions click to focus first, so they use the click set. fill skips the "receives events" check because it sets the value via JavaScript rather than simulating keystrokes — but it does require the field to be editable.

How does the polling loop work?

Vibium runs the actionability checks in a loop until they pass or the timeout is reached, sleeping briefly between attempts. The element-side checks run in a single BiDi round-trip per attempt for speed.

deadline = now + timeout (default 30s)

loop:
    run actionability script
    if failed or not found:
        if past deadline: raise TimeoutError
        sleep 100ms; continue

    if stability is required:
        sleep 50ms
        run script again
        if bounding boxes differ:
            if past deadline: raise TimeoutError
            sleep 100ms; continue

    return element (ready to act)

Stability is the one check that runs partly on the Go side, because it needs a time delay: Vibium measures the bounding box, waits 50ms, measures again, and only proceeds if the box hasn't moved. Everything else runs inside the page in one shot.

What does this look like in code?

Because waiting is automatic, your script reads like a description of intent, with no timing scaffolding. Here is a login flow using the verified Python sync API:

from vibium import browser_sync as browser
 
vibe = browser.launch()
vibe.go("https://app.example.com/login")
 
# Each call auto-waits for actionability — no sleeps needed
vibe.find("#username").type("alice")
vibe.find("#password").type("s3cret")
vibe.find(role="button", text="Sign in").click()
 
print(vibe.find(".welcome").text())
vibe.quit()

Notice there is no wait_for before the click. If the "Sign in" button is briefly disabled while the form validates, Vibium simply keeps polling until it becomes enabled, then clicks.

How do I scroll, and what about off-screen elements?

You rarely need to scroll manually — Vibium automatically scrolls an element into view before running its checks. The actionability script calls Chrome's scrollIntoViewIfNeeded (falling back to scrollIntoView) so an off-screen button gets a fair chance to become visible before the visibility and hit-testing checks run. That means a click() on an element below the fold just works.

Can I change or shorten the timeout?

Yes. The default is 30 seconds, but you can override it per action when you know an element should appear fast and want to fail quickly. In JavaScript:

await page.find('#submit').click({ timeout: 5000 }) // wait up to 5s

A shorter timeout is useful in tests where a missing element should be reported as a failure rather than hanging for the full 30 seconds.

Why server-side actionability matters

Putting actionability in the binary is what lets the clients stay trivial. The waiting logic is written once in Go, runs over a fast local connection to the browser, and gives Python, JavaScript, and AI agents the same behavior. That is also why the accessibility-tree finders and semantic selectors feel so robust — they ride on the same actionability engine. You describe the element and the action; Vibium handles the timing.

Next steps

Frequently asked questions

What is actionability in Vibium?

Actionability is Vibium's auto-wait system: a set of conditions an element must satisfy before an action runs. Vibium polls until the element is visible, stable, receiving events, enabled, and (for fills) editable, up to a 30-second default timeout, so your scripts don't need manual sleeps or retries.

What checks does Vibium run before clicking?

Before a click, Vibium verifies four conditions: the element is visible (non-zero size, not hidden by CSS), stable (its bounding box hasn't moved over 50ms), receives events (not covered by an overlay), and enabled (not disabled or aria-disabled). All must pass within the timeout.

How do I change Vibium's auto-wait timeout?

The default actionability timeout is 30 seconds. You can override it per action by passing a timeout. For example, in JavaScript page.find('#submit').click({ timeout: 5000 }) waits up to 5 seconds. If the element never becomes actionable, Vibium raises a timeout error.

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

Related guides