Rustenium
The most robust, high-performance WebDriver BiDi automation library for Rust.
Rustenium provides a powerful and ergonomic API for browser automation using the WebDriver BiDi protocol. It offers both low-level control and high-level abstractions for common automation tasks.
Features
- WebDriver BiDi Protocol: Built on the modern BiDi protocol for bidirectional communication
- Chrome Support: First-class support for Chrome/Chromium browsers
- Flexible Input Methods:
- BidiMouse: Direct, precise mouse movements for fast automation
- HumanMouse: Realistic mouse movements with Bezier curves and jitter to mimic human behavior
- Keyboard: Full keyboard support with modifier keys
- Touchscreen: Multi-touch gesture support for mobile testing
- CSS & XPath Selectors: Convenient macros (
css!(), xpath!()) for element location
- Screenshot Capture: Take screenshots of elements or entire pages
- Network Interception: Monitor and intercept network requests
- Event System: Subscribe to browser events in real-time
- Type-Safe API: Leverages Rust's type system for compile-time safety
Installation
Add Rustenium to your Cargo.toml:
[dependencies]
rustenium = "1.0.0"
tokio = { version = "1", features = ["full"] }
Quick Start
use rustenium::browsers::create_chrome_browser;
use rustenium_macros::css;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
browser.navigate("https://example.com").await?;
let search_box = browser.find_node(css!("input[type='search']")).await?.expect("No node found");
search_box.screenshot().await?;
let mut submit_button = browser.find_node(css!("button[type='submit']")).await?.expect("No node found");
submit_button.mouse_click().await?;
browser.screenshot().await?;
Ok(())
}
Examples
Browser Setup and Navigation
use rustenium::browsers::{ChromeConfig, NavigateOptions, create_chrome_browser};
use rustenium_bidi_definitions::browsing_context::types::ReadinessState;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = ChromeConfig::default();
config.capabilities.add_arg("--disable-gpu")
.add_args(["--window-size=1920,1080"])
.accept_insecure_certs(true);
let mut browser = create_chrome_browser(Some(config)).await;
browser.navigate_with_options("https://example.com", NavigateOptions {
wait: Some(ReadinessState::Interactive),
..Default::default()
}).await?;
Ok(())
}
Finding Elements
use rustenium::browsers::create_chrome_browser;
use rustenium_macros::{css, xpath};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
let element = browser.find_node(css!("#my-id")).await?;
let buttons = browser.find_nodes(css!(".btn-primary")).await?;
let headers = browser.find_nodes(xpath!("//h1[@class='title']")).await?;
Ok(())
}
Mouse Input - Precise Movements
use rustenium::browsers::create_chrome_browser;
use rustenium::input::{MouseMoveOptions, Point};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
let context_id = browser.get_active_context_id()?;
browser.mouse().move_to(Point { x: 100.0, y: 200.0 }, &context_id, MouseMoveOptions {
steps: Some(5),
..Default::default()
}).await?;
browser.mouse().click(None, &context_id, MouseClickOptions::default()).await?;
Ok(())
}
Mouse Input - Human-Like Movements
use rustenium::browsers::create_chrome_browser;
use rustenium::input::{MouseMoveOptions, MouseClickOptions, Point};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
let context_id = browser.get_active_context_id()?;
browser.human_mouse().move_to(Point { x: 100.0, y: 200.0 }, &context_id, MouseMoveOptions::default()).await?;
browser.human_mouse().click(None, &context_id, MouseClickOptions::default()).await?;
Ok(())
}
Keyboard Input
use rustenium::browsers::create_chrome_browser;
use rustenium::input::KeyboardTypeOptions;
use rustenium_macros::css;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
let context_id = browser.get_active_context_id()?;
browser.navigate("https://example.com").await?;
let text = browser.wait_for_node(css!("#text")).await?.expect("No node exists");
browser.keyboard().down("Enter", &context_id).await?;
sleep(Duration::from_secs(1)).await;
browser.keyboard().up("Enter", &context_id).await?;
browser.keyboard().type_text(&text.get_inner_text().await, &context_id, Some(KeyboardTypeOptions { delay: Some(36) })).await?;
browser.keyboard().down("Control", &context_id).await?;
browser.keyboard().press("a", &context_id, None).await?; browser.keyboard().up("Control", &context_id).await?;
Ok(())
}
Network Interception
use rustenium::browsers::create_chrome_browser;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut browser = create_chrome_browser(None).await;
browser.on_request_bidi(|request| async move {
println!("Request URL: {}", request.url());
if request.url().contains("ads.example.com") {
let _ = request.abort().await;
return;
}
request.continue_().await;
}).await?;
browser.authenticate("username", "password").await?;
Ok(())
}
Documentation
Full API documentation is available on docs.rs.
Browser Support
Currently supported browsers:
- Chrome/Chromium (stable, beta, dev, canary)
Support for Firefox and other browsers is planned for future releases.
Requirements
- Rust 1.85 or later (2024 edition)
- Chrome/Chromium browser installed (for Chrome automation)
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.