From bab58991fea7471e68fff28af661e52045eaed4b Mon Sep 17 00:00:00 2001 From: leeguooooo Date: Thu, 11 Jun 2026 19:29:49 +0900 Subject: [PATCH] feat(stealth): adaptive anti-bot detection drives humanize level (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After each navigation, probe the loaded page for known behavioural anti-bot vendor fingerprints — cookies (_abck/Akamai, _px/PerimeterX, datadome, reese84/Imperva, …), script URLs, and window globals — and escalate this session to HumanizeLevel::Human when one is present, else fall back to the Off baseline. So ordinary sites run at full speed (instant clicks) and only pages actually guarded by behavioural detection pay for human-like motion. `AGENT_BROWSER_HUMANIZE` still forces a fixed level and short-circuits the probe. Best-effort: a failed probe leaves the level unchanged. Verified end-to-end (headless --launch): a HUMANIZE=human click on example.com traverses the curved trajectory and lands correctly (→ iana.org), identical outcome to Off. --- cli/src/native/actions.rs | 45 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/cli/src/native/actions.rs b/cli/src/native/actions.rs index cfa3f8e..355d623 100644 --- a/cli/src/native/actions.rs +++ b/cli/src/native/actions.rs @@ -23,6 +23,7 @@ use super::cdp::types::{ use super::cookies; use super::diff; use super::element::RefMap; +use super::humanize; use super::inspect_server::InspectServer; use super::interaction; use super::network::{self, DomainFilter, EventTracker}; @@ -2512,7 +2513,49 @@ async fn handle_navigate(cmd: &Value, state: &mut DaemonState) -> Result { try { + const cookies = document.cookie.split(';').map(c => c.trim().split('=')[0]).filter(Boolean); + const scripts = Array.from(document.scripts, s => s.src || '').filter(Boolean); + const re = /_px|bmak|_abck|datadome|reese84|kpsdk|incap_ses|visid_incap|akam/i; + const globals = Object.getOwnPropertyNames(window).filter(k => re.test(k)); + return { cookies, scripts, globals }; + } catch (e) { return {}; } })()"#; + let Ok(val) = mgr.evaluate(js, None).await else { + return; + }; + let to_strings = |v: Option<&Value>| -> Vec { + v.and_then(|v| v.as_array()) + .map(|a| { + a.iter() + .filter_map(|x| x.as_str().map(String::from)) + .collect() + }) + .unwrap_or_default() + }; + let signals = humanize::DetectSignals { + cookie_names: to_strings(val.get("cookies")), + script_urls: to_strings(val.get("scripts")), + window_globals: to_strings(val.get("globals")), + }; + let level = humanize::detect_level(&signals, humanize::HumanizeLevel::Off); + humanize::set_detected_level(level); } async fn handle_url(state: &DaemonState) -> Result {