身份

时区、区域设置和语言指纹指南

时区、区域设置和语言设置如何创建地理指纹,以及如何一致地配置它们以实现完整的身份控制。

文档中心

想直接看维护中的产品文档?

这篇文章对应的主题已经有文档中心页面。需要规范流程、当前参数和长期参考时,优先看 docs。

将区域设置作为一个整体

你的浏览器通过多个渠道暴露地理信息:通过 Intl API 暴露时区,通过数字和日期格式暴露区域设置,通过 navigator.languageAccept-Language 头暴露语言,以及通过 Geolocation API 暴露地理位置。这四个属性构成了浏览器身份的地理层。当它们彼此不一致或与你的 IP 地址不一致时,不一致是可见的。

BotBrowser 为每项区域属性提供专用 CLI 标志。保留为 auto 的设置会根据所选代理路由派生。本文介绍自动值、明确覆盖和多区域工作流。

隐私影响

地理元数据是浏览器身份中最常被检查的方面之一。追踪系统会比较:

  • IP 地理位置 vs. 时区:德国 IP 地址配 America/New_York 时区是明显的不匹配
  • 区域设置 vs. 语言de-DE 区域设置仅配 Accept-Language: en-US 是不寻常的
  • 语言 vs. IP 区域:日本 IP 仅有英语语言偏好可能表明配置错误
  • 地理位置坐标 vs. IP:如果 Geolocation API 返回东京坐标但 IP 解析到纽约,冲突很明显

这些检查简单且快速,使其成为任何追踪管线中的早期过滤器。正确获得地理一致性是任何注重隐私的浏览设置的必要基础。

BotBrowser 的自动地理检测消除了这些不匹配最常见的来源:手动配置错误。当你通过代理连接时,BotBrowser 检测代理的 IP 并自动派生时区、区域设置、语言和地理位置。

区域值之间的关系

浏览器如何暴露地理信息

时区:JavaScript 的 Intl.DateTimeFormat().resolvedOptions().timeZone 返回 IANA 时区名称(如 America/New_York)。Date 对象的 getTimezoneOffset() 方法返回以分钟为单位的 UTC 偏移。两者必须彼此一致并与声称的位置一致。

区域设置Intl.NumberFormat().resolvedOptions().localeIntl.DateTimeFormat().resolvedOptions().locale 揭示浏览器的格式区域设置。这影响数字格式(逗号 vs. 句点作为小数点)、日期格式(DD/MM vs. MM/DD)和货币格式。

语言navigator.language 返回主要语言,navigator.languages 返回完整的首选语言列表。Accept-Language HTTP 头随每个请求发送这些偏好。

地理位置navigator.geolocation.getCurrentPosition() API 返回类似 GPS 的坐标。这需要用户权限,但当授权时,坐标必须对给定的 IP 和时区来说是合理的。

一致性链

这些信号形成一个必须内部一致的链:

IP 地址 → 国家 → 时区 → 区域设置 → 语言 → 地理位置

每一步都必须从前一步逻辑推导出来。日本的代理 IP 应该产生:

  • 时区:Asia/Tokyo
  • 区域设置:ja-JP
  • 语言:ja-JP,ja,en
  • 地理位置:日本坐标(如果查询)

打断此链中的任何环节都会产生可检测的不一致。

DST 和 UTC 偏移

时区配置必须考虑夏令时(DST)。使用 UTC-5 等 UTC 偏移而不是 America/New_York 等 IANA 时区名称,在 DST 转换发生时会失败。America/New_York 在冬季是 UTC-5,夏季是 UTC-4。固定的 UTC 偏移不处理此转换,创建季节性的不匹配,揭示时区是手动配置的。

BotBrowser 内部使用 IANA 时区名称,确保全年正确的 DST 行为。

区域设置优先级 启动参数优先于配置文件,自动值则跟随所选代理路由。 地理身份一致性链 代理 IP 203.0.113.1 时区 Asia/Tokyo 区域设置 ja-JP 语言 ja-JP, ja, en 地理位置 35.67, 139.65 BotBrowser 从代理 IP 自动派生所有设置 需要时使用 --bot-config-* 标志覆盖任何属性

配置偏差的来源

框架级时区和区域设置

Playwright 提供每个上下文的 timezoneIdlocale 选项:

const context = await browser.newContext({
  timezoneId: 'America/New_York',
  locale: 'en-US',
});

这改变了 Intl API 行为和 navigator.language,但:

  • 地理位置坐标不受影响
  • Accept-Language 头可能不完全对齐
  • Date.getTimezoneOffset() 中的时区偏移可能不在所有上下文中一致更新

手动头设置

通过 page.setExtraHTTPHeaders() 设置 Accept-Language 改变了 HTTP 头但不改变 navigator.languagenavigator.languages。HTTP 和 JavaScript 值之间的不匹配是可检测的。

VPN 配系统时区

更改系统时区以匹配 VPN 有效但影响所有应用,不仅仅是浏览器。它还需要管理员访问权限和每次区域更改时的手动干预。

BotBrowser 的方法

自动地理检测

默认情况下,BotBrowser 从代理 IP 自动派生所有地理设置:

chrome --bot-profile="path/to/profile.enc" \
       --proxy-server=socks5://user:pass@jp-proxy:1080

BotBrowser 检测到日本 IP 并自动配置:

  • 时区:Asia/Tokyo
  • 区域设置:ja-JP
  • 语言:ja-JP,ja,en
  • 地理位置:从 IP 近似的坐标

不需要额外标志。auto 行为是所有地理设置的默认值。

手动覆盖标志

当需要特定地理设置时,四个 CLI 标志提供完整控制:

--bot-config-timezone(ENT Tier1):设置 IANA 时区。

--bot-config-timezone=America/New_York    # 特定时区
--bot-config-timezone=auto                # 从 IP 派生(默认)
--bot-config-timezone=real                # 使用系统时区

--bot-config-locale(ENT Tier1):设置浏览器区域设置。

--bot-config-locale=en-US    # 特定区域设置
--bot-config-locale=auto     # 从 IP/语言派生(默认)

--bot-config-languages(ENT Tier1):设置语言偏好。

--bot-config-languages=en-US,en          # 特定语言
--bot-config-languages=auto              # 从 IP 派生(默认)

--bot-config-location(ENT Tier1):设置地理位置坐标。

--bot-config-location=40.7128,-74.0060   # 特定坐标
--bot-config-location=auto               # 从 IP 派生(默认)
--bot-config-location=real               # 使用系统 GPS

一致的浏览器配置

BotBrowser 将这些值作为浏览器配置统一应用,这意味着:

  • 时区Intl.DateTimeFormat().resolvedOptions().timeZoneDate.getTimezoneOffset() 都反映配置的时区,包括正确的 DST 行为
  • 区域设置:所有 Intl 格式化器(NumberFormat、DateTimeFormat、Collator)使用配置的区域设置
  • 语言navigator.languagenavigator.languagesAccept-Language HTTP 头都一致
  • 地理位置navigator.geolocation.getCurrentPosition() 返回配置的坐标

所有值在主线程、workers 和 HTTP 头中保持一致。

设置区域值

完整地理配置(CLI)

chrome --bot-profile="path/to/profile.enc" \
       --proxy-server=socks5://user:pass@us-east.proxy:1080 \
       --bot-config-timezone=America/New_York \
       --bot-config-locale=en-US \
       --bot-config-languages=en-US,en \
       --bot-config-location=40.7128,-74.0060

常见区域配置

区域时区区域设置语言坐标
美东America/New_Yorken-USen-US,en40.7128,-74.0060
美西America/Los_Angelesen-USen-US,en34.0522,-118.2437
英国Europe/Londonen-GBen-GB,en51.5074,-0.1278
德国Europe/Berlinde-DEde-DE,de,en52.5200,13.4050
法国Europe/Parisfr-FRfr-FR,fr,en48.8566,2.3522
日本Asia/Tokyoja-JPja-JP,ja,en35.6762,139.6503
韩国Asia/Seoulko-KRko-KR,ko,en37.5665,126.9780
巴西America/Sao_Paulopt-BRpt-BR,pt,en-23.5505,-46.6333
澳大利亚Australia/Sydneyen-AUen-AU,en-33.8688,151.2093

Playwright 集成

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: 'path/to/botbrowser/chrome',
    args: [
      '--bot-profile=path/to/profile.enc',
      '--proxy-server=socks5://user:pass@us-east.proxy:1080',
      '--bot-config-timezone=America/New_York',
      '--bot-config-locale=en-US',
      '--bot-config-languages=en-US,en',
      '--bot-config-location=40.7128,-74.0060',
    ],
    headless: true,
  });

  const context = await browser.newContext();
  const page = await context.newPage();

  const tz = await page.evaluate(() =>
    Intl.DateTimeFormat().resolvedOptions().timeZone
  );
  const langs = await page.evaluate(() => navigator.languages);
  const locale = await page.evaluate(() =>
    Intl.NumberFormat().resolvedOptions().locale
  );

  console.log('Timezone:', tz);     // America/New_York
  console.log('Languages:', langs); // ['en-US', 'en']
  console.log('Locale:', locale);   // en-US

  await browser.close();
})();

多区域设置

const regions = [
  {
    profile: 'profiles/us-user.enc',
    proxy: 'socks5://user:pass@us.proxy:1080',
    timezone: 'America/New_York',
    locale: 'en-US',
    languages: 'en-US,en',
    location: '40.7128,-74.0060',
  },
  {
    profile: 'profiles/de-user.enc',
    proxy: 'socks5://user:pass@de.proxy:1080',
    timezone: 'Europe/Berlin',
    locale: 'de-DE',
    languages: 'de-DE,de,en',
    location: '52.5200,13.4050',
  },
  {
    profile: 'profiles/jp-user.enc',
    proxy: 'socks5://user:pass@jp.proxy:1080',
    timezone: 'Asia/Tokyo',
    locale: 'ja-JP',
    languages: 'ja-JP,ja,en',
    location: '35.6762,139.6503',
  },
];

for (const cfg of regions) {
  const browser = await chromium.launch({
    executablePath: 'path/to/botbrowser/chrome',
    args: [
      `--bot-profile=${cfg.profile}`,
      `--proxy-server=${cfg.proxy}`,
      `--bot-config-timezone=${cfg.timezone}`,
      `--bot-config-locale=${cfg.locale}`,
      `--bot-config-languages=${cfg.languages}`,
      `--bot-config-location=${cfg.location}`,
    ],
    headless: true,
  });

  // 运行区域特定任务...
  await browser.close();
}

当前版本的优先级

BotBrowser 对每项区域设置采用清晰的优先顺序。启动时明确传入的值优先级最高。如果启动配置将某项保留为 auto,则使用所选配置文件 configs 中的值。如果两层都没有明确值,该设置会跟随所选代理路由。

时区、区域、语言和位置会分别应用这套顺序。auto 表示把选择交给下一个适用来源,并不会覆盖配置文件中的明确值。修改任一输入后,应创建新上下文并验证应用结果。

检查区域一致性

配置地理设置后,验证所有属性:

const page = await context.newPage();

// 时区
const tz = await page.evaluate(() =>
  Intl.DateTimeFormat().resolvedOptions().timeZone
);

// 时区偏移(应对当前日期/DST 正确)
const offset = await page.evaluate(() => new Date().getTimezoneOffset());

// 从数字格式获取区域设置
const locale = await page.evaluate(() =>
  Intl.NumberFormat().resolvedOptions().locale
);

// 语言
const lang = await page.evaluate(() => navigator.language);
const langs = await page.evaluate(() => navigator.languages);

// 日期格式(区域设置特定)
const dateFormat = await page.evaluate(() =>
  new Date().toLocaleDateString()
);

// 数字格式(区域设置特定)
const numFormat = await page.evaluate(() =>
  (1234567.89).toLocaleString()
);

console.log('Timezone:', tz);
console.log('Offset:', offset);
console.log('Locale:', locale);
console.log('Language:', lang);
console.log('Languages:', langs);
console.log('Date format:', dateFormat);
console.log('Number format:', numFormat);

确认:

  1. 时区匹配预期的 IANA 名称
  2. UTC 偏移对当前日期正确(考虑 DST)
  3. 区域设置正确影响数字和日期格式
  4. 语言按预期优先顺序排列
  5. 所有值与代理 IP 地理一致

配置保障

  1. 使用 IANA 时区名称,不要用 UTC 偏移。 America/New_York 正确处理 DST。UTC-5 不会。

  2. 按优先顺序设置语言。 德国用户通常有 de-DE,de,en。将英语作为次要语言对大多数区域来说是合理的。

  3. 将地理位置匹配到代理城市,而不是街道地址。 城市级精度足够且更现实。

  4. 保持区域设置和时区在同一区域。 ja-JP 区域设置配 Europe/London 时区是明显的不一致。

  5. 尽可能让 BotBrowser 自动检测。 auto 默认值从代理 IP 产生一致的结果,无需手动配置。

  6. 测试格式化行为,不仅仅是 API 值。 检查 toLocaleDateString()toLocaleString() 是否产生区域适当的格式。

区域配置问答

BotBrowser 正确处理 DST 转换吗? 是的。BotBrowser 内部使用 IANA 时区名称,其中编码了 DST 规则。Date.getTimezoneOffset() 对任何日期返回正确的偏移,包括转换。

我可以在 Playwright 中按上下文设置时区吗? Playwright 的 timezoneId 选项按上下文改变 JavaScript Intl 行为。BotBrowser 的 --bot-config-timezone 标志在 BotBrowser 配置中应用时区。为该值选择一个来源并验证结果。

不使用代理的自动检测会怎样? 没有代理时,BotBrowser 使用你的真实公共 IP 进行自动检测。地理设置将匹配你的实际位置。

我可以只设置时区让其余自动检测吗? 可以。你可以覆盖单个设置。例如,只设置 --bot-config-timezone 而将区域设置、语言和位置保持为 auto 是可行的。但确保时区与自动检测的值一致。

--bot-config-location 需要用户权限吗? BotBrowser 设置在页面请求地理位置权限时返回的地理位置值。用户权限提示行为由浏览器上下文设置控制。

--bot-config-languages 接受什么语言格式? 逗号分隔的 BCP 47 语言标签列表:en-US,en,fr-FR,fr。顺序决定优先级,反映在 navigator.languagesAccept-Language 头中。

不使用 --bot-profile 也能使用这些标志吗? 地理标志可以独立工作,但没有配置文件就没有指纹保护。始终使用 --bot-profile 作为基础。

设置 --bot-config-languages 时 Accept-Language 头会更新吗? 是的。每个 HTTP 请求的 Accept-Language 头反映配置的语言列表,包括用于优先排序的适当质量值(q-values)。

维护区域一致性

时区、区域设置、语言和地理位置构成配置文件的区域层。auto 值遵循文档说明的优先顺序和代理路由。应用有明确需求时,可使用对应标志进行设置。

代理设置请参阅代理配置。浏览器身份请参阅浏览器品牌切换User Agent 控制和 Client Hints。多区域工作流程请参阅多账户浏览器隔离

#Timezone#Locale#Language#Identity#Geolocation

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。