felix-starman
Bibbidi - Low-level Elixir client for W3C WebDriver BiDi
Bibbidi — W3C WebDriver BiDi Protocol for Elixir
I’m excited to share Bibbidi, a low-level Elixir implementation of the W3C WebDriver BiDi Protocol.
BEAM Interface to Browsers with BiDi — the name is a nod to the Fairy Godmother’s spell in Disney’s Cinderella.
What is WebDriver BiDi?
WebDriver BiDi is a bidirectional protocol for browser automation. Unlike classic WebDriver (HTTP request/response), BiDi uses a persistent WebSocket connection that lets you send commands and receive real-time events from the browser — think console logs, network requests, navigation events, and more. It’s the successor to CDP (Chrome DevTools Protocol) but is a W3C standard with cross-browser support.
What is Bibbidi?
Bibbidi is a building-block library. It gives you WebSocket connectivity, command/response correlation, and event dispatch, but imposes no supervision tree. You supervise Bibbidi.Connection processes yourself, exactly how you want.
It’s designed as a foundation for RPA frameworks, browser testing libraries, and anything else that needs to talk BiDi to a browser.
Features
-
Full protocol coverage — command builder modules for all BiDi domains: BrowsingContext, Script, Session, Input, Network, Storage, Browser, Emulation, Log, and WebExtension (although I’m adding more Integration tests to validate functionality)
-
Real-time events — subscribe to browser events and receive them as regular Erlang messages (
{:bibbidi_event, method, params}) -
Swappable transport — ships with a
mint_web_sockettransport; bring your own via theBibbidi.Transportbehaviour -
Browser lifecycle —
Bibbidi.BrowserGenServer can launch and manage browser OS processes for you (OS process “culling” PRs or comments would be appreciated, this is an area for improvement) -
Types & events generated from the W3C CDDL spec — attempts to stay as close to the protocol definition as possible
-
No opinionated supervision — fits into any OTP application architecture (I may add Igniter recipes in the future that include some useful supervision abstractions, but ideally this is not part of the library)
-
Interactive Livebook — an included example with a Kino UI for navigating, clicking, running JS, taking screenshots, and watching live events
Quick example
{:ok, conn} = Bibbidi.Connection.start_link(url: "ws://localhost:9222/session")
{:ok, _caps} = Bibbidi.Session.new(conn)
{:ok, tree} = Bibbidi.Commands.BrowsingContext.get_tree(conn)
context = hd(tree["contexts"])["context"]
{:ok, _} = Bibbidi.Commands.BrowsingContext.navigate(conn, context, "https://example.com", wait: "complete")
{:ok, %{"result" => %{"value" => title}}} =
Bibbidi.Commands.Script.evaluate(conn, "document.title", %{context: context})
IO.puts("Page title: #{title}")
Supervision
Bibbidi doesn’t impose a process tree — add connections to your own supervisor:
children = [
{Bibbidi.Connection, url: "ws://localhost:9222/session", name: MyApp.Browser}
]
Supervisor.start_link(children, strategy: :one_for_one)
Try it in Livebook
The repo includes an Interactive Browser Livebook that lets you point-and-click navigate, run JavaScript, take screenshots, and watch browser events in real time.
Links
Installation
def deps do
[
{:bibbidi, "~> 0.1.0"}
]
end
This is v0.1.0 and still fairly early, so feedback, bug reports, and contributions are very welcome! I’d love to hear what you think and what you’d like to build with it.
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #elixirconf-us
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex











First 4 of 4 Posts!
felix-starman
A note: This was created with heavy use of LLMs, although the CDDL parsing did most of the codegen, and the actual GenServer parts aren’t particularly complicated.
For anyone curious on next steps, I’m planning to take a crack at making a
bibbidi_wallabyorphoenix_test_bibbidimainly to stress the interface, and because it won’t cause as many issues if the API needed to change, since end users would be less likely to interact w/ Bibbidi directly.I’d also be adding some useful igniter generators of different supervision patterns that someone could use.
Medium time horizon, I want to play around with some dependent plugins in the vein of
puppeteer-extraand it’s sub-project playwright-extra, in particular the stealth pluginsLonger term, once the interface is more stable (I may go to structs/protocols, we’ll see, FEEDBACK WELCOME!) I am hoping to have some useful graph-walking approaches and Jido examples w/ igniter templates. The idea being it could walk a graph to control the browser and/or have a Jido Agent able to work w/
JidoBrowser(I need to look into this more anyways) and Bibbidi to provide a full set of functionality and controls.felix-starman
I released a 0.2, and a quick 0.3
TL;DR because some of the changes are less important
Bibbidi.Encodableprotocol for writing custom commands if you wantExpandableprotocol but that immediately became a workflow enginebibbidi_runicfor a very-alpha/unreleased example of how to use bibbidi with a workflow enginemix bibbidi.gen.workflowor look at exampleOpWorkflow.Opfor another self-maintained option:telemetryset up for your use, and aBibbidi.Telemetry.Metadatato make it easier to emit attributes that help correlate commands/events, or custom workflow operations togetherBibbidi.Keysfor converting to BiDi compliant unicode characters (e.g. Super, Ctrl, Alt, Enter)Feedback on documentation, or anything that pops into your mind would be appreciated.
The 0.2.0 and 0.3.0 changelog is here:
mikehostetler
Felix, happy to collab on this! I have hit some of the same issues you ran into that prompted creating this package - would be interesting to discuss the best way forward.
felix-starman
I am going to release 0.4 shortly once some docs improvements are combined with that branch.
The interface though is fairly stable. There’s a backwards compatible breaking change that allows people to control the interface for how they receive messages, but defaults to the event structs.
I have a design plan for a higher level library called Bobbidi that I think would probably be the better interface for general purpose use as it will contain all of the useful tooling for the different libraries to adapt to their use case.
I’d like to keep Bibbidi as close to the spec as possible, and have some useful helpers for constructing some of the more complex structs such as sending keys and other things like that.
Bobbidi will probably be the place, where if you just need some high-level hooks for interacting with a browser in a typical way and you don’t need to control absolutely everything, you would interface with it.
Let me know some of the pain points you’ve had as well. I have some ideas for how to write bobbidi adapters for the different upstream libraries but knowing the pain points will really help