#![deny(missing_docs)]
pub mod bounded_fetch;
pub mod browser;
pub mod cdp;
pub mod download;
pub mod element;
pub mod error;
pub mod fetch;
mod keyboard;
pub mod network;
pub mod page;
pub mod session;
pub mod stealth;
#[allow(dead_code)]
const _: () = {
fn assert_send_sync<T: Send + Sync>() {}
fn _assertions() {
assert_send_sync::<browser::Browser>();
assert_send_sync::<page::Page>();
}
};
pub use bounded_fetch::{BoundedFetchRequest, BoundedFetchResponse, MAX_TEXT_FETCH_BYTES};
pub use browser::{Browser, TabInfo};
pub use download::{
DownloadBeginning, DownloadEvent, DownloadProgress, DownloadWatch, NativeDownloadState,
};
pub use element::{BoundingBox, Element};
pub use error::{Error, Result};
pub use fetch::{BrowserFetchOutcome, BrowserFetchRequest, BrowserFetchResponse};
pub use network::{NetworkEvent, NetworkWatcher};
pub use page::{
CaptureBodyError, CapturedFrameResponse, FrameResponseCapture, FrameResponseCaptureOptions,
FrameResponseCaptureReport,
};
pub use page::{CapturedRequest, FrameInfo, MouseButton, Page, PageState, ResponseBody, TextMatch};
pub use session::{BrowserSession, BrowserState, SessionCookie};
pub use stealth::{Fingerprint, HumanSpeed};
#[derive(Debug, Clone)]
pub struct StealthConfig {
pub webgl_spoof: bool,
pub canvas_spoof: bool,
pub audio_spoof: bool,
pub human_mouse: bool,
pub human_typing: bool,
pub user_agent: Option<String>,
pub headless: bool,
pub chrome_path: Option<String>,
pub patch_binary: bool,
pub viewport_width: u32,
pub viewport_height: u32,
pub debug: bool,
pub debug_dir: Option<String>,
pub proxy: Option<String>,
pub user_data_dir: Option<String>,
pub profile_dir: Option<String>,
pub proxy_username: Option<String>,
pub proxy_password: Option<String>,
pub cdp_timeout: u64,
pub timezone: Option<String>,
pub extra_args: Vec<String>,
pub aggressive_cdp_evasion: bool,
pub live_session: bool,
pub filter_cdp: bool,
pub ignore_cert_errors: bool,
pub strip_x_client_data: bool,
pub geo_align: bool,
}
impl Default for StealthConfig {
fn default() -> Self {
Self {
webgl_spoof: true,
canvas_spoof: true,
audio_spoof: true,
human_mouse: true,
human_typing: true,
user_agent: None,
headless: true,
chrome_path: None,
patch_binary: true,
viewport_width: 1920,
viewport_height: 1080,
debug: false,
debug_dir: None,
proxy: None,
user_data_dir: None,
profile_dir: None,
proxy_username: None,
proxy_password: None,
cdp_timeout: 30,
timezone: None, extra_args: Vec::new(),
aggressive_cdp_evasion: false,
live_session: false,
filter_cdp: true,
ignore_cert_errors: false,
strip_x_client_data: true,
geo_align: false,
}
}
}
impl StealthConfig {
pub fn minimal() -> Self {
Self {
webgl_spoof: false,
canvas_spoof: false,
audio_spoof: false,
human_mouse: false,
human_typing: false,
headless: false,
patch_binary: false,
..Default::default()
}
}
pub fn visible() -> Self {
Self {
headless: false,
..Default::default()
}
}
pub fn debug() -> Self {
Self {
headless: false,
debug: true,
..Default::default()
}
}
pub fn live() -> Self {
Self {
live_session: true,
filter_cdp: false,
patch_binary: false,
webgl_spoof: false,
canvas_spoof: false,
audio_spoof: false,
human_mouse: true,
human_typing: true,
..Default::default()
}
}
}
#[cfg(test)]
mod tests {
use super::StealthConfig;
#[test]
fn default_config_is_headless() {
assert!(StealthConfig::default().headless);
}
#[test]
fn visible_configs_are_explicitly_not_headless() {
assert!(!StealthConfig::visible().headless);
assert!(!StealthConfig::debug().headless);
}
}