控制端只需要做两件事:把一份 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 值
0(个别字段为 -1)表示不覆盖。
这条约定保证"没配的项"与上游 Chromium 逐字节一致。共 84 项。未列出的字段名会被忽略。数值型字段的 0 / 空串 / 空数组表示不覆盖。
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
enabled | bool | false | 总开关。必须显式写 true,否则后面所有字段都不生效。 |
profile_name | string | "" | 仅用于日志记录。 |
preset | string | "" | 仅日志字段,不驱动任何行为。写了名字并不会自动填好整套配置。 |
seed | string | "" | 噪声种子,十进制无符号整数的字符串形式,如 "9021073948172635401"。
所有噪声都由它派生。写成 JSON 数字会被忽略,开了噪声就会报错。 |
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
user_agent | string | "" | navigator.userAgent,同时是 UA-CH 的推导基线。 |
ua_platform | string | "" | UA-CH 的 platform,如 Windows / macOS。 |
ua_platform_version | string | "" | 10.0.0(Win10)/ 15.0.0(Win11)等。 |
ua_architecture | string | "" | x86 / arm。 |
ua_bitness | string | "" | 64 / 32。 |
ua_model | string | "" | 桌面端留空。 |
ua_full_version | string | "" | 如 146.0.7680.252。 |
ua_brands | string[] | [] | Sec-CH-UA 品牌列表。两种写法:"Brand"(版本取主版本)或 "Brand/版本"。整段省略最安全。 |
ua_mobile | bool | false | |
ua_wow64 | bool | false | |
platform | string | "" | navigator.platform,如 Win32 / MacIntel。 |
hardware_concurrency | int | 0 | navigator.hardwareConcurrency。 |
device_memory | double | 0 | navigator.deviceMemory(GB)。 |
max_touch_points | int | -1 | navigator.maxTouchPoints。-1 表示原生。 |
webdriver | bool | false | navigator.webdriver。 |
languages | string[] | [] | 顺序有意义,如 ["zh-CN","zh","en"]。 |
accept_language | string | "" | Accept-Language 请求头。 |
plugins | object[] | [] | navigator.plugins / mimeTypes。留空用原生列表。结构见下方说明。 |
connection_effective_type | string | "" | slow-2g / 2g / 3g / 4g。 |
connection_type | string | "" | wifi / ethernet / cellular / bluetooth / wimax / none / other / unknown。需要启动时加 --enable-blink-features=NetInfoDownlinkMax 才可读,否则该属性为 undefined。 |
connection_rtt | int | 0 | 毫秒。 |
connection_downlink | double | 0 | Mbps。 |
connection_save_data | bool | false | |
timezone | string | "" | IANA 名,必须含 /,如 Asia/Shanghai。 |
timezone_offset_minutes | int | 0 | 与 timezone 相差的分钟数。 |
screen_width / screen_height | int | 0 | 必须成对设置。 |
screen_avail_width / screen_avail_height | int | 0 | 不得大于对应的 screen 尺寸。 |
screen_avail_left / screen_avail_top | int | 0 | 任务栏偏移。 |
screen_color_depth | int | 0 | 通常 24。 |
screen_pixel_depth | int | 0 | 通常 24。 |
device_pixel_ratio | double | 0 | 如 1 / 1.25 / 1.5。 |
window_outer_width / window_outer_height | int | 0 | 窗口外尺寸。 |
storage_quota | int64 | 0 | 存储配额(字节)。0 = 原生;否则须落在 [1 MiB, 1 PiB] 区间内。 |
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 即为空数组。整个数组留空则使用原生列表。
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
canvas_noise | bool | false | 开启 canvas 像素噪声。 |
canvas_noise_strength | double | 0 | 须 > 0。只动 alpha 低 4 位,肉眼不可见。 |
webgl_noise | bool | false | 开启 WebGL 参数扰动。 |
webgl_vendor | string | "" | 如 Google Inc. (NVIDIA)。 |
webgl_renderer | string | "" | 如 ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 Direct3D11 vs_5_0 ps_5_0, D3D11)。必须与 UA 的 OS 家族自洽。 |
webgl_extensions | string[] | [] | 留空 = 原生扩展列表。 |
webgl_preset | string | "" | GPU 能力档位名,覆盖 getParameter() 的一批数值上限,使其与 vendor / renderer 自洽。未知名字会被拒绝。 |
audio_noise | bool | false | 开启 WebAudio 噪声(AnalyserNode / AudioBuffer)。 |
audio_noise_strength | double | 0 | 须 > 0。 |
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
webgpu_preset | string | "" | GPU 档位名,与 webgl_preset 用同一张表。未知名字会被拒绝。 |
webgpu_vendor | string | "" | 必须与 webgpu_description 成对设置;且不能与 webgl_renderer 的 GPU 家族矛盾。 |
webgpu_description | string | "" | 适配器描述,与 vendor 成对。 |
webgpu_architecture | string | "" | 适配器架构字符串。不做交叉校验,请自行与所选档位保持一致。 |
webgpu_device | string | "" | PCI 设备号,必须是 0x 开头的十六进制,如 "0x2482"。 |
webgpu_driver | string | "" | 驱动信息字符串。 |
GPUAdapterInfo 的某些属性(device / description / driver)本身不对外暴露,
配了值也可能读不到。上线前建议用下面的自检方式在目标机器上实测一次。
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
font_whitelist | string[] | [] | 允许被探测到的字体白名单。 |
font_block_unknown | bool | false | 白名单之外的字体一律视为不存在。 |
font_metrics_noise | bool | false | 对 getBoundingClientRect() / getClientRects() 加亚像素抖动。 |
font_metrics_strength | double | 0 | 取值区间 (0, 1]。1.0 约 ±3 CSS px,0.5 约 ±1.5 px。写 1.5 会被拒绝。 |
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
permission_geolocation | string | "" | granted / denied / prompt。空 = 不覆盖。 |
permission_notifications | string | "" | 同上。 |
permission_camera | string | "" | 同上。 |
permission_microphone | string | "" | 同上。 |
prompt;
整齐划一反而更显眼。
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
tls_preset | string | "" | BoringSSL 密码套件档位,影响 JA3 / JA4。合法名见预设名。 注意:未知名字不报错,会静默回落到上游默认列表。 |
http2_preset | string | "" | HTTP/2 SETTINGS 帧档位。合法名见预设名。 |
http_header_order | string[] | [] | HTTP 请求头顺序。 |
proxy_server | string | "" | 代理地址,如 http://127.0.0.1:7890、https://…、socks5://127.0.0.1:1080。 |
proxy_bypass | string | "" | 绕过列表,分号分隔。 |
proxy_username | string | "" | 代理用户名。请用这个字段,不要把凭据写进代理 URL。 |
proxy_password | string | "" | 代理密码。SOCKS5 下用户名/密码各不超过 255 字节(RFC 1929 的长度字段是单字节)。 |
proxy_auth_realm | string | "" | 认证 realm。必须与目标代理实际返回的 407 realm 一致,否则认证不会生效。 |
proxy_auth_scheme | string | "" | 认证方案,只能取 6 个全小写值:basic / digest / ntlm / negotiate / spdyproxy / mock。 |
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
block_webrtc_local_ip | bool | true | 阻断 WebRTC 暴露本机内网 IP。默认就是开启的,要放开须显式写 false。 |
spoof_media_devices | bool | false | 伪造 enumerateDevices() 结果。 |
media_device_count | int | 0 | 伪造的设备数量。 |
spoof_geolocation | bool | false | 开启地理位置伪造。开启后下面几项才参与校验。 |
geo_latitude | double | 0 | 范围 [-90, 90]。 |
geo_longitude | double | 0 | 范围 [-180, 180]。 |
geo_accuracy | double | 0 | 必须 > 0。 |
geo_altitude | double | -10000 | 米。默认值表示 JS 侧为 null。合法区间 [-500, 9000]。 |
geo_altitude_accuracy | double | -1 | 米。负值表示 null,上限 1000。 |
geo_heading | double | -1 | 度。负值或 > 360 表示 null。 |
geo_speed | double | -1 | 米/秒。负值表示 null,上限 300。 |
写错名字的后果因字段而异,这点很容易踩:webgl_preset / webgpu_preset
写错会被拒绝,而 tls_preset 写错会静默回落到上游默认 —— 看起来"生效了",其实没有。
webgl_preset / webgpu_preset(同一张表,共 8 个)| 名字 | 对应 GPU |
|---|---|
nvidia_gtx1660_win | NVIDIA GeForce GTX 1660 / Windows |
nvidia_rtx3070_win | NVIDIA GeForce RTX 3070 / Windows |
intel_hd630_win | Intel HD 630 / Windows |
apple_m1_mac | Apple M1 / macOS |
apple_m2_mac | Apple M2 / macOS |
mali_g78_android | ARM Mali-G78 / Android |
adreno_740_android | Qualcomm Adreno 740 / Android |
mesa_llvmpipe_linux | Mesa llvmpipe / Linux |
tls_preset| 名字 | 效果 |
|---|---|
""(空) | 上游 Chromium 默认密码套件列表 |
chrome_132_win、chrome_146_win / _mac / _linux | 与原生列表一致(等价于不设) |
chrome_131_win | Chrome 120–131 档:切换 ALPS 扩展码点至 17513,ja4_c = 02713d6af862 |
chrome_136_win | Chrome 133–136 档:切换 ALPS 扩展码点至 17613,ja4_c = d8a2da3f94cd |
firefox_132_win | Firefox 132 Windows 密码套件顺序(17 套) |
firefox_120_win | Firefox 120 Windows 密码套件顺序(14 套) |
safari_17_mac | Safari 17 macOS 密码套件顺序(11 套) |
http2_preset| 名字 | HEADER_TABLE_SIZE | INITIAL_WINDOW_SIZE | MAX_HEADER_LIST_SIZE |
|---|---|---|---|
chrome_146_* / 空 | 原生,不改 | ||
firefox_132_win | 65536 | 131072 | 65536 |
firefox_120_win | 65536 | 65535 | 65536 |
safari_17_mac | 4096 | 4194304 | 65536 |
校验是全有或全无:任何一条不过,整份配置作废并回落到原生 Chromium。以下组合会被拒绝。
| # | 会被拒绝的情况 |
|---|---|
| 1 | webgl_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 等) |
| 2 | permission_* 写了 granted / denied / prompt 之外的值 |
| 3 | 开了任一项噪声,但 seed 为 0 或缺失 |
| 4 | 开了噪声但强度为 0;font_metrics_strength 不在 (0, 1] |
| 5 | screen_width 与 screen_height 只写了一个 |
| 6 | screen_avail_width / screen_avail_height 大于对应 screen 尺寸 |
| 7 | timezone 不含 / |
| 8 | connection_effective_type 不是 slow-2g / 2g / 3g / 4g,或 connection_type 不是合法词元 |
| 9 | 连接参数自相矛盾(例如 effectiveType=4g 却 downlink=0.1) |
| 10 | plugins[].name 为空 |
| 11 | geo_* 越界(纬度 [-90,90]、经度 [-180,180]、accuracy > 0、altitude ∈ [-500,9000]、altitude_accuracy ≤ 1000、heading ∈ [0,360]、speed ≤ 300) |
| 12 | webgl_preset / webgpu_preset 写了不认识的名字 |
| 13 | webgpu_vendor 与 webgpu_description 只写了一个 |
| 14 | webgpu_vendor 声称的 GPU 厂商与 webgl_renderer 矛盾 |
| 15 | webgpu_device 不是 0x 开头的十六进制串 |
| 16 | storage_quota 非 0 且不在 [1 MiB, 1 PiB] 内 |
| 17 | ua_brands 里的品牌主版本与 ua_full_version 矛盾(GREASE 品牌须用 Not? 或 Not. 前缀) |
| 18 | proxy_auth_scheme 不是那 6 个全小写合法值之一 |
下面是一份可以直接复制使用的 Windows / 美国时区配置。完整字段版见随程序附带的 fp.example.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);
这些是设计约束,不是缺陷。写进文档是为了让你少走弯路。
fp.json 无效,必须重启浏览器进程。--fingerprint-profile 不传给子进程。子进程通过内部 --fp-config=<base64> 获得配置,不要手工设置这个开关。plugins 列表。--user-data-dir 不能被两个进程同时使用。多开就多目录,每个目录配一份配置。seed 决定噪声,不决定一切。只改了 UA 而没开噪声时,同 UA 的两个实例在 JS 侧看起来是一样的。block_webrtc_local_ip 默认是 true。业务若需要 WebRTC 获取真实内网 IP,必须显式写 false。preset 字段不生效,它只是日志字段。http://user:pw@host 这种形式会被解析成无效规则集,导致静默直连真实 IP 且不报错。请用独立的用户名 / 密码字段。加 --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 family | UA 与 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_version | GREASE 品牌没用 Not? / Not. 前缀 | 改成 "Not?A_Brand/24",或整段删掉 ua_brands |
| 启动后立刻退出,没有调试端口也没报错 | 受限 / 沙箱环境里进程沙箱起不来 | 加 --no-sandbox(普通桌面环境不需要) |
日志出现 produced no usable proxy | 代理凭据写进了 URL | 拆成 proxy_username / proxy_password |