use crate::stealth::profile::{DeviceClass, MediaDeviceInfo, StealthProfile};
fn default_media_devices(seed: &str) -> Vec<MediaDeviceInfo> {
let hash = |s: &str| -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut h = DefaultHasher::new();
s.hash(&mut h);
format!(
"{:016x}{:016x}",
h.finish(),
h.finish().wrapping_mul(0x9e3779b97f4a7c15)
)
};
vec![
MediaDeviceInfo {
device_id: hash(&format!("{}-audio-in", seed)),
kind: "audioinput".into(),
label: "Default".into(),
group_id: hash(&format!("{}-group-a", seed)),
},
MediaDeviceInfo {
device_id: hash(&format!("{}-audio-out", seed)),
kind: "audiooutput".into(),
label: "Default".into(),
group_id: hash(&format!("{}-group-a", seed)),
},
MediaDeviceInfo {
device_id: hash(&format!("{}-video-in", seed)),
kind: "videoinput".into(),
label: "Integrated Camera".into(),
group_id: hash(&format!("{}-group-v", seed)),
},
]
}
pub fn chrome_148_windows() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "Windows".into(),
os_version: "10.0".into(),
platform: "Win32".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
screen_width: 1920,
screen_height: 1080,
screen_avail_width: 1920,
screen_avail_height: 1040,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 1.0,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 0,
webgl_vendor: "Google Inc. (NVIDIA)".into(),
webgl_renderer: "ANGLE (NVIDIA, NVIDIA GeForce RTX 3080 Direct3D11 vs_5_0 ps_5_0, D3D11)".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/New_York".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "15.0.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "chrome_147".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0x1234567890abcdef,
audio_seed: 0xfedcba0987654321,
audio_sample_rate: 44100,
has_platform_authenticator: true,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1920,
inner_height: 969,
outer_width: 1920,
outer_height: 1080,
proxy: None,
media_devices: default_media_devices("win10"),
gpu_profile: crate::stealth::gpu::nvidia_rtx_3060_windows(),
}
}
pub fn chrome_148_macos() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "macOS".into(),
os_version: "15.2".into(),
platform: "MacIntel".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
screen_width: 1512,
screen_height: 982,
screen_avail_width: 1512,
screen_avail_height: 949,
screen_avail_top: 33,
screen_color_depth: 30,
device_pixel_ratio: 2.0,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 0,
webgl_vendor: "Google Inc. (Apple)".into(),
webgl_renderer: "ANGLE (Apple, ANGLE Metal Renderer: Apple M3, Unspecified Version)".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Los_Angeles".into(),
cpu_architecture: "arm".into(),
cpu_bitness: "64".into(),
platform_version: "15.2.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "chrome_147".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0xabcdef1234567890,
audio_seed: 0x0987654321fedcba,
audio_sample_rate: 48000,
has_platform_authenticator: true,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "p3".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1512,
inner_height: 871,
outer_width: 1512,
outer_height: 982,
proxy: None,
media_devices: default_media_devices("macos"),
gpu_profile: crate::stealth::gpu::apple_m3_macos(),
}
}
pub fn chrome_148_linux() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "Linux".into(),
os_version: "6.1".into(),
platform: "Linux x86_64".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
screen_width: 1920,
screen_height: 1080,
screen_avail_width: 1920,
screen_avail_height: 1053,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 1.0,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 0,
webgl_vendor: "Google Inc. (Intel)".into(),
webgl_renderer: "ANGLE (Intel, Mesa Intel(R) UHD Graphics 630 (CFL GT2), OpenGL 4.6)".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Chicago".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "chrome_147".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0x1111222233334444,
audio_seed: 0x5555666677778888,
audio_sample_rate: 44100,
has_platform_authenticator: false,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1920,
inner_height: 969,
outer_width: 1920,
outer_height: 1080,
proxy: None,
media_devices: default_media_devices("linux"),
gpu_profile: crate::stealth::gpu::intel_uhd_630_linux(),
}
}
pub fn chrome_148_ru() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "Windows".into(),
os_version: "10.0".into(),
platform: "Win32".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
screen_width: 1920, screen_height: 1080,
screen_avail_width: 1920, screen_avail_height: 1040,
screen_avail_top: 0,
screen_color_depth: 24, device_pixel_ratio: 1.0,
cpu_cores: 8, device_memory: 8, max_touch_points: 0,
webgl_vendor: "Google Inc. (NVIDIA)".into(),
webgl_renderer: "ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 SUPER Direct3D11 vs_5_0 ps_5_0, D3D11)".into(),
language: "ru-RU".into(),
languages: vec!["ru-RU".into(), "ru".into(), "en-US".into(), "en".into()],
timezone: "Europe/Moscow".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "15.0.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "chrome_147".into(),
connection_effective_type: "4g".into(),
connection_rtt: 100, connection_downlink: 8.0,
pdf_viewer_enabled: true, plugins_count: 5, mime_types_count: 2,
canvas_seed: 0xaaaa_bbbb_cccc_dddd, audio_seed: 0xdddd_cccc_bbbb_aaaa,
audio_sample_rate: 44100,
has_platform_authenticator: true, conditional_mediation: true, allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(), hover_capability: "hover".into(),
inner_width: 1920, inner_height: 969,
outer_width: 1920, outer_height: 1080,
proxy: None,
media_devices: default_media_devices("ru"),
gpu_profile: crate::stealth::gpu::nvidia_rtx_3060_windows(),
}
}
pub fn chrome_148_cn() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "Windows".into(),
os_version: "10.0".into(),
platform: "Win32".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36".into(),
screen_width: 1920, screen_height: 1080,
screen_avail_width: 1920, screen_avail_height: 1040,
screen_avail_top: 0,
screen_color_depth: 24, device_pixel_ratio: 1.25,
cpu_cores: 12, device_memory: 16, max_touch_points: 0,
webgl_vendor: "Google Inc. (NVIDIA)".into(),
webgl_renderer: "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)".into(),
language: "zh-CN".into(),
languages: vec!["zh-CN".into(), "zh".into(), "en-US".into(), "en".into()],
timezone: "Asia/Shanghai".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "15.0.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "chrome_147".into(),
connection_effective_type: "4g".into(),
connection_rtt: 150, connection_downlink: 6.0,
pdf_viewer_enabled: true, plugins_count: 5, mime_types_count: 2,
canvas_seed: 0x1122_3344_5566_7788, audio_seed: 0x8877_6655_4433_2211,
audio_sample_rate: 44100,
has_platform_authenticator: true, conditional_mediation: true, allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(), hover_capability: "hover".into(),
inner_width: 1920, inner_height: 969,
outer_width: 1920, outer_height: 1080,
proxy: None,
media_devices: default_media_devices("cn"),
gpu_profile: crate::stealth::gpu::nvidia_rtx_3060_windows(),
}
}
pub fn chrome_148_de() -> StealthProfile {
let mut p = chrome_148_windows();
p.language = "de-DE".into();
p.languages = vec!["de-DE".into(), "de".into(), "en-US".into(), "en".into()];
p.timezone = "Europe/Berlin".into();
p.canvas_seed = 0xdede_dede_dede_dede;
p.audio_seed = 0xeded_eded_eded_eded;
p
}
pub fn chrome_148_jp() -> StealthProfile {
let mut p = chrome_148_windows();
p.language = "ja-JP".into();
p.languages = vec!["ja".into(), "en-US".into(), "en".into()];
p.timezone = "Asia/Tokyo".into();
p.canvas_seed = 0x0a00_0000_0000_0001;
p.audio_seed = 0x0a00_0000_0000_0002;
p
}
pub fn firefox_135_macos() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14.5; rv:135.0) Gecko/20100101 Firefox/135.0"
.into(),
browser_name: "Firefox".into(),
browser_version: "135.0".into(),
os_name: "macOS".into(),
os_version: "14.5".into(),
platform: "MacIntel".into(),
vendor: "".into(),
vendor_sub: "".into(),
product_sub: "20100101".into(),
app_version: "5.0 (Macintosh; Intel Mac OS X 14.5; rv:135.0) Gecko/20100101 Firefox/135.0"
.into(),
screen_width: 1440,
screen_height: 900,
screen_avail_width: 1440,
screen_avail_height: 875,
screen_avail_top: 25,
screen_color_depth: 30,
device_pixel_ratio: 2.0,
cpu_cores: 10,
device_memory: 16,
max_touch_points: 0,
webgl_vendor: "Mozilla".into(),
webgl_renderer: "Mozilla".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Los_Angeles".into(),
cpu_architecture: "arm".into(),
cpu_bitness: "64".into(),
platform_version: "14.5.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "firefox_135".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0xff0011_ff0022_ff0033_u128 as u64,
audio_seed: 0x88aa_bbcc_ddee_ff00,
audio_sample_rate: 44100,
has_platform_authenticator: true,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "p3".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1440,
inner_height: 789,
outer_width: 1440,
outer_height: 900,
proxy: None,
media_devices: default_media_devices("macos"),
gpu_profile: crate::stealth::gpu::apple_m2_pro_macos(),
}
}
pub fn firefox_135_windows() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0"
.into(),
browser_name: "Firefox".into(),
browser_version: "135.0".into(),
os_name: "Windows".into(),
os_version: "10.0".into(),
platform: "Win32".into(),
vendor: "".into(),
vendor_sub: "".into(),
product_sub: "20100101".into(),
app_version: "5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0"
.into(),
screen_width: 1920,
screen_height: 1080,
screen_avail_width: 1920,
screen_avail_height: 1040,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 1.0,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 0,
webgl_vendor: "Mozilla".into(),
webgl_renderer: "Mozilla".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/New_York".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "15.0.0".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "firefox_135".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0x1122_3344_5566_7788,
audio_seed: 0x99aa_bbcc_ddee_ff00,
audio_sample_rate: 44100,
has_platform_authenticator: true,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1920,
inner_height: 969,
outer_width: 1920,
outer_height: 1080,
proxy: None,
media_devices: default_media_devices("windows"),
gpu_profile: crate::stealth::gpu::nvidia_rtx_3060_windows(),
}
}
pub fn firefox_135_linux() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0".into(),
browser_name: "Firefox".into(),
browser_version: "135.0".into(),
os_name: "Linux".into(),
os_version: "6.1".into(),
platform: "Linux x86_64".into(),
vendor: "".into(),
vendor_sub: "".into(),
product_sub: "20100101".into(),
app_version: "5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0".into(),
screen_width: 1920,
screen_height: 1080,
screen_avail_width: 1920,
screen_avail_height: 1053,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 1.0,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 0,
webgl_vendor: "Mozilla".into(),
webgl_renderer: "Mozilla".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Chicago".into(),
cpu_architecture: "x86".into(),
cpu_bitness: "64".into(),
platform_version: "".into(),
ua_model: "".into(),
ua_wow64: false,
device_class: DeviceClass::Desktop,
tls_impersonate: "firefox_135".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: true,
plugins_count: 5,
mime_types_count: 2,
canvas_seed: 0xaaaa_bbbb_cccc_dddd,
audio_seed: 0xdddd_cccc_bbbb_aaaa,
audio_sample_rate: 44100,
has_platform_authenticator: false,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "fine".into(),
hover_capability: "hover".into(),
inner_width: 1920,
inner_height: 969,
outer_width: 1920,
outer_height: 1080,
proxy: None,
media_devices: default_media_devices("linux"),
gpu_profile: crate::stealth::gpu::intel_uhd_630_linux(),
}
}
pub fn with_locale(
mut base: StealthProfile,
language: &str,
languages: &[&str],
timezone: &str,
) -> StealthProfile {
base.language = language.into();
base.languages = languages.iter().map(|s| s.to_string()).collect();
base.timezone = timezone.into();
base
}
pub fn random_desktop() -> StealthProfile {
use rand::RngExt;
let mut rng = rand::rng();
let mut profile = match rng.random_range(0..3) {
0 => chrome_148_windows(),
1 => chrome_148_macos(),
_ => chrome_148_linux(),
};
profile.canvas_seed = rng.random();
profile.audio_seed = rng.random();
profile
}
pub fn chrome_148_macos_sampled() -> StealthProfile {
chrome_148_macos_sampled_with_rng(&mut rand::rng())
}
pub fn chrome_148_macos_sampled_with_rng(rng: &mut impl rand::RngExt) -> StealthProfile {
let mut p = chrome_148_macos();
type ChipConfig = (
&'static [u8], &'static [u8], &'static [(u32, u32, u32)], crate::stealth::gpu::GpuProfile, );
let chip_idx = rng.random_range(0..3);
let (cores_pool, ram_pool, screens, gpu): ChipConfig = match chip_idx {
0 => (
&[8],
&[8, 16, 24],
&[
(1512, 982, 949), (1728, 1117, 1010), ],
crate::stealth::gpu::apple_m3_macos(),
),
1 => (
&[11, 12],
&[18, 36],
&[
(1800, 1169, 1100), (2056, 1329, 1253), ],
crate::stealth::gpu::apple_m3_pro_macos(),
),
_ => (
&[14, 16],
&[36, 48],
&[
(1800, 1169, 1100), (2056, 1329, 1253), ],
crate::stealth::gpu::apple_m3_max_macos(),
),
};
p.cpu_cores = cores_pool[rng.random_range(0..cores_pool.len())];
p.device_memory = ram_pool[rng.random_range(0..ram_pool.len())];
let (w, h, ah) = screens[rng.random_range(0..screens.len())];
p.screen_width = w;
p.screen_height = h;
p.screen_avail_width = w;
p.screen_avail_height = ah;
p.inner_width = w;
p.inner_height = h.saturating_sub(111);
p.outer_width = w;
p.outer_height = h;
p.gpu_profile = gpu;
p.webgl_renderer = p.gpu_profile.unmasked_renderer.clone();
p.canvas_seed = rng.random();
p.audio_seed = rng.random();
debug_assert!(
p.validate().is_ok(),
"chrome_148_macos_sampled produced an invalid profile: {:?}",
p.validate()
);
p
}
pub fn pixel_9_pro_chrome_148() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (Linux; Android 15; Pixel 9 Pro Build/AP4A.250105.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Mobile Safari/537.36".into(),
browser_name: "Chrome".into(),
browser_version: "148.0.7778.168".into(),
os_name: "Android".into(),
os_version: "15".into(),
platform: "Linux armv81".into(),
vendor: "Google Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (Linux; Android 15; Pixel 9 Pro Build/AP4A.250105.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Mobile Safari/537.36".into(),
screen_width: 412,
screen_height: 870,
screen_avail_width: 412,
screen_avail_height: 870,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 2.625,
cpu_cores: 8,
device_memory: 8,
max_touch_points: 5,
webgl_vendor: "Google Inc. (Google)".into(),
webgl_renderer: "ANGLE (Google, Mali-G715 MP7, OpenGL ES 3.2)".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Los_Angeles".into(),
cpu_architecture: "".into(),
cpu_bitness: "64".into(),
platform_version: "15.0.0".into(),
ua_model: "Pixel 9 Pro".into(),
ua_wow64: false,
device_class: DeviceClass::MobileAndroid,
tls_impersonate: "chrome_147_android".into(),
connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: false,
plugins_count: 0,
mime_types_count: 0,
canvas_seed: 0xa5a5_d5d5_3c3c_e6e6,
audio_seed: 0x9c9c_5e5e_4040_b1b1,
audio_sample_rate: 44100,
has_platform_authenticator: false,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "srgb".into(),
pointer_type: "coarse".into(),
hover_capability: "none".into(),
inner_width: 412,
inner_height: 870,
outer_width: 412,
outer_height: 870,
proxy: None,
media_devices: default_media_devices("android"),
gpu_profile: crate::stealth::gpu::apple_m3_macos(), }
}
pub fn iphone_15_pro_safari_18() -> StealthProfile {
StealthProfile {
enforce_csp: true,
user_agent: "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Mobile/15E148 Safari/604.1".into(),
browser_name: "Safari".into(),
browser_version: "18.0.1".into(),
os_name: "iOS".into(),
os_version: "18.0.1".into(),
platform: "iPhone".into(),
vendor: "Apple Computer, Inc.".into(),
vendor_sub: "".into(),
product_sub: "20030107".into(),
app_version: "5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Mobile/15E148 Safari/604.1".into(),
screen_width: 393,
screen_height: 852,
screen_avail_width: 393,
screen_avail_height: 852,
screen_avail_top: 0,
screen_color_depth: 24,
device_pixel_ratio: 3.0,
cpu_cores: 2,
device_memory: 0,
max_touch_points: 5,
webgl_vendor: "Apple Inc.".into(),
webgl_renderer: "Apple GPU".into(),
language: "en-US".into(),
languages: vec!["en-US".into(), "en".into()],
timezone: "America/Los_Angeles".into(),
cpu_architecture: "arm".into(),
cpu_bitness: "64".into(),
platform_version: "18.0.1".into(),
ua_model: "iPhone".into(),
ua_wow64: false,
device_class: DeviceClass::MobileIOS,
tls_impersonate: "safari_18_ios".into(), connection_effective_type: "4g".into(),
connection_rtt: 50,
connection_downlink: 10.0,
pdf_viewer_enabled: false,
plugins_count: 0,
mime_types_count: 0,
canvas_seed: 0xa1b2_c3d4_e5f6_0708,
audio_seed: 0x0807_0605_0403_0201,
audio_sample_rate: 44100,
has_platform_authenticator: false,
conditional_mediation: true,
allow_http3: false,
prefers_color_scheme: "light".into(),
color_gamut: "p3".into(),
pointer_type: "coarse".into(),
hover_capability: "none".into(),
inner_width: 393,
inner_height: 852,
outer_width: 393,
outer_height: 852,
proxy: None,
media_devices: default_media_devices("ios"),
gpu_profile: crate::stealth::gpu::apple_m3_macos(), }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chrome_148_windows_validates() {
let profile = chrome_148_windows();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
}
#[test]
fn http3_disabled_by_default_on_all_presets() {
for profile in [
chrome_148_windows(),
chrome_148_macos(),
chrome_148_linux(),
chrome_148_ru(),
chrome_148_cn(),
chrome_148_de(),
chrome_148_jp(),
firefox_135_macos(),
firefox_135_windows(),
firefox_135_linux(),
] {
assert!(
!profile.allow_http3,
"Profile {} sets allow_http3=true, which is not supported",
profile.user_agent
);
}
}
#[test]
fn chrome_148_macos_validates() {
let profile = chrome_148_macos();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
}
#[test]
fn chrome_148_linux_validates() {
let profile = chrome_148_linux();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
}
#[test]
fn firefox_135_macos_validates() {
let profile = firefox_135_macos();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
assert_eq!(profile.browser_name, "Firefox");
assert_eq!(profile.vendor, "");
assert_eq!(profile.product_sub, "20100101");
assert!(profile.user_agent.contains("rv:135.0"));
assert!(profile.user_agent.contains("Firefox/135.0"));
assert!(!profile.user_agent.contains("Chrome"));
assert_eq!(profile.tls_impersonate, "firefox_135");
}
#[test]
fn firefox_135_windows_validates() {
let profile = firefox_135_windows();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
assert!(profile.user_agent.contains("Windows NT 10.0"));
assert!(profile.user_agent.contains("Firefox/135.0"));
}
#[test]
fn firefox_135_linux_validates() {
let profile = firefox_135_linux();
assert!(profile.validate().is_ok(), "{:?}", profile.validate());
assert!(profile.user_agent.contains("X11; Linux x86_64"));
assert!(profile.user_agent.contains("Firefox/135.0"));
}
#[test]
fn firefox_webgl_is_masked() {
for profile in [
firefox_135_macos(),
firefox_135_windows(),
firefox_135_linux(),
] {
assert_eq!(profile.webgl_vendor, "Mozilla");
assert_eq!(profile.webgl_renderer, "Mozilla");
}
}
#[test]
fn random_desktop_validates() {
for _ in 0..10 {
let profile = random_desktop();
assert!(profile.validate().is_ok());
}
}
#[test]
fn invalid_profile_detected() {
let mut profile = chrome_148_windows();
profile.platform = "MacIntel".into(); assert!(profile.validate().is_err());
}
#[test]
fn invalid_gpu_os_mismatch() {
let mut profile = chrome_148_windows();
profile.webgl_renderer =
"ANGLE (Apple, ANGLE Metal Renderer: Apple M2, Unspecified Version)".into();
profile.webgl_vendor = "Google Inc. (Apple)".into();
assert!(profile.validate().is_err());
}
#[test]
fn webdriver_not_in_profile() {
let profile = chrome_148_windows();
assert!(!profile.user_agent.contains("webdriver"));
}
#[test]
fn ua_contains_version() {
let profile = chrome_148_windows();
assert!(profile.user_agent.contains("148.0.0.0"));
assert_eq!(profile.browser_version, "148.0.7778.168");
}
#[test]
fn serialization_roundtrip() {
let profile = chrome_148_windows();
let json = serde_json::to_string(&profile).unwrap();
let deserialized: StealthProfile = serde_json::from_str(&json).unwrap();
assert_eq!(profile.user_agent, deserialized.user_agent);
assert_eq!(profile.screen_width, deserialized.screen_width);
}
#[test]
fn macos_sampler_produces_valid_profiles() {
for _ in 0..200 {
let p = chrome_148_macos_sampled();
p.validate()
.unwrap_or_else(|e| panic!("invalid sampled profile: {e:?}"));
assert!(
matches!(p.screen_width, 1512 | 1728 | 1800 | 2056),
"screen_width {} not in M3-family pool",
p.screen_width
);
assert!(
matches!(p.cpu_cores, 8 | 11 | 12 | 14 | 16),
"cpu_cores {} not in M3-family pool",
p.cpu_cores
);
assert!(
matches!(p.device_memory, 8 | 16 | 18 | 24 | 36 | 48),
"device_memory {} not in M3-family pool",
p.device_memory
);
assert_eq!(p.device_pixel_ratio, 2.0);
assert_eq!(p.audio_sample_rate, 48000);
assert_eq!(p.cpu_architecture, "arm");
assert_eq!(p.platform, "MacIntel");
assert_eq!(p.inner_height + 111, p.screen_height);
}
}
#[test]
fn macos_sampler_produces_diverse_fingerprints() {
use std::collections::HashSet;
let mut chips = HashSet::new();
let mut tuples = HashSet::new();
let mut seeds = HashSet::new();
for _ in 0..30 {
let p = chrome_148_macos_sampled();
chips.insert(p.cpu_cores);
tuples.insert((p.screen_width, p.cpu_cores, p.device_memory));
seeds.insert(p.canvas_seed);
seeds.insert(p.audio_seed);
}
assert!(
chips.len() >= 3,
"expected ≥3 distinct cpu_cores values in 30 samples (M3/Pro/Max), got {chips:?}"
);
assert!(
tuples.len() >= 6,
"expected ≥6 distinct (screen, cores, mem) tuples in 30 samples, got {}: {tuples:?}",
tuples.len()
);
assert!(
seeds.len() >= 58,
"canvas/audio seeds should be near-fully-distinct, got {} unique of 60",
seeds.len()
);
}
#[test]
fn macos_sampler_keeps_per_chip_cross_api_consistency() {
for _ in 0..50 {
let p = chrome_148_macos_sampled();
let r = &p.gpu_profile.unmasked_renderer;
match p.cpu_cores {
8 => {
assert!(
r.contains("Apple M3,"),
"8 cores must pair with 'Apple M3' renderer; got '{r}'"
);
assert!(matches!(p.device_memory, 8 | 16 | 24));
}
11 | 12 => {
assert!(
r.contains("Apple M3 Pro"),
"11-12 cores must pair with 'Apple M3 Pro' renderer; got '{r}'"
);
assert!(matches!(p.device_memory, 18 | 36));
}
14 | 16 => {
assert!(
r.contains("Apple M3 Max"),
"14-16 cores must pair with 'Apple M3 Max' renderer; got '{r}'"
);
assert!(matches!(p.device_memory, 36 | 48));
}
other => panic!("unexpected cpu_cores {other} from sampler"),
}
assert_eq!(p.webgl_renderer, *r);
}
}
}