15 releases
| new 0.2.5 | May 11, 2026 |
|---|---|
| 0.2.4 | May 9, 2026 |
| 0.1.9 | Apr 29, 2026 |
| 0.1.3 | Mar 19, 2026 |
#485 in Hardware support
215KB
4.5K
SLoC
rust_drission
rust_drission is a Rust browser automation library built on Chrome DevTools Protocol (CDP). Its public API is intentionally close to DrissionPage, and the recommended entry point for most usage is ChromiumPage.
rust_drission 是一个基于 Chrome DevTools Protocol (CDP) 的 Rust 浏览器自动化库。它的公开 API 尽量贴近 DrissionPage,大多数场景建议直接从 ChromiumPage 开始。
Why ChromiumPage
- One entry point for browser launch, navigation, element lookup, JS execution, screenshots, cookies, and tab access
- DrissionPage-style locator strings such as
css:,xpath:,text:,id:,class:,tag: - Supports direct JS/CDP calls when the high-level API is not enough
- Keeps advanced capabilities available through
page.tab()andpage.browser() - Built-in network traffic listening with URL/resource-type filtering and batch collection
- Built-in stealth injection by default for the initial tab and
new_tab()
Installation
[dependencies]
rust_drission = "0.2"
Quick Start
use rust_drission::{BrowserConfig, ChromiumPage, CdpError};
fn main() -> Result<(), CdpError> {
let page = ChromiumPage::new(
BrowserConfig::new()
.headless(false)
.set_local_port(9222),
)?;
page.get("https://example.com")?;
println!("title = {}", page.title()?);
println!("url = {}", page.url()?);
if let Some(h1) = page.ele("css:h1")? {
println!("h1 = {}", h1.text()?);
}
page.screenshot("example.png")?;
Ok(())
}
Common Patterns
Launch a new Chrome
ChromiumPage::new(...) starts a fresh browser instance and injects the built-in stealth script into the initial tab.
use rust_drission::{BrowserConfig, ChromiumPage};
let page = ChromiumPage::new(
BrowserConfig::new()
.chrome_path("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe")
.user_data_dir("./data/profile")
.set_local_port(9222)
.headless(false),
)?;
If you want to skip stealth injection for the initial tab, use ChromiumPage::new_without_stealth(...).
Connect to an existing Chrome
Chrome must already be started with remote debugging enabled, for example:
chrome --remote-debugging-port=9222
Then connect:
use rust_drission::ChromiumPage;
let page = ChromiumPage::connect("127.0.0.1:9222")?;
Use connect(...) only when you want to attach to an already-running browser instead of launching a fresh one.
Locate and operate on elements
page.input("css:input[name='q']", "rust cdp")?;
page.click("text:Search")?;
if let Some(button) = page.ele("id:submit")? {
println!("enabled = {}", button.is_enabled()?);
}
Listen to network traffic
use std::time::Duration;
// Start listener first (blocks until ready), then navigate
let listener = page.listen()?;
page.get("https://example.com")?;
// Receive all packets
while let Some(pkt) = listener.wait(Duration::from_secs(5))? {
println!("{} {} → {}", pkt.request.method, pkt.request.url, pkt.response.status.unwrap_or(0));
}
// Or filter by URL keyword
let url_listener = page.listen_url("api")?;
page.get("https://example.com")?;
if let Some(pkt) = url_listener.wait(Duration::from_secs(10))? {
println!("API response: {:?}", pkt.body);
}
// Or filter by resource type (XHR, Fetch, Document, Script, etc.)
let fetch_listener = page.listen_resource_type("Fetch")?;
// Or batch collect after navigation
let listener = page.listen()?;
page.get("https://example.com")?;
let packets = page.listen_collect(&listener, Duration::from_secs(5), |pkt| true)?;
println!("collected {} packets", packets.len());
Run JavaScript
let result = page.run_js("document.title")?;
let async_result = page.run_js_await("fetch('https://httpbin.org/get').then(r => r.json())")?;
Use advanced page APIs
use std::time::Duration;
// wait() is on ChromiumPage; all other wait_* methods are on Page (via tab())
if let Ok(el) = page.wait(".item-list", Duration::from_secs(5)) {
println!("loaded: {}", el.text()?);
}
let tab = page.tab();
tab.wait_visible("css:.result", Duration::from_secs(10))?;
tab.wait_hidden("#spinner", Duration::from_secs(5))?;
tab.wait_network_idle()?;
tab.set_local_storage("token", "demo-value")?;
Documentation
- Chinese guide: docs/usage.zh-CN.md
- English guide: docs/usage.en.md
- Skill guide for usage-oriented prompting: skills/rust_drission/SKILL.md
Notes
ChromiumPageis the recommended starting point. Usepage.tab()orpage.browser()only when you need lower-level control.Framesupport is aimed at same-origin iframes.listen()is available directly onChromiumPage, as well aslisten_url(),listen_resource_type(), andlisten_collect().- Always start the listener before navigating, so no network events are missed:
let l = page.listen()?; page.get("...")?;. - Element lookup methods often return
Result<Option<Element>, CdpError>. Handle theNonecase explicitly.
Changelog
v0.2.5
- Make
ChromiumPage::new(...)always launch a fresh browser instance instead of attaching to an existing remote-debugging session. - Inject the built-in stealth script into tabs created by
ChromiumPage::new_tab(...), and addnew_without_stealth(...)/new_tab_without_stealth(...)for callers that need a clean tab. - Add
Page::listen_url(...)andPage::listen_resource_type(...)helpers alongside the existingChromiumPagelistener filters.
v0.2.4
- Improve stealth injection defaults on newly created
ChromiumPageinstances: suppress common console-based anti-debug hooks, masknavigator.webdriver, blocklocation.replace("about:blank"), and filter suspicioussetIntervaldebugger loops. - Add a simple Boss Zhipin example at
examples/boss.rsfor opening the candidate list page with a persistentuser_data_dir.
v0.2.3
- Fix: XPath and Text locators now query the live DOM via
Runtime.evaluateinstead of querying CDP's stale internal DOM snapshot (DOM.performSearch). This fixespage.wait()timing out for dynamically-created elements when using XPath / Text locators. - Fix: preserve
objectIdwhen constructingElementfrom XPath evaluation results, so thattag()andtext()return correct values instead of empty strings.
v0.2.2
- Fix: when a custom
user_data_diris specified viaBrowserConfig::user_data_dir(), the directory is now auto-created before Chrome starts. Previously it was only created for auto-generated temp paths, which could cause Chrome to show a "Cannot perform read/write operations" system dialog on Windows when the directory didn't exist.
v0.2.1
- Fix: clean up Chrome Singleton lock files (
SingletonLock,SingletonCookie,SingletonSocket) inuser_data_dirbefore browser launch, preventing startup failures when a previous browser instance crashed or was killed unexpectedly
v0.2.0
- All error messages changed from Chinese to English for better internationalization
- macOS: auto-detect Chrome, Chrome Canary, Chromium, Edge, and Brave browser paths
- Fixed element lookup fallback logic to avoid false errors when main scan returns no results
- Added 5 runnable API test examples (navigation, element actions, element queries, browser tabs)
- Cross-platform example paths (no longer Windows-only)
Dependencies
~4–16MB
~147K SLoC