pub fn random() -> IdentityExpand description
Return a random preset identity.
Uses a simple entropy source based on the current system time so it requires no extra dependencies.
Examples found in repository?
examples/launch.rs (line 24)
18async fn main() -> Result<(), Box<dyn std::error::Error>> {
19 let identity = match std::env::args().nth(1) {
20 Some(arg) => {
21 let id: u64 = arg.parse()?;
22 preset::get_by_id(id)?
23 }
24 None => preset::random(),
25 };
26
27 println!(
28 "Launching preset #{:?}: {:?} {} / {:?} / {}",
29 identity.id, identity.os, identity.os_version, identity.browser, identity.gpu.webgl_renderer
30 );
31
32 let _session = IdentitySession::launch(identity).await?;
33
34 println!("Browser is up with the identity applied.");
35 println!("Visit a detection site in the opened window (e.g. creepjs / bot.sannysoft.com).");
36 println!("Press Ctrl-C to quit.");
37
38 // Hold the process (and therefore the browser) open until interrupted.
39 tokio::signal::ctrl_c().await?;
40 println!("\nShutting down.");
41 Ok(())
42}More examples
examples/verify.rs (line 15)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13 let identity = match std::env::args().nth(1) {
14 Some(arg) => preset::get_by_id(arg.parse()?)?,
15 None => preset::random(),
16 };
17 let url = std::env::args()
18 .nth(2)
19 .unwrap_or_else(|| "https://abrahamjuliot.github.io/creepjs/".to_string());
20
21 println!("preset #{:?}: {:?} / {:?}", identity.id, identity.os, identity.browser);
22
23 let mut session = IdentitySession::launch(identity).await?;
24 println!("launched, navigating to {url} ...");
25
26 // Collect page errors before anything else runs.
27 session.browser().add_init_script(rustenium::cdp::target_manager::InitScript {
28 page: Some(r#"window.__errs=[];
29 addEventListener('error', e => __errs.push('ERR ' + (e.message||e)));
30 addEventListener('unhandledrejection', e => __errs.push('REJ ' + (e.reason && (e.reason.message||e.reason))));
31 "#.into()),
32 worker: None,
33 }).await;
34
35 session.browser_mut().navigate(&url).await?;
36 println!("navigated; waiting for CreepJS to finish computing");
37
38 // CreepJS takes a while; poll for the widget rather than guessing a duration.
39 let mut rendered = false;
40 for _ in 0..40 {
41 tokio::time::sleep(Duration::from_secs(2)).await;
42 let probe = session
43 .browser_mut()
44 .evaluate_script("!!document.querySelector('.stealth-rating')", false)
45 .await;
46 if let Ok(v) = probe {
47 if format!("{:?}", v).contains("true") {
48 rendered = true;
49 break;
50 }
51 }
52 print!(".");
53 }
54 println!();
55 if !rendered {
56 println!("WARNING: stealth widget never rendered — page may be blocked or hung");
57 }
58 tokio::time::sleep(Duration::from_secs(3)).await;
59
60 let expr = r#"(() => {
61 const pct = (s) => { const e=document.querySelector(s); return e ? (e.textContent.match(/^\s*(\d+%)/)||['','?'])[1] : 'MISSING'; };
62 const flagged = [...document.querySelectorAll('#fingerprint-data span.hash')]
63 .map(e => [e.parentElement.textContent.trim().slice(0,12), e.className.replace('hash','').trim()])
64 .filter(([,c]) => c).map(([n,c]) => n+'='+c);
65 return 'stealth=' + pct('.stealth-rating') + ' headless=' + pct('.headless-rating')
66 + ' hashes=' + document.querySelectorAll('span.hash').length
67 + ' flagged=' + (flagged.join(',') || 'NONE');
68 })()"#;
69
70 match session.browser_mut().evaluate_script(expr, false).await {
71 Ok(v) => println!("\n=== CreepJS ===\n{:?}", v.result.value),
72 Err(e) => println!("\nevaluate failed: {e:?}"),
73 }
74
75 session.close().await;
76 Ok(())
77}