Library / SDK
stevepryde/thirtyfour avatar
stevepryde/thirtyfour

thirtyfour: Selenium WebDriver automation for Rust

Selenium WebDriver client for Rust, for automated testing of websites

1,443 stars102 forksRustNOASSERTION

At a glance

What is it?
thirtyfour is an async Selenium and WebDriver client for Rust website UI tests, with selector queries, action chains, CDP, and WebDriver BiDi. It fits teams that already operate compatible browser infrastructure and value explicit session cleanup.
Who is it for?
Rust teams using WebDriver, Selenium Grid, or driver-based browser infrastructure should evaluate thirtyfour for async UI tests, while teams seeking recorded no-code tests or a self-contained browser runner should look elsewhere. Verify first that the required commands work with the intended browser and driver, especially for CDP or BiDi, and review the exact enabled Cargo features before upgrading.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • stevepryde/thirtyfour1,443 ★ · +8
Star history
Repository2026-10-172026-11-06
stevepryde/thirtyfour1.4k1.4k

8 Stars in the last 20 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What thirtyfour solves for Rust test engineers

thirtyfour connects Rust test code to browsers through Selenium and W3C WebDriver. It is aimed at engineers writing automated website UI tests in Rust, especially those who want browser interactions to remain inside an existing Rust codebase rather than living in a separate automation language. The library can create a browser session directly through WebDriver, including a setup based on `chromedriver`, or connect through Selenium Standalone or Selenium Grid.

Its documented scope covers the common browser-testing operations: finding elements with `Testid`, `Id`, `ClassName`, `Css`, `TagName`, and `XPath`; sending text and key combinations; clicking; executing JavaScript; using action chains; reading and setting cookies; switching frames, windows, elements, and alerts; handling Shadow DOM; capturing PNG screenshots; and working with alert interfaces. These operations make it relevant to end-to-end checks that exercise forms, navigation, dialogs, frames, and application-owned browser controls.

This is a client library, not a hosted testing service, graphical recorder, or complete test management product. A project still needs a browser, a compatible driver, and suitable Selenium infrastructure. That distinction matters when choosing thirtyfour. Its value is the typed Rust interface around WebDriver sessions, not elimination of browser provisioning or test-environment setup.

How thirtyfour queries elements and manages sessions

The documented async flow starts with `DesiredCapabilities`, creates a managed `WebDriver`, and issues awaited WebDriver operations. Element lookup uses a query interface. A driver-level search begins with `driver.query(By::...)`, adds a description with `.desc(...)`, and expects one result through `.single().await?`. An element can issue its own query, in which case the search is scoped to that element's subtree rather than the whole page.

The Wikipedia example follows this path. It locates a search form by ID, finds the input within that form, sends the term `selenium`, locates the submit button within the same form, and clicks it. It then waits for a unique article heading before reading the page title. Subtree queries help when a page contains repeated structures because the test can search within the component it intends to operate.

Browser shutdown is deliberate. Application-style flows should call `driver.quit().await?`. Test functions are advised to use `run_browser_test`, which the README says attempts cleanup after successful tests, early error returns, and panicking assertions. It also preserves both errors if the test and cleanup operations fail. This reduces leaked browser sessions after failed tests, but it does not eliminate cleanup failures. Browser processes, remote sessions, and WebDriver endpoints still need operational monitoring appropriate to the test environment.

Thirtyfour feature flags for TLS, macros, CDP, and BiDi

Thirtyfour exposes optional Cargo features for several parts of its stack. The default `rustls-tls` feature uses rustls for TLS through `reqwest`. `native-tls` selects native TLS instead. The default `component` feature enables the `Component` derive macro through `thirtyfour_macros` and exports `Component` and `ElementResolver` through the prelude. These options affect dependency behavior and the available API surface, so upgrade reviews should include `Cargo.toml` changes.

The default `cdp` feature provides typed Chrome DevTools Protocol commands. Adding `cdp-events` enables WebSocket-backed event subscription. This separation is useful for teams that need occasional browser-specific commands without subscribing to the event stream, although Chrome is required for CDP. The README does not document a command compatibility matrix by browser or driver version, so teams should validate each CDP command they depend on.

WebDriver BiDi uses the separate opt-in `bidi` feature. It provides typed commands and event subscription across browsers through `WebDriver::bidi()`. Capability negotiation occurs before session startup: callers must use `caps.enable_bidi()` before creating the session. The ordering requirement makes advanced tests more sensitive to setup mistakes. The README does not promise identical support from every Selenium Grid deployment or WebDriver endpoint, which should be checked against the intended environment.

Installing thirtyfour and running an async Wikipedia check

The README identifies the crate as `thirtyfour`, links to its Crates.io page, and states that Rust 1.88 is the minimum supported version. It does not include a `Cargo.toml` dependency block or complete instructions for installing `chromedriver` and starting Selenium Standalone or Grid. Those environment prerequisites must be obtained through the browser and WebDriver distribution selected by the project.

The documented runnable example can be launched from the repository with the following command:

bash
cargo run --example tokio_async

The example uses `#[tokio::main]`, requests Chrome capabilities, starts a managed browser session, and visits Wikipedia. With the required driver available and the example running, the search field should receive `selenium`, the search should submit, and the code should wait for the Wikipedia article heading. It then checks that the page title is `Selenium - Wikipedia` and explicitly quits the browser.

The session initialization shown in the README is:

rust
let caps = DesiredCapabilities::chrome();
let driver = WebDriver::managed(caps).await?;
driver.goto("https://wikipedia.org").await?;

The form is then found as a single element:

rust
let elem_form = driver
    .query(By::Id("search-form"))
    .desc("Wikipedia search form")
    .single()
    .await?;

Application flows should preserve the explicit shutdown call. Test functions should follow the README's recommendation to use `run_browser_test`, whose cleanup path is designed to run after normal returns and panics.

Stable selectors and practical browser-test constraints

Selector quality has a direct effect on whether a WebDriver suite remains useful as a web application changes. The README gives a clear preference order for application-owned hooks: use `data-testid` first, then stable semantic CSS selectors. Visible text can be appropriate when the wording itself is part of the behavior under test. XPath is recommended only when CSS cannot reasonably identify the target.

For example, a settings page can expose a stable test hook and locate its save control like this:

rust
let save_button = driver
    .query(By::Testid("settings-save"))
    .desc("settings save button")
    .single()
    .await?;

This approach couples tests to an application-owned interface instead of incidental styling, but it also means frontend developers must design and preserve that interface. Third-party pages offer less control. The Wikipedia example therefore uses selectors that page already provides, while projects under development can add hooks specifically for tests.

Thirtyfour does not make timing, browser behavior, or infrastructure disappear. The query interface supports explicit waits and predicates, but asynchronous page behavior can still require carefully chosen assertions and reliable synchronization. The README does not document retry policies, parallel test execution, reporting formats, or automatic driver provisioning. Those needs require separate decisions in the surrounding Rust and CI setup.

Where thirtyfour sits against Playwright-based automation

The README provides a Selenium and Playwright translation guide for engineers porting existing automation. That comparison points to a concrete architectural difference. Thirtyfour is centered on Selenium and W3C WebDriver sessions, with support for direct drivers, Selenium Standalone, Selenium Grid, Chrome DevTools Protocol, and WebDriver BiDi.

Thirtyfour is therefore a more natural candidate for a Rust team that already maintains Selenium sessions or requires WebDriver behavior across its test infrastructure. A team already standardized on Playwright should not assume that translation means identical APIs.

The README does not publish a performance comparison, feature parity table, or migration compatibility claim. It also does not document a built-in visual comparison service or graphical test editor. The choice should therefore be based on protocol fit, existing infrastructure, and required browser operations rather than unsupported claims about speed or completeness.

License, recent releases, and thirtyfour upgrade cost

The repository metadata and README identify the project as dual-licensed under `MIT OR Apache-2.0`. The README points to the `NOTICE` file for details and gives the SPDX expression `MIT OR Apache-2.0`. This is a direct licensing statement, not legal advice. Organizations should review the actual license files and notice requirements when integrating the crate.

The repository is not archived. Its last push was on 2026-10-12. Releases `v0.37.8`, `v0.37.7`, and `v0.37.6` were published on 2026-10-12, 2026-10-08, and 2026-10-08 respectively. These dates establish recent release activity, but they do not prove that every browser integration remains compatible. The project requires Rust 1.88 or newer, so older toolchains need an upgrade before adopting the current release line.

Upgrade work can include more than changing the crate version. Teams must review default features, compare `rustls-tls` with `native-tls`, and account for separately enabled `cdp-events` and `bidi` behavior. Driver and Selenium Server compatibility also needs verification because the README does not publish a complete version matrix. The workspace contains `thirtyfour` and `thirtyfour-macros`, so developers maintaining local patches may need to handle both crates rather than editing only one directory.

Editorial conclusion

Rust teams using WebDriver, Selenium Grid, or driver-based browser infrastructure should evaluate thirtyfour for async UI tests, while teams seeking recorded no-code tests or a self-contained browser runner should look elsewhere. Verify first that the required commands work with the intended browser and driver, especially for CDP or BiDi, and review the exact enabled Cargo features before upgrading.

Frequently asked questions

What is thirtyfour used for?

thirtyfour is a Rust client for Selenium and W3C WebDriver. It supports automated website UI tests through direct driver sessions or Selenium Standalone and Grid.

How do I run the thirtyfour async example?

The README documents `cargo run --example tokio_async` with Rust 1.88 or newer and a compatible Chrome WebDriver environment. The example searches Wikipedia for `selenium`, checks the resulting title, and quits the browser.

How does thirtyfour close browser sessions?

Application flows should call `driver.quit().await?`. For test functions, the README recommends `run_browser_test`, which attempts cleanup after successful tests, early returns, and panicking assertions.

Does thirtyfour support WebDriver BiDi?

Yes, through the opt-in `bidi` feature. The README says to call `caps.enable_bidi()` before starting the browser session, after which `WebDriver::bidi()` exposes typed commands and event subscription.

What Rust version does thirtyfour require?

The README states that Rust 1.88 is the minimum supported version. Toolchains older than that cannot use the documented minimum-supported release line without upgrading Rust.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. stevepryde/thirtyfour on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stevepryde-thirtyfour.svg)](https://hysenlabs.com/projects/stevepryde-thirtyfour)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/stevepryde-thirtyfour.svg)](https://hysenlabs.com/projects/stevepryde-thirtyfour)

Was this useful?