Skip to main content

zendriver_imperva/
lib.rs

1//! Imperva WAF / Incapsula bypass for `zendriver`.
2//!
3//! See the [Imperva chapter](https://turtiesocks.github.io/zendriver-rs/imperva.html)
4//! of the [zendriver-rs user guide](https://turtiesocks.github.io/zendriver-rs/)
5//! for end-to-end usage, surface variants, and CAPTCHA-callback recipes.
6//!
7//! **Stealth required.** Imperva's reese84 sensor is itself a browser
8//! fingerprint check. Run with [`BrowserBuilder::stealth`] enabled or this
9//! bypass will fail on nearly all real Imperva-protected sites.
10//!
11//! # Limitations
12//!
13//! This crate observes the page; it does not modify Imperva's response.
14//! A [`ClearanceOutcome::TokenAcquired`] result means the JS challenge
15//! completed and the `reese84` cookie landed — it does *not* guarantee
16//! the next request will be accepted. Imperva runs a second validation
17//! pass on every request that ships the token; if its scoring of the
18//! fingerprint collected during the challenge falls below threshold,
19//! the next request returns a 403 challenge page with `edet=15` /
20//! `B15(x,y,z)` (general bot protection). Root causes for that are
21//! upstream of this crate:
22//!
23//! - **Browser stealth gaps.** Missing fingerprint shim — canvas,
24//!   audio, WebGL, client hints — leaks "automation" even when the
25//!   challenge JS itself runs to completion.
26//! - **IP reputation.** Residential / datacenter pools flagged at
27//!   the edge return `B15` before the JS challenge runs at all.
28//! - **UA-vs-binary drift.** Claiming Chrome 146 from a Chromium 148
29//!   binary leaks JS-API behavior inconsistent with the claimed
30//!   version.
31//!
32//! If [`ImpervaBypass::wait_for_clearance`] returns `TokenAcquired` but
33//! subsequent requests still hit `edet=15`, look upstream — the
34//! fingerprint the browser emitted is the problem, not the clearance
35//! detection.
36//!
37//! Most users go through `zendriver`'s `Tab::imperva()` (feature-gated)
38//! rather than constructing the bypass directly. The [`ImpervaBypass`]
39//! type is the underlying driver.
40//!
41//! ```no_run
42//! # async fn ex(tab: &zendriver_transport::SessionHandle)
43//! #   -> Result<(), zendriver_imperva::ImpervaError> {
44//! use std::time::Duration;
45//! use zendriver_imperva::{ClearanceOutcome, ImpervaBypass};
46//!
47//! let outcome = ImpervaBypass::new(tab)
48//!     .timeout(Duration::from_secs(30))
49//!     .wait_for_clearance()
50//!     .await?;
51//! match outcome {
52//!     ClearanceOutcome::TokenAcquired { reese84, .. } => {
53//!         println!("token: {reese84}")
54//!     }
55//!     ClearanceOutcome::ChallengeGone => println!("legacy cleared"),
56//!     ClearanceOutcome::AlreadyClear => println!("no challenge present"),
57//!     ClearanceOutcome::TimedOut { last_surface } => {
58//!         println!("timed out; last_surface = {last_surface:?}")
59//!     }
60//! }
61//! # Ok(()) }
62//! ```
63//!
64//! [`BrowserBuilder::stealth`]: https://docs.rs/zendriver/latest/zendriver/struct.BrowserBuilder.html#method.stealth
65
66pub mod bypass;
67pub mod captcha;
68pub mod detection;
69pub mod error;
70mod interception;
71
72pub use bypass::{ClearanceOutcome, ImpervaBypass};
73pub use captcha::{CaptchaChallenge, CaptchaSolution};
74pub use detection::{
75    CaptchaKind, CookieSnapshot, DetectionSnapshot, ImpervaSurface, detect_surface,
76};
77pub use error::ImpervaError;