pub struct Page<'b> { /* private fields */ }Expand description
A loaded page within the browser.
Implementations§
Source§impl<'b> Page<'b>
impl<'b> Page<'b>
Sourcepub async fn mouse_move(&self, x: f64, y: f64, steps: u32) -> Result<()>
pub async fn mouse_move(&self, x: f64, y: f64, steps: u32) -> Result<()>
Move mouse along a human-like bezier curve to (x, y).
Sourcepub async fn click(&self, x: f64, y: f64) -> Result<()>
pub async fn click(&self, x: f64, y: f64) -> Result<()>
Click at (x, y) with human-like mouse movement first.
Examples found in repository?
examples/input_test.rs (line 32)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== Input Simulation Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22 let page = browser.navigate("https://www.google.com").await
23 .expect("navigate failed");
24
25 println!("[1] Human idle (2s)...");
26 page.human_idle(2000).await.expect("idle failed");
27
28 println!("[2] Scroll...");
29 page.scroll(300).await.expect("scroll failed");
30
31 println!("[3] Click...");
32 page.click(600.0, 300.0).await.expect("click failed");
33
34 println!("[4] Type...");
35 page.type_text("hello").await.expect("type failed");
36
37 println!("[5] Shutting down...");
38 browser.shutdown().await.expect("shutdown failed");
39
40 println!("\n=== PASSED ===");
41}Sourcepub async fn type_text(&self, text: &str) -> Result<()>
pub async fn type_text(&self, text: &str) -> Result<()>
Type text with human-like timing.
Examples found in repository?
examples/input_test.rs (line 35)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== Input Simulation Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22 let page = browser.navigate("https://www.google.com").await
23 .expect("navigate failed");
24
25 println!("[1] Human idle (2s)...");
26 page.human_idle(2000).await.expect("idle failed");
27
28 println!("[2] Scroll...");
29 page.scroll(300).await.expect("scroll failed");
30
31 println!("[3] Click...");
32 page.click(600.0, 300.0).await.expect("click failed");
33
34 println!("[4] Type...");
35 page.type_text("hello").await.expect("type failed");
36
37 println!("[5] Shutting down...");
38 browser.shutdown().await.expect("shutdown failed");
39
40 println!("\n=== PASSED ===");
41}Sourcepub async fn scroll(&self, delta_y: i32) -> Result<()>
pub async fn scroll(&self, delta_y: i32) -> Result<()>
Scroll with human-like momentum.
Examples found in repository?
examples/input_test.rs (line 29)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== Input Simulation Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22 let page = browser.navigate("https://www.google.com").await
23 .expect("navigate failed");
24
25 println!("[1] Human idle (2s)...");
26 page.human_idle(2000).await.expect("idle failed");
27
28 println!("[2] Scroll...");
29 page.scroll(300).await.expect("scroll failed");
30
31 println!("[3] Click...");
32 page.click(600.0, 300.0).await.expect("click failed");
33
34 println!("[4] Type...");
35 page.type_text("hello").await.expect("type failed");
36
37 println!("[5] Shutting down...");
38 browser.shutdown().await.expect("shutdown failed");
39
40 println!("\n=== PASSED ===");
41}More examples
examples/youtube_test.rs (line 28)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== YouTube Headful Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22
23 let page = browser.navigate("https://www.youtube.com").await
24 .expect("failed to navigate");
25
26 // Simulate human behavior
27 page.human_idle(1500).await.expect("idle failed");
28 page.scroll(200).await.expect("scroll failed");
29
30 println!("Title: {}", page.js("document.title").await.unwrap_or_default());
31 println!("URL: {}", page.js("window.location.href").await.unwrap_or_default());
32
33 let checks: &[(&str, &str)] = &[
34 ("UA", "navigator.userAgent"),
35 ("Cores", "navigator.hardwareConcurrency.toString()"),
36 ("Memory", "(navigator.deviceMemory||'?').toString()"),
37 ("webdriver", "navigator.webdriver.toString()"),
38 ("Screen", "screen.width+'x'+screen.height"),
39 ("Timezone", "Intl.DateTimeFormat().resolvedOptions().timeZone"),
40 ("GPU", "(function(){var c=document.createElement('canvas');var g=c.getContext('webgl');if(!g)return'no';var d=g.getExtension('WEBGL_debug_renderer_info');return d?g.getParameter(d.UNMASKED_RENDERER_WEBGL):'no'})()"),
41 ];
42 for (name, code) in checks {
43 println!("{}: {}", name, page.js(code).await.unwrap_or_default());
44 }
45
46 browser.shutdown().await.expect("shutdown failed");
47 println!("\nDone.");
48}Sourcepub async fn human_idle(&self, duration_ms: u64) -> Result<()>
pub async fn human_idle(&self, duration_ms: u64) -> Result<()>
Simulate idle human presence with random mouse movements.
Examples found in repository?
examples/input_test.rs (line 26)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== Input Simulation Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22 let page = browser.navigate("https://www.google.com").await
23 .expect("navigate failed");
24
25 println!("[1] Human idle (2s)...");
26 page.human_idle(2000).await.expect("idle failed");
27
28 println!("[2] Scroll...");
29 page.scroll(300).await.expect("scroll failed");
30
31 println!("[3] Click...");
32 page.click(600.0, 300.0).await.expect("click failed");
33
34 println!("[4] Type...");
35 page.type_text("hello").await.expect("type failed");
36
37 println!("[5] Shutting down...");
38 browser.shutdown().await.expect("shutdown failed");
39
40 println!("\n=== PASSED ===");
41}More examples
examples/youtube_test.rs (line 27)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== YouTube Headful Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22
23 let page = browser.navigate("https://www.youtube.com").await
24 .expect("failed to navigate");
25
26 // Simulate human behavior
27 page.human_idle(1500).await.expect("idle failed");
28 page.scroll(200).await.expect("scroll failed");
29
30 println!("Title: {}", page.js("document.title").await.unwrap_or_default());
31 println!("URL: {}", page.js("window.location.href").await.unwrap_or_default());
32
33 let checks: &[(&str, &str)] = &[
34 ("UA", "navigator.userAgent"),
35 ("Cores", "navigator.hardwareConcurrency.toString()"),
36 ("Memory", "(navigator.deviceMemory||'?').toString()"),
37 ("webdriver", "navigator.webdriver.toString()"),
38 ("Screen", "screen.width+'x'+screen.height"),
39 ("Timezone", "Intl.DateTimeFormat().resolvedOptions().timeZone"),
40 ("GPU", "(function(){var c=document.createElement('canvas');var g=c.getContext('webgl');if(!g)return'no';var d=g.getExtension('WEBGL_debug_renderer_info');return d?g.getParameter(d.UNMASKED_RENDERER_WEBGL):'no'})()"),
41 ];
42 for (name, code) in checks {
43 println!("{}: {}", name, page.js(code).await.unwrap_or_default());
44 }
45
46 browser.shutdown().await.expect("shutdown failed");
47 println!("\nDone.");
48}Sourcepub async fn capture_mhtml(&self) -> Result<Vec<u8>>
pub async fn capture_mhtml(&self) -> Result<Vec<u8>>
Capture full page as MHTML (HTML + JS + CSS + images — everything). Save to .mhtml file, opens in Chrome with full fidelity.
Examples found in repository?
examples/capture_test.rs (line 23)
8async fn main() {
9 let browser = Browser::builder()
10 .headful()
11 .random()
12 .build().await
13 .expect("failed to create browser");
14
15 let page = browser.navigate("https://www.youtube.com").await
16 .expect("navigate failed");
17
18 // Wait for page to fully load
19 tokio::time::sleep(std::time::Duration::from_secs(3)).await;
20
21 // 1. Capture full MHTML (HTML + JS + CSS + images)
22 println!("[1] Capturing MHTML...");
23 let mhtml = page.capture_mhtml().await.expect("mhtml failed");
24 std::fs::write("youtube.mhtml", &mhtml).expect("write failed");
25 println!(" Saved youtube.mhtml ({} bytes)", mhtml.len());
26
27 // 2. Capture HTML via DOM (scripts intact, no escaping issues)
28 println!("[2] Capturing HTML via DOM...");
29 let html = page.capture_html().await.expect("html failed");
30 std::fs::write("youtube.html", &html).expect("write failed");
31 println!(" Saved youtube.html ({} bytes)", html.len());
32
33 // Verify scripts are intact
34 let script_count = html.matches("<script").count();
35 println!(" <script> tags found: {}", script_count);
36
37 browser.shutdown().await.expect("shutdown failed");
38 println!("\nDone. Open youtube.mhtml in Chrome to verify.");
39}Sourcepub async fn capture_html(&self) -> Result<String>
pub async fn capture_html(&self) -> Result<String>
Capture page HTML via DOM API (won’t break JS/special chars).
Returns outerHTML including all <script> tags intact.
Examples found in repository?
examples/capture_test.rs (line 29)
8async fn main() {
9 let browser = Browser::builder()
10 .headful()
11 .random()
12 .build().await
13 .expect("failed to create browser");
14
15 let page = browser.navigate("https://www.youtube.com").await
16 .expect("navigate failed");
17
18 // Wait for page to fully load
19 tokio::time::sleep(std::time::Duration::from_secs(3)).await;
20
21 // 1. Capture full MHTML (HTML + JS + CSS + images)
22 println!("[1] Capturing MHTML...");
23 let mhtml = page.capture_mhtml().await.expect("mhtml failed");
24 std::fs::write("youtube.mhtml", &mhtml).expect("write failed");
25 println!(" Saved youtube.mhtml ({} bytes)", mhtml.len());
26
27 // 2. Capture HTML via DOM (scripts intact, no escaping issues)
28 println!("[2] Capturing HTML via DOM...");
29 let html = page.capture_html().await.expect("html failed");
30 std::fs::write("youtube.html", &html).expect("write failed");
31 println!(" Saved youtube.html ({} bytes)", html.len());
32
33 // Verify scripts are intact
34 let script_count = html.matches("<script").count();
35 println!(" <script> tags found: {}", script_count);
36
37 browser.shutdown().await.expect("shutdown failed");
38 println!("\nDone. Open youtube.mhtml in Chrome to verify.");
39}Sourcepub async fn js(&self, code: &str) -> Result<String>
pub async fn js(&self, code: &str) -> Result<String>
Execute JavaScript and return the result as a string.
Examples found in repository?
examples/smoke_test.rs (line 22)
8async fn test_antidetect(page: &clawser_browser::Page<'_>, label: &str) {
9 println!("\n --- {} antidetect checks ---", label);
10 let checks: &[(&str, &str)] = &[
11 ("UA", "navigator.userAgent"),
12 ("Platform", "navigator.platform"),
13 ("Languages", "JSON.stringify(navigator.languages)"),
14 ("Cores", "navigator.hardwareConcurrency.toString()"),
15 ("webdriver", "navigator.webdriver.toString()"),
16 ("Screen", "screen.width + 'x' + screen.height"),
17 ("Timezone", "Intl.DateTimeFormat().resolvedOptions().timeZone"),
18 ("chrome", "typeof window.chrome"),
19 ("cdc_", "(function(){for(var k in window){if(/^cdc_/.test(k))return 'YES'}return 'NO'})()"),
20 ];
21 for (name, code) in checks {
22 match page.js(code).await {
23 Ok(val) => println!(" {}: {}", name, val),
24 Err(e) => println!(" {}: ERROR - {}", name, e),
25 }
26 }
27}
28
29#[tokio::main]
30async fn main() {
31 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
32 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
33 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
34 let cfg = dir.join("test_profile.json");
35 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
36 }
37 "out/Default/test_profile.json".to_string()
38 });
39
40 println!("=== clawser-browser smoke test (async) ===\n");
41
42 // HEADLESS
43 println!("[1] Creating HEADLESS browser...");
44 let start = Instant::now();
45 let browser = Browser::builder().headless().config(&config).build().await
46 .expect("Failed to create headless browser");
47 println!(" OK in {:?}", start.elapsed());
48
49 let page = browser.navigate("about:blank").await.expect("navigate failed");
50 let result = page.js("1 + 1").await.expect("js failed");
51 assert!(result.contains("2"));
52 test_antidetect(&page, "HEADLESS").await;
53 browser.shutdown().await.expect("shutdown failed");
54
55 // HEADFUL
56 println!("\n[2] Creating HEADFUL browser...");
57 let start = Instant::now();
58 let browser = Browser::builder().headful().config(&config).build().await
59 .expect("Failed to create headful browser");
60 println!(" OK in {:?}", start.elapsed());
61
62 let page = browser.navigate("about:blank").await.expect("navigate failed");
63 test_antidetect(&page, "HEADFUL").await;
64 browser.shutdown().await.expect("shutdown failed");
65
66 println!("\n=== ALL TESTS PASSED ===");
67}More examples
examples/rotate_test.rs (line 19)
8async fn main() {
9 println!("=== Profile Rotation Test (async) ===\n");
10
11 for i in 0..3 {
12 println!("--- Browser {} (random profile) ---", i + 1);
13
14 let browser = Browser::builder().headful().random().build().await
15 .expect("failed to create browser");
16
17 let page = browser.navigate("about:blank").await.expect("navigate failed");
18
19 let cores = page.js("navigator.hardwareConcurrency.toString()").await.unwrap_or_default();
20 let screen = page.js("screen.width+'x'+screen.height").await.unwrap_or_default();
21 let tz = page.js("Intl.DateTimeFormat().resolvedOptions().timeZone").await.unwrap_or_default();
22 let langs = page.js("JSON.stringify(navigator.languages)").await.unwrap_or_default();
23 let gl = page.js(
24 "(function(){var c=document.createElement('canvas');var g=c.getContext('webgl');if(!g)return'no';var d=g.getExtension('WEBGL_debug_renderer_info');return d?g.getParameter(d.UNMASKED_RENDERER_WEBGL):'no'})()"
25 ).await.unwrap_or_default();
26
27 println!(" Cores: {} Screen: {}", cores, screen);
28 println!(" GPU: {}", gl);
29 println!(" TZ: {} Langs: {}", tz, langs);
30
31 browser.shutdown().await.expect("shutdown failed");
32 println!();
33 }
34
35 println!("=== DONE ===");
36}examples/youtube_test.rs (line 30)
8async fn main() {
9 let config = std::env::var("CLAWSER_CONFIG").unwrap_or_else(|_| {
10 if let Ok(chrome) = std::env::var("CLAWSER_CHROME_PATH") {
11 let dir = std::path::Path::new(&chrome).parent().unwrap_or(std::path::Path::new("."));
12 let cfg = dir.join("test_profile.json");
13 if cfg.exists() { return cfg.to_string_lossy().to_string(); }
14 }
15 "out/Default/test_profile.json".to_string()
16 });
17
18 println!("=== YouTube Headful Test (async) ===\n");
19
20 let browser = Browser::builder().headful().config(&config).build().await
21 .expect("failed to create browser");
22
23 let page = browser.navigate("https://www.youtube.com").await
24 .expect("failed to navigate");
25
26 // Simulate human behavior
27 page.human_idle(1500).await.expect("idle failed");
28 page.scroll(200).await.expect("scroll failed");
29
30 println!("Title: {}", page.js("document.title").await.unwrap_or_default());
31 println!("URL: {}", page.js("window.location.href").await.unwrap_or_default());
32
33 let checks: &[(&str, &str)] = &[
34 ("UA", "navigator.userAgent"),
35 ("Cores", "navigator.hardwareConcurrency.toString()"),
36 ("Memory", "(navigator.deviceMemory||'?').toString()"),
37 ("webdriver", "navigator.webdriver.toString()"),
38 ("Screen", "screen.width+'x'+screen.height"),
39 ("Timezone", "Intl.DateTimeFormat().resolvedOptions().timeZone"),
40 ("GPU", "(function(){var c=document.createElement('canvas');var g=c.getContext('webgl');if(!g)return'no';var d=g.getExtension('WEBGL_debug_renderer_info');return d?g.getParameter(d.UNMASKED_RENDERER_WEBGL):'no'})()"),
41 ];
42 for (name, code) in checks {
43 println!("{}: {}", name, page.js(code).await.unwrap_or_default());
44 }
45
46 browser.shutdown().await.expect("shutdown failed");
47 println!("\nDone.");
48}Auto Trait Implementations§
impl<'b> Freeze for Page<'b>
impl<'b> !RefUnwindSafe for Page<'b>
impl<'b> Send for Page<'b>
impl<'b> Sync for Page<'b>
impl<'b> Unpin for Page<'b>
impl<'b> UnsafeUnpin for Page<'b>
impl<'b> !UnwindSafe for Page<'b>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more