HAR 文件查看与分析:读懂抓包、归纳接口,安全地分享给别人
本页目录
客服让你“导一份 HAR 文件发过来”。你在 DevTools 里点了导出,手上就多了一个 JSON 文件:页面发出的每个请求、收到的每个响应都在里面,很可能还有你的会话 Cookie 和 Bearer token。本文就讲这个文件:各浏览器怎么导出、怎么看、怎么把几百条记录归纳成一张接口清单,以及发给任何人之前要检查什么。
会用到两个工具。本站的 HAR 分析器 在浏览器里运行,把抓包变成一份脱敏的接口摘要。REA(morluto 的开源项目)提供 inspect-web-network-capture,让 AI agent 逐条读取同一份 HAR,而且不会访问录制里的任何 URL。
适合谁读: 需要根据抓包排查 Web 应用问题、或者要把抓包交给别人的开发、测试和技术支持人员。
你会学到:
- 在 Chrome、Edge、Firefox、Safari 里导出 HAR
- 找到 HAR 里的敏感位置:请求头、Cookie、查询串和请求/响应体
- 按接口归纳 HAR,找出慢请求和错误码
- 决定分享什么,弄清两个工具的脱敏各管什么、不管什么
- 用 REA 6.4.0 让 agent 读取 HAR
只抓你有权记录的流量: 自己的应用、测试账号,或你获得授权测试的系统。HAR 里可能有他人的个人数据。请先阅读 REA 的 DISCLAIMER.md。
HAR 文件是什么
HAR(HTTP Archive)是一种 JSON 格式。顶层是 log,下面有 version(通常是 "1.2")、creator(写出文件的浏览器)和 entries。每个 entry 是一对请求和响应:
request:方法、带查询串的 URL、请求头、Cookie,以及请求体postDataresponse:状态码、响应头、Cookie,以及content,响应体放在text里(有时是 base64)time和timings:请求耗时,分成wait(首字节时间)等几个阶段
因为响应体通常也在里面,HAR 远不只是一串 URL。这正是它适合排查问题的原因,也是需要小心对待它的原因。
第 1 步:从浏览器导出 HAR
不管哪个浏览器,都要在复现问题之前打开开发者工具。Network 面板只在打开期间记录。
Chrome 和 Edge(Chromium 内核):
- 按 F12 打开 DevTools,切到 Network,勾选 Preserve log,避免页面跳转时清空列表。
- 复现问题。
- 点 Network 工具栏上的下载图标,选择 Export HAR (sanitized)…。
从 Chrome 130 开始,默认导出不包含 Cookie、Set-Cookie 和 Authorization 请求头。要导出它们,必须打开 Settings > Preferences > Network > Allow to generate HAR with sensitive data。提交工单时,几乎总是选脱敏版就够了。
Firefox: 打开开发者工具,切到 Network,页面会跳转的话打开 Persist Logs,复现问题后在请求列表上右键,选 Save All As HAR。Firefox 没有 Chrome 那一步脱敏,请当作它什么都包含。
Safari: 先在 Safari 设置里打开开发菜单(高级 > 显示网页开发者功能),打开 Web 检查器,切到 网络,复现问题后用 导出 保存 .har 文件。同样按未脱敏处理。
抓包越短越好。 在你关心的操作之前开始记录,操作完马上停止。短的抓包更好读,包含的个人数据也更少。
第 2 步:知道秘密藏在哪里
在归纳或分享 HAR 之前,先弄清敏感值通常在哪:
| 位置 | 常见内容 | Chrome 脱敏导出会去掉吗? |
|---|---|---|
Authorization 请求头 |
Bearer token、Basic 凭证 | 会 |
Cookie / Set-Cookie 头和 cookies 数组 |
会话 ID | 会 |
其他请求头,如 X-Api-Key |
API key | 不会 |
| URL 查询串 | ?token=、?api_key=、签名 URL 参数 |
不会 |
postData.text |
登录表单里的密码、个人信息 | 不会 |
response.content.text |
服务器返回的任何内容,包括用户资料 | 不会 |
最容易漏掉的是后三行。Chrome 脱敏导出的文件里,查询串中仍可能有 API key,响应体里仍可能有完整的用户资料。
第 3 步:按接口归纳 HAR
400 条记录的 HAR 用文本编辑器很难看。通常你想要的是一张接口清单:每个接口调用了几次、返回了哪些状态码、耗时多少。打开 HAR 分析器,把文件拖进去即可。文件在当前标签页的 Web Worker 里解析,不会上传。
为了展示真实结果,我们给一个演示用的笔记应用 notes.example.com 构造了一份小 HAR,共 7 条:两次读取笔记、一次新建笔记、一次返回 500 的搜索、一次 GraphQL 查询,以及两个脚本,其中一个来自第三方域名。部分请求带着 JWT Bearer token 和会话 Cookie,搜索 URL 里带着 api_key=test-key-123。下面是分析器导出的 JSON 片段:
{
"summary": {
"exchanges": 7,
"endpoints": 6,
"firstParty": "example.com",
"thirdPartyRatio": 0.143
},
"endpoints": [
{
"host": "notes.example.com",
"method": "GET",
"path": "/api/notes/{id}",
"count": 2,
"status": { "200": 2 },
"credentials": [
{ "where": "header", "name": "authorization", "value": "[REDACTED]",
"length": 60, "scheme": "Bearer", "jwt": true },
{ "where": "cookie", "name": "sid", "value": "[REDACTED]", "length": 20 }
],
"maxMs": 2400,
"avgMs": 1242.5,
"resShape": { "object": { "id": "number", "title": "string",
"tags": { "array": "string" }, "archived": "boolean|null" } }
},
{
"host": "notes.example.com",
"method": "GET",
"path": "/api/search",
"status": { "500": 1 },
"query": ["api_key", "q"],
"credentials": [
{ "where": "query", "name": "api_key", "value": "[REDACTED]", "length": 12 }
],
"maxMs": 310
}
]
}
怎么读:
- 路径模板把重复调用合并。
/api/notes/41和/api/notes/42合成了一行/api/notes/{id},count: 2。纯数字、UUID、JWT、日期、长十六进制串、邮箱和类似 token 的随机串都会换成占位符;order-12345这样的 slug 保持原样。 - 把
maxMs和avgMs放在一起看,就能找到慢请求。 平均 1242.5 ms 掩盖了实情:两次读取里有一次花了 2400 ms。某个接口的最大值远高于平均值时,先查它。 status按接口统计错误。 搜索接口返回了500。状态码0表示请求没有收到响应,例如被拦截或取消。resShape只描述结构,不含数据。 能看出archived有时是布尔值、有时是null,前端 bug 常常就出在这种差异上。- GraphQL 请求按操作拆开。 演示里的
/graphql单独成为一个接口,"kind": "graphql"、"operation": "query Me",查询文本和变量都没有保留。
我们还在完整导出里搜索了演示文件中的每个秘密:JWT、Cookie 值、test-key-123、搜索词和笔记正文,一个都没找到。分析器从不把请求头、Cookie、查询参数或请求/响应体的值写进报告,只保留名称、类型、次数和最长值的长度。
第 4 步:决定分享什么
分析器不会生成一份清理过的 HAR,它生成的是摘要。所以你有三种选择,按安全程度排序:
- 分享分析器导出的 JSON。 里面没有任何值,只有域名、路径模板、名称、类型、次数和耗时,但会带上你打开的文件名。回答“哪个接口出错、有多慢”已经够用。
- 分享浏览器的脱敏导出。 用 Chrome 或 Edge 的 Export HAR (sanitized),然后按下面的清单自己检查查询串里的 API key 和请求/响应体里的个人数据。
- 只有对方确实需要完整的头和正文时,才分享完整 HAR,并通过公司认可的渠道发送。发完之后退出这个测试会话,让里面的 token 失效。
分享前检查清单:
- 在文件里搜索
token、key、secret、password、session和eyJ(大多数 JWT 的开头)。 - 搜索你自己的邮箱、姓名和手机号。
- 检查登录、注册请求的
postData.text。 - 看看抓包里有没有其他标签页或无关网站的请求。
- 尽量用测试账号。真实账号的 token 在过期或退出登录之前一直有效。
分析器的凭证规则覆盖哪些: 名为 authorization、proxy-authorization、cookie、set-cookie、x-api-key 的请求头;名称里含 token、secret、password、session、key、auth、signature、credential 的请求头或查询参数;以及值是 JWT 的任何请求头或查询参数。这些会作为凭证按名称列出。其他值同样会被丢弃,因为报告根本不存值。分析器做不到的是判断某个正文字段里是不是个人数据,它只能告诉你 title 字段是字符串。
第 5 步:用 REA 让 AI agent 读 HAR
摘要告诉你该看哪一条请求。要看这条请求真实的头和正文,或者让 agent 把请求和前端代码对照,就用 REA 的 inspect-web-network-capture。它不需要浏览器,也不需要额外的分析引擎。安装方法见 REA MCP 安装指南。
rea inspect-web-network-capture /absolute/path/notes-demo.har har --record 1 --json
--record 接受从 0 开始的条目序号,可以重复写多次;不写就读取全部条目。下面是 REA 6.4.0 对演示文件第 1 条返回结果的一部分:
"records": [
{
"ordinal": 1,
"location": { "kind": "json-pointer", "pointer": "/log/entries/1" },
"reported": {
"request": {
"method": "GET",
"url": "https://notes.example.com/api/notes/41",
"headers": [
{ "name": "authorization", "value": null },
{ "name": "cookie", "value": null }
]
},
"response": {
"status": 200,
"content": {
"mimeType": "application/json",
"text": "{\"id\":41,\"title\":\"a\",\"tags\":[\"x\"],\"archived\":false}"
}
}
},
"redactions": [
{ "pointer": "/request/headers/0/value", "reason": "transport-credential" },
{ "pointer": "/request/headers/1/value", "reason": "transport-credential" }
]
}
]
它和分析器是两类工具。REA 按浏览器写出的原样保留记录,包括响应体,并记录 Evidence ID 和文件的 SHA-256,agent 可以准确说明某个事实来自哪个文件的哪一条。它只去掉已知的传输凭证:Authorization、Proxy-Authorization、Cookie、Set-Cookie 请求头的值,Cookie 值,以及 URL 里嵌入的用户名和密码。
其余内容都会保留。我们读取第 4 条(那条失败的搜索)时,URL 原样返回 https://notes.example.com/api/search?q=invoice&api_key=test-key-123,redactions 是空列表。要排除这类值,需要显式声明:
rea inspect-web-network-capture /absolute/path/notes-demo.har har \
--record 4 --sensitive-value 'test-key-123' --json
加上这个参数后,REA 6.4.0 把整个 url 字段换成了 null,并记录 {"pointer": "/request/url", "reason": "explicit-sensitive-value"}。输出里任何地方都找不到这个 key,Evidence 参数里也只记 "sensitive_value_count": 1,不记值本身。注意它丢掉的是整个字段而不是匹配的那一段,所以这条记录的 URL 其余部分也看不到了。
通过 MCP 调用时,agent 使用 inspect_web_network_capture,传入 capture_path、format: "har",可选 record_ordinals 和 sensitive_values。提示词可以这样写:
用 REA 读取 /absolute/path/notes-demo.har。找出失败或耗时超过一秒的请求,
给我看它们的请求和响应,并注明每条的 record ordinal。把 test-key-123 当作敏感值。
REA 6.4.0 在这里做不到的事: 它只接受 HAR 1.2 和 mitmproxy 原生抓包,后者需要 Linux 上的 mitmdump 12.2.3。它不读 Fiddler 的 .saz 文件(本站分析器可以读)。它没有针对 HAR 的接口归纳视图,归纳请用分析器的摘要。输入上限 32 MiB。它从不发请求,用它自己限制说明里的话说:“Recorded URLs are never fetched”。
常见问题和排错
分析器提示 JSON 不是 HAR 1.2 格式。 文件缺少 log.entries,或者某条记录没有请求方法、URL 或响应状态码。请从浏览器重新导出,不要手工改。
明明需要登录的接口,凭证列表却是空的。 你的 HAR 很可能来自 Chrome 的脱敏导出,Authorization 和 Cookie 在分析器看到之前就被删掉了。用于分享这没问题。要审计哪些接口带了凭证,就用包含敏感数据的导出,在本地分析,用完删掉。
REA 拒绝读取文件。 REA 只接受 HAR 1.2,会拒绝有重复 JSON 键的文件,输入上限 32 MiB。请重新导出一份只覆盖目标操作的短抓包。
同一个接口出现了两次。 路径里有某一段被占位规则当成普通单词,例如 order-12345。每一行本身是对的,只是没有合并。
FAQ
HAR 文件可以直接发给客服吗?
默认不行。Chrome 或 Edge 的脱敏导出去掉了 Cookie 和 Authorization,但查询串和正文还在。按上面的清单检查一遍;如果摘要就能回答问题,直接发分析器的摘要。
HAR 分析器会上传我的文件吗?
不会。它在 Web Worker 里运行,Worker 的内容安全策略禁止任何网络请求。工具页说明了怎么用浏览器的 Network 面板或断网来自己验证。
不用任何工具能看 HAR 吗?
可以,它就是 JSON。jq '.log.entries[] | [.request.method, .request.url, .response.status, .time]' file.har 就能得到一张简单的表。不过要分享结果,还是需要路径模板和脱敏。
这篇和“追踪 API 调用到代码”有什么区别?
本文讲 HAR 文件本身。要从一个请求找到发出它的 JavaScript,请看 用 REA 追踪网站 API 调用。
下一步
- 从请求追到前端代码:用 REA 追踪网站 API 调用:浏览器捕获、HAR 与前端 bundle。
- 把同一会话里压缩后的堆栈位置还原到源码:从 JavaScript bundle 还原源码。
- 把抓包作为可对比的 Evidence 跨版本保存:Evidence、快照与版本对比。
- 阅读 REA 的 网络抓包参考文档。