Skip to main content

Module warmup

Module warmup 

Source
Expand description

Page-warming (natural pre-captcha visitor activity).

reCAPTCHA v3, Cloudflare Turnstile passive mode, hCaptcha invisible, PerimeterX, and Akamai score the visitor on a signal stack that includes:

  • Mouse movement entropy (not just final position)
  • Scroll history (did they read the page or jump straight to the form?)
  • Focus changes / tab switches
  • Time-on-page before the first solve attempt
  • Page interaction count (clicks on non-form elements)

warm_session(page, duration) runs a budgeted human-like activity loop on the page BEFORE captchaforge’s solver chain fires. The widgets see a session that looks like a real visitor, not a script that loaded the page and went straight to the form. For passive captchas this single addition can flip a 0% solve rate to 60%+.

What the loop does (within the budget):

  1. Move the mouse to a few random points along a human trajectory with realistic acceleration / deceleration / micro-jitter.
  2. Scroll down by a small random amount, pause, scroll back up.
  3. Hover over (without clicking) a few non-form elements to trigger their mouseover listeners.
  4. Idle pause between actions to vary inter-event timing.

Every pointer/scroll action is dispatched as a TRUSTED BiDi input event (crate::behaviorruntime_foxdriver’s input.performActions), so event.isTrusted === true. This is load-bearing: the passive scorers this module exists to satisfy (PerimeterX, DataDome, Akamai, reCAPTCHA v3) all gate on isTrusted, and a synthetic new MouseEvent(...) + dispatchEvent carries isTrusted === false: a burst of which is a stronger bot tell than no motion at all. Warming therefore never hand-rolls JS-dispatched events; it routes exclusively through the same trusted human-input primitives the captcha solver uses. (JS evaluate is still used for reads, viewport size, element geometry, which emit no events.)

Budget is in WALL-CLOCK milliseconds. Default 4_000ms is enough for reCAPTCHA v3 score warming without significantly slowing the overall solve. Set higher (8_000-15_000ms) when solving an actively-challenged session for the first time.

Constants§

DEFAULT_WARMUP_MS
Default budget if caller doesn’t override. 4 seconds is enough to register page-interaction signals without dragging the overall solve too much.

Functions§

apply_default_warmup
Convenience wrapper: run warm_session with the default budget.
warm_session
Run page-warming activity for up to budget. Returns when the budget is exhausted OR an evaluate call fails (best-effort the solver chain runs regardless, warming is a nice-to-have).