凯迪浏览器

指纹能力与配置参考

控制端只需要做两件事:把一份 fp.json 放到约定位置(或用参数指定路径), 启动时带上对应开关。渲染进程与网络进程不需要额外处理 —— 浏览器进程会把配置转发给所有子进程。

命令行开关

开关作用域说明
--user-data-dir=<目录>浏览器进程 必填。该实例的数据目录。一个目录 = 一个实例;不同实例之间 Cookie、缓存、扩展完全隔离。
--fingerprint-profile=<名字>仅浏览器进程 按名字加载配置,解析为 <user-data-dir>/profiles/<名字>/fp.json。必须同时给 --user-data-dir。
--fingerprint-config-path=<绝对路径>仅浏览器进程 直接指定配置文件绝对路径,适合配置集中管理。优先级高于 --fingerprint-profile。
--fingerprint-debug浏览器 + 子进程 打印加载日志(来源、进程类型、pid、enabled、profile、preset、seed、UA、完整 JSON)。排错时加。
--fp-config=<base64>仅子进程 内部开关,请勿手工设置。由浏览器进程在启动子进程时自动追加。

加载优先级(进程启动时一次性决定,之后只读)

优先级从高到低
1. --fp-config=<base64>              子进程;由浏览器进程传播
2. --fingerprint-config-path=<路径>   浏览器进程;显式指定文件
3. --fingerprint-profile=<名字>      浏览器进程;<user-data-dir>/profiles/<名字>/fp.json
4. 三个都没给                        指纹功能关闭,全部走原生 Chromium 值
改了 fp.json 必须重启浏览器进程。配置在进程启动早期读取一次,运行期改文件不生效。

配置文件语义

字段全表

共 84 项。未列出的字段名会被忽略。数值型字段的 0 / 空串 / 空数组表示不覆盖。

元信息

字段类型默认说明
enabledboolfalse总开关。必须显式写 true,否则后面所有字段都不生效。
profile_namestring""仅用于日志记录。
presetstring""仅日志字段,不驱动任何行为。写了名字并不会自动填好整套配置。
seedstring""噪声种子,十进制无符号整数的字符串形式,如 "9021073948172635401"。 所有噪声都由它派生。写成 JSON 数字会被忽略,开了噪声就会报错。

L1 — navigator 与 JS 表面

字段类型默认说明
user_agentstring""navigator.userAgent,同时是 UA-CH 的推导基线。
ua_platformstring""UA-CH 的 platform,如 Windows / macOS。
ua_platform_versionstring""10.0.0(Win10)/ 15.0.0(Win11)等。
ua_architecturestring""x86 / arm。
ua_bitnessstring""64 / 32。
ua_modelstring""桌面端留空。
ua_full_versionstring""如 146.0.7680.252。
ua_brandsstring[][]Sec-CH-UA 品牌列表。两种写法:"Brand"(版本取主版本)或 "Brand/版本"。整段省略最安全。
ua_mobileboolfalse
ua_wow64boolfalse
platformstring""navigator.platform,如 Win32 / MacIntel。
hardware_concurrencyint0navigator.hardwareConcurrency。
device_memorydouble0navigator.deviceMemory(GB)。
max_touch_pointsint-1navigator.maxTouchPoints。-1 表示原生。
webdriverboolfalsenavigator.webdriver。
languagesstring[][]顺序有意义,如 ["zh-CN","zh","en"]。
accept_languagestring""Accept-Language 请求头。
pluginsobject[][]navigator.plugins / mimeTypes。留空用原生列表。结构见下方说明。
connection_effective_typestring""slow-2g / 2g / 3g / 4g。
connection_typestring""wifi / ethernet / cellular / bluetooth / wimax / none / other / unknown。
需要启动时加 --enable-blink-features=NetInfoDownlinkMax 才可读,否则该属性为 undefined。
connection_rttint0毫秒。
connection_downlinkdouble0Mbps。
connection_save_databoolfalse
timezonestring""IANA 名,必须含 /,如 Asia/Shanghai。
timezone_offset_minutesint0与 timezone 相差的分钟数。
screen_width / screen_heightint0必须成对设置。
screen_avail_width / screen_avail_heightint0不得大于对应的 screen 尺寸。
screen_avail_left / screen_avail_topint0任务栏偏移。
screen_color_depthint0通常 24。
screen_pixel_depthint0通常 24。
device_pixel_ratiodouble0如 1 / 1.25 / 1.5。
window_outer_width / window_outer_heightint0窗口外尺寸。
storage_quotaint640存储配额(字节)。0 = 原生;否则须落在 [1 MiB, 1 PiB] 区间内。

plugins 的结构

plugins 数组元素
"plugins": [
  {
    "name": "Chrome PDF Viewer",
    "filename": "internal-pdf-viewer",
    "description": "Portable Document Format",
    "mime_types": [
      { "type": "application/pdf", "description": "Portable Document Format", "suffixes": "pdf" }
    ]
  }
]

name 不能为空(校验会拒绝)。不写 mime_types 即为空数组。整个数组留空则使用原生列表。

L2 — 图形(canvas / WebGL / WebAudio)

字段类型默认说明
canvas_noiseboolfalse开启 canvas 像素噪声。
canvas_noise_strengthdouble0须 > 0。只动 alpha 低 4 位,肉眼不可见。
webgl_noiseboolfalse开启 WebGL 参数扰动。
webgl_vendorstring""如 Google Inc. (NVIDIA)。
webgl_rendererstring""如 ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 Direct3D11 vs_5_0 ps_5_0, D3D11)。必须与 UA 的 OS 家族自洽。
webgl_extensionsstring[][]留空 = 原生扩展列表。
webgl_presetstring""GPU 能力档位名,覆盖 getParameter() 的一批数值上限,使其与 vendor / renderer 自洽。未知名字会被拒绝。
audio_noiseboolfalse开启 WebAudio 噪声(AnalyserNode / AudioBuffer)。
audio_noise_strengthdouble0须 > 0。

L2b — WebGPU

字段类型默认说明
webgpu_presetstring""GPU 档位名,与 webgl_preset 用同一张表。未知名字会被拒绝。
webgpu_vendorstring""必须与 webgpu_description 成对设置;且不能与 webgl_renderer 的 GPU 家族矛盾。
webgpu_descriptionstring""适配器描述,与 vendor 成对。
webgpu_architecturestring""适配器架构字符串。不做交叉校验,请自行与所选档位保持一致。
webgpu_devicestring""PCI 设备号,必须是 0x 开头的十六进制,如 "0x2482"。
webgpu_driverstring""驱动信息字符串。
部分 GPU 环境下 GPUAdapterInfo 的某些属性(device / description / driver)本身不对外暴露, 配了值也可能读不到。上线前建议用下面的自检方式在目标机器上实测一次。

L2+ — 排版与字体

字段类型默认说明
font_whiteliststring[][]允许被探测到的字体白名单。
font_block_unknownboolfalse白名单之外的字体一律视为不存在。
font_metrics_noiseboolfalse对 getBoundingClientRect() / getClientRects() 加亚像素抖动。
font_metrics_strengthdouble0取值区间 (0, 1]。1.0 约 ±3 CSS px,0.5 约 ±1.5 px。写 1.5 会被拒绝。

A6 — 权限状态

字段类型默认说明
permission_geolocationstring""granted / denied / prompt。空 = 不覆盖。
permission_notificationsstring""同上。
permission_camerastring""同上。
permission_microphonestring""同上。
建议不要把四项填成同一个值。真实用户通常是 notifications 已有明确答案、camera 仍是 prompt; 整齐划一反而更显眼。

L3 — 网络

字段类型默认说明
tls_presetstring""BoringSSL 密码套件档位,影响 JA3 / JA4。合法名见预设名。
注意:未知名字不报错,会静默回落到上游默认列表。
http2_presetstring""HTTP/2 SETTINGS 帧档位。合法名见预设名。
http_header_orderstring[][]HTTP 请求头顺序。
proxy_serverstring""代理地址,如 http://127.0.0.1:7890、https://…、socks5://127.0.0.1:1080。
proxy_bypassstring""绕过列表,分号分隔。
proxy_usernamestring""代理用户名。请用这个字段,不要把凭据写进代理 URL。
proxy_passwordstring""代理密码。SOCKS5 下用户名/密码各不超过 255 字节(RFC 1929 的长度字段是单字节)。
proxy_auth_realmstring""认证 realm。必须与目标代理实际返回的 407 realm 一致,否则认证不会生效。
proxy_auth_schemestring""认证方案,只能取 6 个全小写值:basic / digest / ntlm / negotiate / spdyproxy / mock。

L4 — 硬件、媒体与传感器

字段类型默认说明
block_webrtc_local_ipbooltrue阻断 WebRTC 暴露本机内网 IP。默认就是开启的,要放开须显式写 false。
spoof_media_devicesboolfalse伪造 enumerateDevices() 结果。
media_device_countint0伪造的设备数量。
spoof_geolocationboolfalse开启地理位置伪造。开启后下面几项才参与校验。
geo_latitudedouble0范围 [-90, 90]。
geo_longitudedouble0范围 [-180, 180]。
geo_accuracydouble0必须 > 0。
geo_altitudedouble-10000米。默认值表示 JS 侧为 null。合法区间 [-500, 9000]。
geo_altitude_accuracydouble-1米。负值表示 null,上限 1000。
geo_headingdouble-1度。负值或 > 360 表示 null。
geo_speeddouble-1米/秒。负值表示 null,上限 300。

预设名

写错名字的后果因字段而异,这点很容易踩:webgl_preset / webgpu_preset 写错会被拒绝,而 tls_preset 写错会静默回落到上游默认 —— 看起来"生效了",其实没有。

webgl_preset / webgpu_preset(同一张表,共 8 个)

名字对应 GPU
nvidia_gtx1660_winNVIDIA GeForce GTX 1660 / Windows
nvidia_rtx3070_winNVIDIA GeForce RTX 3070 / Windows
intel_hd630_winIntel HD 630 / Windows
apple_m1_macApple M1 / macOS
apple_m2_macApple M2 / macOS
mali_g78_androidARM Mali-G78 / Android
adreno_740_androidQualcomm Adreno 740 / Android
mesa_llvmpipe_linuxMesa llvmpipe / Linux

tls_preset

名字效果
""(空)上游 Chromium 默认密码套件列表
chrome_132_win、chrome_146_win / _mac / _linux与原生列表一致(等价于不设)
chrome_131_winChrome 120–131 档:切换 ALPS 扩展码点至 17513,ja4_c = 02713d6af862
chrome_136_winChrome 133–136 档:切换 ALPS 扩展码点至 17613,ja4_c = d8a2da3f94cd
firefox_132_winFirefox 132 Windows 密码套件顺序(17 套)
firefox_120_winFirefox 120 Windows 密码套件顺序(14 套)
safari_17_macSafari 17 macOS 密码套件顺序(11 套)
Chrome 家族档位的密码套件列表跨版本完全相同,两档的差异在 ALPS 扩展码点。 因此没有必要按 129 / 130 / 131…… 逐版铺档位 —— 那等于伪造现实中不存在的指纹。

http2_preset

名字HEADER_TABLE_SIZEINITIAL_WINDOW_SIZEMAX_HEADER_LIST_SIZE
chrome_146_* / 空原生,不改
firefox_132_win6553613107265536
firefox_120_win655366553565536
safari_17_mac4096419430465536

校验规则

校验是全有或全无:任何一条不过,整份配置作废并回落到原生 Chromium。以下组合会被拒绝。

#会被拒绝的情况
1webgl_renderer 与 user_agent 的 OS 家族不匹配(Windows UA 的 renderer 须含 ANGLE / D3D / Direct3D / SwiftShader / Google Inc.;macOS 须含 Apple / Metal / Intel;Linux 须含 Mesa / llvmpipe / NVIDIA / Intel;Android 须含 Adreno / Mali / PowerVR / Qualcomm 等)
2permission_* 写了 granted / denied / prompt 之外的值
3开了任一项噪声,但 seed 为 0 或缺失
4开了噪声但强度为 0;font_metrics_strength 不在 (0, 1]
5screen_width 与 screen_height 只写了一个
6screen_avail_width / screen_avail_height 大于对应 screen 尺寸
7timezone 不含 /
8connection_effective_type 不是 slow-2g / 2g / 3g / 4g,或 connection_type 不是合法词元
9连接参数自相矛盾(例如 effectiveType=4g 却 downlink=0.1)
10plugins[].name 为空
11geo_* 越界(纬度 [-90,90]、经度 [-180,180]、accuracy > 0、altitude ∈ [-500,9000]、altitude_accuracy ≤ 1000、heading ∈ [0,360]、speed ≤ 300)
12webgl_preset / webgpu_preset 写了不认识的名字
13webgpu_vendor 与 webgpu_description 只写了一个
14webgpu_vendor 声称的 GPU 厂商与 webgl_renderer 矛盾
15webgpu_device 不是 0x 开头的十六进制串
16storage_quota 非 0 且不在 [1 MiB, 1 PiB] 内
17ua_brands 里的品牌主版本与 ua_full_version 矛盾(GREASE 品牌须用 Not? 或 Not. 前缀)
18proxy_auth_scheme 不是那 6 个全小写合法值之一
设计意图:宁可回落成"干净的、真实一致的原生浏览器",也不产出"自相矛盾的假指纹"——后者比不伪装更容易被识别。

完整示例

下面是一份可以直接复制使用的 Windows / 美国时区配置。完整字段版见随程序附带的 fp.example.json。

fp.json
{
  "enabled": true,
  "profile_name": "example-win10-us",
  "seed": "9021073948172635401",

  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
  "ua_platform": "Windows",
  "ua_platform_version": "10.0.0",
  "ua_architecture": "x86",
  "ua_bitness": "64",
  "ua_full_version": "146.0.7680.252",

  "platform": "Win32",
  "hardware_concurrency": 8,
  "device_memory": 8,
  "max_touch_points": 0,
  "webdriver": false,
  "languages": ["en-US", "en"],
  "accept_language": "en-US,en;q=0.9",

  "connection_effective_type": "4g",
  "connection_type": "wifi",
  "connection_rtt": 50,
  "connection_downlink": 10,

  "timezone": "America/New_York",
  "timezone_offset_minutes": -300,

  "screen_width": 1366,
  "screen_height": 768,
  "screen_avail_width": 1366,
  "screen_avail_height": 728,
  "screen_color_depth": 24,
  "screen_pixel_depth": 24,
  "device_pixel_ratio": 1,

  "canvas_noise": true,
  "canvas_noise_strength": 0.6,
  "webgl_noise": true,
  "webgl_vendor": "Google Inc. (NVIDIA)",
  "webgl_renderer": "ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 Direct3D11 vs_5_0 ps_5_0, D3D11)",
  "webgl_preset": "nvidia_gtx1660_win",
  "audio_noise": true,
  "audio_noise_strength": 0.4,

  "font_metrics_noise": true,
  "font_metrics_strength": 0.5,

  "permission_geolocation": "prompt",
  "permission_notifications": "granted",
  "permission_camera": "prompt",
  "permission_microphone": "prompt",

  "tls_preset": "chrome_146_win",
  "http2_preset": "chrome_146_win",

  "block_webrtc_local_ip": true,
  "spoof_geolocation": true,
  "geo_latitude": 40.7128,
  "geo_longitude": -74.0060,
  "geo_accuracy": 30
}

在页面里核对是否生效

浏览器控制台(需安全上下文)
// about:blank 新建页不是安全上下文,deviceMemory / permissions 会读不到。
// 用 file:// 或 https 页面。
console.log(navigator.userAgent);
console.log(navigator.hardwareConcurrency, navigator.deviceMemory);
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
console.log(navigator.connection && navigator.connection.effectiveType);
console.log(isSecureContext);

已知边界

这些是设计约束,不是缺陷。写进文档是为了让你少走弯路。

常见问题

加 --fingerprint-debug 启动可以看到完整的加载日志。

现象原因处理
指纹完全没生效,日志显示 native/none三个开关一个都没给加 --fingerprint-profile 或 --fingerprint-config-path
日志 needs both a profile name and --user-data-dir只给了 --fingerprint-profile补上 --user-data-dir
日志 cannot read <path>路径算错或文件不存在改用 --fingerprint-config-path 给绝对路径确认
日志 rejected: seed must be non-zero开了噪声但没写 seed,或 seed 写成了数字改成字符串:"seed": "12345"
日志 rejected: webgl_renderer does not match user_agent OS familyUA 与 renderer 打架按校验规则第 1 条对齐
日志 rejected: unknown webgl_preset档位名拼错对照预设名表
改了配置没反应配置只在启动时读一次重启浏览器进程
两个实例指纹一样用了同一个 seed每个实例独立随机生成 seed
deviceMemory / permissions 读不到页面不是安全上下文(新标签页就不是)换成 file:// 或 https 页面,先确认 isSecureContext === true
navigator.connection.type 是 undefined上游默认不暴露该属性启动加 --enable-blink-features=NetInfoDownlinkMax
日志 rejected: ua_brands ... contradicts ua_full_versionGREASE 品牌没用 Not? / Not. 前缀改成 "Not?A_Brand/24",或整段删掉 ua_brands
启动后立刻退出,没有调试端口也没报错受限 / 沙箱环境里进程沙箱起不来加 --no-sandbox(普通桌面环境不需要)
日志出现 produced no usable proxy代理凭据写进了 URL拆成 proxy_username / proxy_password