
Charles 是在 Mac 下常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。
Charles 是收费软件,可以免费试用 30 天。试用期过后,未付费的用户仍然可以继续使用,但是每次使用时间不能超过 30 分钟,并且启动时将会有 10 秒种的延时。因此,该付费方案对广大用户还是相当友好的,即使你长期不付费,也能使用完整的软件功能。只是当你需要长时间进行封包调试时,会因为 Charles 强制关闭而遇到影响。
Charles 主要的功能包括:
截取Web端、移动端 Http 和 Https 网络封包。
支持重发网络请求,方便后端调试。
支持修改网络请求参数。
支持网络请求的截获并动态修改。
支持模拟慢速网络。
charles官网下载:http://www.charlesproxy.com
激活:charles授权码在线生成:https://charles.wrbug.com/
Charles 是通过将自己设置成代理服务器来完成封包截取的
选择菜单中的 “Proxy” -> “Mac OS X Proxy” 来将 Charles 设置成系统代理。如下所示:

- Chrome 和 Firefox 浏览器默认并不使用系统的代理服务器设置,而 Charles 是通过将自己设置成代理服务器来完成封包截取的,所以在默认情况下无法截取 Chrome 和 Firefox 浏览器的网络通讯内容。如果你需要截取的话,在 Chrome 中设置成使用系统代理即可,或者直接将代理服务器设置成 127.0.0.1:8888 也可达到相同效果。
- 测试移动端接口时,一般pc端不将charles设置为系统代理
structure视图,通览抓取的各个网址

sequence时序视图,按照时间顺序显示抓包

包太多太杂怎么办 --> 过滤请求啊
在主界面的中部的 Filter 栏中填入需要过滤出来的关键字。例如我们的服务器的地址是:https://www.baidu.com , 那么只需要在 Filter 栏中填入baidu 即可
通常用于做临时性的封包过滤
在想过滤的网络请求上右击,选择 “Focus”,之后在 Filter 一栏勾选上 Focussed 一项,如下图所示:

在 Charles 的菜单栏选择 “Proxy”->”Recording Settings”,然后选择 Include 栏,选择添加一个项目,然后填入需要监控的协议,主机地址,端口号。这样就可以只截取目标网站的封包了。如下图所示:


在使用方法二或者方法三后一定记住恢复环境,经常会有同学打开过滤器后未恢复但一直抓取不到包。
如果你需要截取分析 Https 协议相关的内容。那么需要安装 Charles 的 CA 证书。具体步骤如下。
首先我们需要在 Mac 电脑上安装证书。点击 Charles 的顶部菜单,选择 “Help” -> “SSL Proxying” -> “Install Charles Root Certificate”,然后输入系统的帐号密码,即可在 KeyChain 看到添加好的证书。如下图所示:

需要注意的是,即使是安装完证书之后,Charles 默认也并不截取 Https 网络通讯的信息,访问“Proxy”->”SSL Proxying Settings”,新增“*:443”,勾选“Enable SSL Proxying”,如下图所示:

这样本机的https请求就可以抓取了
如果我们需要在 iOS 或 Android 机器上截取 Https 协议的通讯内容,还需要在手机上安装相应的证书。点击 Charles 的顶部菜单,选择 “Help” -> “SSL Proxying” -> “Install Charles Root Certificate on a Mobile Device or Remote Browser”,然后就可以看到 Charles 弹出的简单的安装教程。如下图所示:

浏览器打开 chls.pro/ssl 下载证书,打开设置,会弹出证书安装,安装完证书后,就可以截取手机上的 Https 通讯内容了。不过同样需要注意,默认情况下 Charles 并不做截取,你还需要在要截取的网络请求上右击,选择 SSL proxy 菜单项。
注意:iphone手机安装证书后,一定记得去“通用”-》“关于本机”-》“证书新人设置”中开启刚才安装的证书。否则一般默认是关闭的状态,相当于安装了证书但是出于屏蔽状态。
要截取 iPhone 上的网络请求,我们首先需要将 Charles 的代理功能打开。在 Charles 的菜单栏上选择 “Proxy”->”Proxy Settings”,填入代理端口 8888,并且勾上 “Enable transparent HTTP proxying” 就完成了在 Charles 上的设置。如下图所示:

首先我们需要获取 Charles 运行所在电脑的 IP 地址,Charles 的顶部菜单的 “Help”->”Local IP Address”,即可在弹出的对话框中看到 IP 地址,如下图所示:

在 iPhone 的 “ 设置 “->” 无线局域网 “ 中,可以看到当前连接的 wifi 名,通过点击右边的详情键,可以看到当前连接上的 wifi 的详细信息,包括 IP 地址,子网掩码等信息。在其最底部有「HTTP 代理」一项,我们将其切换成手动,然后填上 Charles 运行所在的电脑的 IP,以及端口号 8888
设置好之后,charles弹出请求连接的确认菜单,点击allow

1、手机所在IP一定要和电脑保持在一个网络中,不一定ip相同,但一定要能telnet通。有时候大家会在windows里面碰到未弹框的情况,请排查一下防火墙是否关闭,保证telnet本电脑ip 端口号是畅通的。命令例如:telnet 192.168.1.2 8888
2、部分手机需通过把Wlan开关重启一下。
某些场景需要服务器返回特定的响应来使客服端或浏览器显示相应的内容,这种情况下,要服务器配合构造相应的数据显得会比较麻烦。这个时候,使用 Charles 相关的功能就可以满足我们的需求。
charles提供了三种方式进行mock数据以应对不同的使用场景:
Map :适合长期地将某一些请求重定向到另一个网络地址或本地文件。
Rewrite :适合对网络请求进行一些正则替换。
Breakpoints :适合做一些临时性的修改。
Map分为 Map remote 和 Map local 两种
Map Remote:将指定的网络请求重定向到另一个网址请求地址
Map Local:将制定的网络请求重定向到本地

点击Tools-Map Local,点击「+」按钮新增一条映射规则

Map Local 需要填写重定向的原地址和本地的目标文件,对于有一些复杂的网络请求结果,我们可以先使用 Charles 提供的 “Save Response…” 功能,将请求结果保存到本地(如下图所示),然后稍加修改,成为我们的目标映射本地的一个经过修改的文件中。


备注:
Map Local 在使用的时候,有一个潜在的问题,就是其返回的 Http Response Header 与正常的请求并不一样。这个时候如果客户端校验了 Http Response Header 中的部分内容,就会使得该功能失效。解决办法是同时使用 Map Local 以下面提到的 Rewrite 功能,将相关的 Http 头 Rewrite 成我们希望的内容。
Map Remote 需要分别填写网络重定向的源地址和目的地址,对于不需要限制的条件,可以留空。

Rewrite 功能功能适合对某一类网络请求进行一些正则替换,以达到修改结果的目的。
此功能在 Tools - Rewrite,需要配置地址以及规则。

可以添加规则对各种类型的数据进行匹配替换

如下图,对状态码进行替换

场景:

在测试过程中,提交未成年误充值退款申请时,需要上传身份证照片、姓名身份证号、手机号以及验证码等内容,服务端会对这些信息进行校验,填写不仅繁琐,而且测试过程中使用自己的真实身份信息有一定风险
因此如果不想填写真实信息以及每次都用手机号接收短信的话,就可以对服务器返回的响应进行mock,前端页面根据返回的响应进入下一个页面

右击该条请求,点击 breakpoint,注意右上角的 breakpoint 要 enable

breakpoint 可以在 Proxy -> Breakpoints Setting 中进行查看

如上图,这里可以选择request或者response,表示对请求或者对响应进行拦截
由于本次需要mock响应,因此只选择拦截response即可
完成上述前置步骤后,就可以进行mock了
在c端的页面乱填一下(手机号、身份证号有前端的格式校验),然后点击下一步,
为什么要mock:测试过程中,很多前端字段的数据在测试单中没有,也比较难构造,比如物流轨迹等,因此从线上已有数据抓包并抓取这部分数据,用于 MOCK 这些数据
MOCK 只针对由前端渲染的字段有效
| 场景 | 接口 | MOCK截图 | 线上 | 结论 |
发货物流信息![]() |
/v3/csc/eshop/order/plus/v2/logistics | ![]() ![]() |
![]() 点击详情信息 ![]() |
❌ 各节点的物流状态没有显示,当前显示为udefined |
| 退货物流信息 | /v3/csc/eshop/dispute/detail/info | ![]() ![]() |
![]() ![]() |
❌ 物流状态颜色与线上不同 样式有点丑 |
| 评价内容等信息 | /v3/csc/eshop/dispute/detail/info | ![]() |
![]() |
✅ |
| 仓检信息 | /v3/csc/eshop/dispute/detail/info | ![]() |
![]() |
✅ |
接口:/v3/csc/eshop/order/plus/v2/logistics
logistics字段替换成下面内容
"logistics": [
{
"logisticsId": 77922784724063,
"expressNo": "776431138244005",
"expressName": "申通快递",
"logisticsState": "已签收",
"logisticsStateCode": 4,
"addressInfoVo": null,
"logisticsDetailModelVo": [
{
"time": 1747049454000,
"context": "【自提柜】包裹已签收!如有问题请联系派件员:18553922593,您的快递已经妥投,投诉电话:05392490090",
"logisticsState": "已签收",
"logisticsStateCode": 4,
"stageDesc": ""
},
{
"time": 1747046016000,
"context": "【自提柜】您的包裹已存放至心甜智能柜,记得来君悦诚园取件免存12小时,请及时取它回家!如有取件码问题或找不到包裹等问题,请联系:18553922593,如您未收到此快递,请拨打投诉电话:05392490090!",
"logisticsState": "待取件",
"logisticsStateCode": 19,
"stageDesc": ""
},
{
"time": 1747031462000,
"context": "【临沂市】山东沂南县公司 的快递员(从维霄/18553922593)正在为您派送(有事呼叫我,勿找平台,少一次投诉,多一份感恩),投诉电话:05392490090,可放心接听95089申通专属派送号码",
"logisticsState": "派送中",
"logisticsStateCode": 6,
"stageDesc": ""
},
{
"time": 1747030949000,
"context": "【临沂市】快件已到达 山东沂南县公司 咨询电话:05392490090",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1747005722000,
"context": "【临沂市】快件已发往 山东沂南县公司",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1747005012000,
"context": "【临沂市】快件已到达 山东临沂转运中心",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1746908551000,
"context": "【广州市】快件已发往 山东临沂转运中心",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1746908376000,
"context": "【广州市】快件已到达 广东增城转运中心",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1746901307000,
"context": "【广州市】快件已发往 广东增城转运中心",
"logisticsState": "运输中",
"logisticsStateCode": 1,
"stageDesc": ""
},
{
"time": 1746897521000,
"context": "【广州市】广东广州天河区东圃公司(02028187306)的仓库快手4号机(13539869275) 已揽收",
"logisticsState": "已揽件",
"logisticsStateCode": 2,
"stageDesc": ""
}
],
"latestLogisticsTime": 0,
"uploadLogisticsTime": 1746862707159,
"expressUnreachableReason": null,
"labelNames": null,
"logisticLabelNames": [],
"stageDesc": "商家 -> 买家",
"latestExpressNo": null,
"latestExpressName": null,
"latestStageDesc": null
}
],
/v3/csc/eshop/dispute/detail/info
refundLogisticsInfo字段有两处需要替换
"refundLogisticsInfo": {
"logisticsId": "9429941640476",
"logisticsName": "邮政快递包裹",
"logisticsDetail": [{
"operateTime": 1747094381000,
"content": "快件离开【清河县电商客户揽投部】,正在发往【南宫市城区集散点】",
"logisticsStatus": "在途"
}, {
"operateTime": 1747094380000,
"content": "快件已在【清河县电商客户揽投部】完成分拣,准备发出",
"logisticsStatus": "未知"
}, {
"operateTime": 1747094377000,
"content": "中国邮政 已收取快件",
"logisticsStatus": "揽件"
}],
"expressUnreachableReason": null,
"labelNames": [],
"labelIds": [],
"expressInfo": null
},
"refundLogisticsInfo": {
"logisticsId": 77831658099235,
"expressNo": "9429941640476",
"expressCompanyCode": 0,
"expressName": "邮政快递包裹",
"logisticsState": "",
"addressInfo": {
"addressId": 0,
"receiptUserName": "尧老板",
"mobile": "*******4385",
"province": "辽宁省",
"provinceCode": 0,
"city": "沈阳市",
"cityCode": 0,
"district": "沈河区",
"districtCode": 0,
"address": "滨河街道美博公寓B座16楼1608",
"townCode": 0,
"mobileEncrypted": "IwDgbALATADCEGYQFYg="
},
"sendAddressInfo": null,
"logisticsDetail": [{
"time": 1747094381000,
"context": "快件离开【清河县电商客户揽投部】,正在发往【南宫市城区集散点】",
"logisticsStateCode": 0,
"logisticsState": "在途"
}, {
"time": 1747094380000,
"context": "快件已在【清河县电商客户揽投部】完成分拣,准备发出",
"logisticsStateCode": 0,
"logisticsState": "未知"
}, {
"time": 1747094377000,
"context": "中国邮政 已收取快件",
"logisticsStateCode": 0,
"logisticsState": "揽件"
}],
"performType": 0,
"logisticsStateValue": 0,
"expressUnreachableReason": null,
"labelNames": [],
"labelIds": []
},
/v3/csc/eshop/dispute/detail/info
wareHouseAuditInfoVO字段替换
"wareHouseAuditInfoVO": {
"statusDesc": "质检通过",
"time": 1746165812875,
"failReason": "-"
},