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):
- Move the mouse to a few random points along a human trajectory with realistic acceleration / deceleration / micro-jitter.
- Scroll down by a small random amount, pause, scroll back up.
- Hover over (without clicking) a few non-form elements to
trigger their
mouseoverlisteners. - Idle pause between actions to vary inter-event timing.
Every pointer/scroll action is dispatched as a TRUSTED BiDi input event
(crate::behavior → runtime_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_sessionwith 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).