Writing Your First Browser Automation Code
Before we begin, you’ll need to install Rust. You can do so by using the rustup tool.
Let’s start a new project. Open your terminal application and navigate to the directory where you usually put your source code. Then run these commands:
cargo new --bin my-automation-project
cd my-automation-project
You will see a Cargo.toml file and a src/ directory there already.
First, let’s edit the Cargo.toml file in your editor (e.g. Visual Studio Code) and add some dependencies:
[dependencies]
thirtyfour = "0.37.2"
tokio = { version = "1", features = ["full"] }
Great! Now let’s open src/main.rs and add the following code.
NOTE: Make sure you remove any existing code from
main.rs.
Don’t worry, we’ll go through what it does soon.
/src/main.rs
use std::error::Error;
use thirtyfour::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
let driver = WebDriver::managed(DesiredCapabilities::chrome()).await?;
// Navigate to https://wikipedia.org.
driver.goto("https://wikipedia.org").await?;
let elem_form = driver
.query(By::Id("search-form"))
.desc("Wikipedia search form")
.single()
.await?;
// Querying from an element scopes the search to its subtree.
let elem_text = elem_form
.query(By::Id("searchInput"))
.desc("Wikipedia search input")
.single()
.await?;
// Type in the search terms.
elem_text.send_keys("selenium").await?;
// Click the search button.
let elem_button = elem_form
.query(By::Css("button[type='submit']"))
.desc("Wikipedia search button")
.single()
.await?;
elem_button.click().await?;
// Wait for the unique article heading before checking the title.
driver
.query(By::ClassName("firstHeading"))
.desc("Wikipedia article heading")
.single()
.await?;
assert_eq!(driver.title().await?, "Selenium - Wikipedia");
// Always explicitly close the browser.
driver.quit().await?;
Ok(())
}
Selector note: Wikipedia is a third-party site, so this example uses the stable IDs, element types, and classes that the real page exposes. In an app you control, add stable
data-testidhooks to important controls and preferBy::Testid:#![allow(unused)] fn main() { let save_button = driver .query(By::Testid("settings-save")) .desc("settings save button") .single() .await?; }See Element Queries for the selector priority and guidance on text matching and XPath.
Make sure Chrome is installed, then run:
cargo run
If everything worked correctly you should have seen a Chrome browser window open up, navigate to the “Selenium” article on Wikipedia, and then close again.
The first run will take a few seconds longer than subsequent runs — thirtyfour
downloads a matching chromedriver into your system cache directory the first time,
then reuses it on every later run. See WebDriver Manager
for the version-pinning, offline-mode, and observability options that the manager
provides.
Running on Firefox
To run the code using Firefox instead, change the capabilities in main:
#![allow(unused)]
fn main() {
let driver = WebDriver::managed(DesiredCapabilities::firefox()).await?;
}
Make sure Firefox is installed, and re-run:
cargo run
If everything worked correctly, you should have seen the Wikipedia page open up on Firefox this time.
Congratulations! You successfully automated a web browser.
Before building a larger suite, copy the short Reliable AI-Generated Tests checklist into your coding-agent instructions or project guidance. It captures the reliability rules used by this example and links to the deeper documentation for each one.