pub struct IdentitySession { /* private fields */ }Expand description
A rustenium browser session with an identity applied.
Implementations§
Source§impl IdentitySession
impl IdentitySession
Sourcepub async fn launch(
config: impl Into<IdentityConfig>,
) -> Result<Self, IdentityError>
pub async fn launch( config: impl Into<IdentityConfig>, ) -> Result<Self, IdentityError>
Launch a new Chromium instance from the given config. Applies all CDP emulation overrides and registers the stealth bootstrap script before returning.
Examples found in repository?
examples/launch.rs (line 32)
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 23)
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}Sourcepub fn browser(&self) -> &ChromeBrowser
pub fn browser(&self) -> &ChromeBrowser
Access the underlying rustenium ChromeBrowser.
Examples found in repository?
examples/verify.rs (line 27)
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}Sourcepub fn browser_mut(&mut self) -> &mut ChromeBrowser
pub fn browser_mut(&mut self) -> &mut ChromeBrowser
Mutable access to the underlying rustenium ChromeBrowser.
Examples found in repository?
examples/verify.rs (line 35)
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}Sourcepub async fn close(self) -> bool
pub async fn close(self) -> bool
Examples found in repository?
examples/verify.rs (line 75)
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}Auto Trait Implementations§
impl !RefUnwindSafe for IdentitySession
impl !UnwindSafe for IdentitySession
impl Freeze for IdentitySession
impl Send for IdentitySession
impl Sync for IdentitySession
impl Unpin for IdentitySession
impl UnsafeUnpin for IdentitySession
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
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more