网站统计、兼容性提示和故障排查中,经常需要知道用户正在使用Chrome、Edge、Firefox还是Safari,以及对应的浏览器版本。最常见的方法是读取User-Agent,但现代浏览器正在减少其中可用于识别设备和版本的信息,仅靠一段正则表达式已经不够稳妥。

获取浏览器信息之前,应该先明确用途。统计访问来源可以接受一定误差;处理功能兼容性时,更适合检测浏览器是否支持所需API;涉及登录、安全和权限判断时,则不能信任浏览器自行上报的名称与版本。

浏览器User-Agent怎么看?识别规则与代码示例

浏览器信息从哪里来

网页能够接触到的浏览器信息主要来自三个位置:

  • 前端JavaScript中的navigator.userAgent

  • 支持浏览器提供的User-Agent Client Hints;

  • 浏览器发送给服务器的HTTP请求头。

User-Agent通常包含浏览器、渲染引擎、操作系统和设备信息。例如,一段Edge浏览器的User-Agent中,可能同时出现AppleWebKit、Chrome、Safari和Edg等标记。

这是历史兼容造成的结果,不代表用户同时安装或运行了这些浏览器。因此,识别时不能看到Chrome就立即判断为Google Chrome。

手动查看浏览器版本

如果只是帮助用户确认自己安装的版本,直接打开浏览器的“关于”页面通常最准确。

浏览器查看方式
Google Chrome菜单 → 帮助 → 关于Google Chrome,或打开chrome://settings/help
Microsoft Edge菜单 → 帮助和反馈 → 关于Microsoft Edge,或打开edge://settings/help
Mozilla Firefox菜单 → 帮助 → 关于Firefox,或打开about:support
SafarimacOS菜单栏 → Safari浏览器 → 关于Safari浏览器
Opera菜单 → 更新和恢复,或打开opera://about
Brave菜单 → 关于Brave,或打开brave://settings/help

关于页面还能触发浏览器更新检查。故障排查时,用户从这里复制完整版本号,比网站自动识别的结果更可靠。

前端读取User-Agent

JavaScript可以通过navigator.userAgent读取当前User-Agent字符串:

const userAgent = navigator.userAgent;

console.log(userAgent);

返回结果可能类似:

Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0

这段字符串中同时出现Chrome和Edge标记。如果先匹配Chrome/,就会把Edge错误识别为Chrome。因此,浏览器判断通常要从更具体的标记开始。

常见浏览器匹配顺序

下面是一段基础识别代码,可用于统计或故障信息采集:

function getBrowserInfo() {
    const ua = navigator.userAgent;

    const rules = [
        {
            name: "Microsoft Edge",
            regex: /EdgiOS\/([\d.]+)|EdgA\/([\d.]+)|Edg\/([\d.]+)/
        },
        {
            name: "Opera",
            regex: /OPR\/([\d.]+)/
        },
        {
            name: "Samsung Internet",
            regex: /SamsungBrowser\/([\d.]+)/
        },
        {
            name: "Google Chrome",
            regex: /CriOS\/([\d.]+)|Chrome\/([\d.]+)/
        },
        {
            name: "Mozilla Firefox",
            regex: /FxiOS\/([\d.]+)|Firefox\/([\d.]+)/
        },
        {
            name: "Internet Explorer",
            regex: /MSIE\s([\d.]+)|Trident\/.*rv:([\d.]+)/
        },
        {
            name: "Safari",
            regex: /Version\/([\d.]+).*Safari\//
        }
    ];

    for (const rule of rules) {
        const match = ua.match(rule.regex);

        if (match) {
            const version = match.slice(1).find(Boolean) || "未知";

            return {
                name: rule.name,
                version,
                userAgent: ua
            };
        }
    }

    return {
        name: "未知浏览器",
        version: "未知",
        userAgent: ua
    };
}

console.log(getBrowserInfo());

这段代码需要把Edge、Opera和Samsung Internet放在Chrome之前,因为这些浏览器可能同样包含Chrome/标记。Safari则应放在Chromium系浏览器之后,避免被通用的Safari/标记误判。

正则规则只能覆盖已知情况。浏览器更改User-Agent、应用内浏览器增加自定义标记,或者用户主动修改标识后,结果都可能出现偏差。

User-Agent为何不可靠

User-Agent最初用于向服务器说明客户端环境,后来被大量用于浏览器判断、设备识别和用户追踪。随着字段越来越复杂,不同浏览器开始减少或固定其中的部分信息。

使用User-Agent时需要接受以下限制:

  • 浏览器可以修改或伪装User-Agent;

  • 扩展、自动化工具和爬虫可以发送任意字符串;

  • 部分版本字段可能只保留主版本号;

  • 操作系统版本可能被固定或降低精度;

  • 同一内核的浏览器可能包含大量相同标记;

  • 应用内浏览器不一定提供稳定的识别格式;

  • 隐私浏览器可能主动隐藏真实品牌。

因此,User-Agent适合做访问统计、日志分类和辅助排查,不适合作为严格的身份依据。

使用Client Hints获取

User-Agent Client Hints是一套结构化的浏览器信息接口。在支持该接口的浏览器中,可以通过navigator.userAgentData读取品牌、平台和移动设备状态。

async function getClientHints() {
    if (!navigator.userAgentData) {
        return null;
    }

    const basic = {
        brands: navigator.userAgentData.brands,
        mobile: navigator.userAgentData.mobile,
        platform: navigator.userAgentData.platform
    };

    const details = await navigator.userAgentData.getHighEntropyValues([
        "fullVersionList",
        "platformVersion",
        "architecture",
        "bitness",
        "model"
    ]);

    return {
        ...basic,
        ...details
    };
}

getClientHints().then(console.log);

brandsfullVersionList返回的是数组,而不是唯一的浏览器名称。例如,结果中可能同时包含Chromium和Google Chrome,或者Chromium和Microsoft Edge。

数组中还可能出现用于降低固定识别规则可靠性的伪品牌,因此不要默认第一项就是浏览器名称。更合理的做法是遍历列表,优先匹配业务真正需要识别的品牌。

Client Hints并未得到所有浏览器的统一支持,也可能因为权限、隐私设置和运行环境而缺少部分字段。代码中仍需保留User-Agent或“未知浏览器”的降级处理。

服务端读取请求头

服务器可以从HTTP请求头读取User-Agent。以Node.js和Express为例:

app.get("/browser-info", (req, res) => {
    const info = {
        userAgent: req.get("user-agent") || "",
        brands: req.get("sec-ch-ua") || "",
        mobile: req.get("sec-ch-ua-mobile") || "",
        platform: req.get("sec-ch-ua-platform") || ""
    };

    res.json(info);
});

支持Client Hints的浏览器可能发送以下低熵请求头:

Sec-CH-UA
Sec-CH-UA-Mobile
Sec-CH-UA-Platform

服务器需要更详细的信息时,可以通过响应头声明所需字段:

Accept-CH: Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform-Version

浏览器在后续请求中可能发送对应信息。Client Hints通常要求安全上下文,并且浏览器是否返回某个字段仍由客户端决定。

请求过多字段还会增加隐私风险和缓存复杂度。只需要判断移动端时,没有必要同时索取完整版本、处理器架构和设备型号。

服务端解析注意事项

服务器日志中的User-Agent数量可能非常大,自己长期维护全部正则规则并不现实。项目需要识别大量浏览器、爬虫、电视和应用内WebView时,可以使用持续维护的User-Agent解析库。

引入第三方解析库时,应检查以下内容:

  • 是否仍在持续更新规则;

  • 能否识别常见移动端和应用内浏览器;

  • 是否支持Client Hints数据;

  • 软件许可证是否符合项目要求;

  • 是否存在已公开的安全问题;

  • 返回的版本是完整版本还是主版本。

解析库只能整理客户端提供的信息,不能验证信息是否真实。即使库返回“Chrome 140”,也不代表请求一定来自真实Chrome浏览器。

参考资料

  1. Navigator userAgent接口说明

  2. User-Agent Client Hints API文档

  3. MDN浏览器检测指南

  4. Chrome User-Agent Client Hints说明

  5. User-Agent Client Hints规范