开头先说个反直觉的结论:很多朋友遇到反爬就急着换UA、挂代理、调访问频率,结果发现该封还是封。我这两年接到最多的求助就是"我这个目标到底是不是Akamai?"——这问题问得特别好,因为先定位对防护厂商,比费尽心思调参重要十倍。Akamai旗下的Bot Manager(aka反爬体系)和你常见的Cloudflare、阿里云WAF完全不是一个物种,它检测的不只是IP和请求频率,而是从TLS握手阶段就开始拆解你的客户端身份。这篇就把我实际排查过程中用到的定位思路和判定特征梳理一遍,按这个顺序走,基本能快速确认对面究竟是不是Akamai在挡路。
值得先说清楚的是:这篇文章讲的是"识别和定位",不是教怎么打穿它。识别是制定一切后续策略的前提,把对面认清楚了,你才知道要不要上浏览器环境模拟、要不要处理tls指纹、代理资源该买什么档位——这些决策的起点都指向同一个问题:对面到底是谁。
1. 为什么定位防护厂商是反爬对抗的第一步
1.1 反爬系统的分层逻辑:你面对的不只是"一个墙"
很多开发者的认知还停留在"反爬就是检测IP和UA"的层面,但主流商业防护系统的设计早就分成了多层。我通常把它们分成三层来理解:网络层、应用层、行为层。
网络层最简单,看你的IP段、访问频率、连接特征,这层是所有防护体系的地基。应用层则复杂一些,会检查你的HTTP头是否完整、顺序是否符合真实浏览器的标准、Cookie是否完整、TLS指纹是否看起来像一个真浏览器。行为层最玄乎,它统计你鼠标轨迹、点击停留、页面操作是否像人类,甚至会把你在多个站点上的行为拼在一起做关联。
Akamai Bot Manager属于那种三层全部覆盖的"六边形选手",而且它的应用层和网络层做得尤其细致。这一点决定了你对付它时,只看headers是绝对不够的,必须同时关心TLS指纹、HTTP/2指纹、Cookie生成逻辑——这些都不是普通WAF会管的。
1.2 Akamai在爬虫对抗里的位置:和Cloudflare不是一个量级
如果你想在五分钟内判断一个站点属于哪个防护体系,直接看Cookie就行:cf_clearance是Cloudflare,_abck是Akamai,datadome是DataDome,yandex家的则是y uid。这些标记几乎是各家的名片。
Akamai的_abck是它最标志性的文件。这个名字你可能见过但没在意过——它是"Abnormal Cookie"的缩写,一个从浏览器端采集大量环境参数生成的校验凭证。而且这个Cookie不是在首次访问时就给完整版的,而是随时可能被二次验证、刷新,非常难缠。
所以定位Akamai的意义在于:一旦确认是它,你就要做好打硬仗的心理准备。它不止验证"你是不是浏览器",还会验证"你是什么品牌的浏览器、什么版本、运行在什么系统上",这些信息全被编码在那串长得离谱的_abck里。
1.3 "认错人"的代价:为什么说定位准确比蛮干重要
我见过不少团队花了数周在调UA、换代理头上,最后抓包一看,对面防护厂商是Akamai,而他们的请求体里连正常的浏览器扩展指纹都没做,失败是必然的。
反过来,如果把Cloudflare的防护当成Akamai来对付,也会浪费大量精力去做无谓的TLS改造。Cloudflare的拦截相对"结果导向",它更关注你最终能不能通过JS质询;而Akamai更像"过程稽查",它从头到尾盯着你的客户端行为记录。路线选错,后面所有投入都要打水漂。
这就是为什么我坚持把"识别防护厂商"放在反爬项目路线图的第一步。它不解决具体问题,但决定了你后续所有方案是否有效。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从HTTP响应与Cookie痕迹里找"实锤"
2.1 Cookie指纹:_abck、bm_sz与ak_bmsc
最快的判断方式就是抓一次请求,看返回的Set-Cookie里有没有Akamai家的痕迹。通常你会看到这么几个关键Cookie:
_abck:最核心的验证Cookie,值是一长串经过编码的加密字符串,包含浏览器指纹、时间戳、校验位。名字里的"abck"是"Abnormal Cookie"的意思,它由Akamai的JavaScript保护脚本生成,并根据客户端环境动态更新。bm_sz:全称大概是"Bot Manager Size",主要用于存储当前会话的与会话相关的信息,比如时间窗口、请求计数、页面加载标记等。它比_abck短一些,但也同样是指纹验证体系的一部分。ak_bmsc:Akamai Bot Manager Session Cookie,一般出现于访问初始阶段,随后会和_abck配合做二次校验。
你可以用浏览器开发者工具直接看,也可以用Python快速验证:
python复制import requests
url = "https://目标站点.example"
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36"
),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
resp = requests.get(url, headers=headers, timeout=10)
print("Server:", resp.headers.get("Server"))
print("Set-Cookie:", resp.headers.get("Set-Cookie"))
print("Cookies:", resp.cookies.get_dict())
正常来讲,如果目标是Akamai的防护站点,你会在输出里看到 _abck=... 和 bm_sz=...。如果首次访问没看到,也别急着下结论,因为有些站点把Cookie生成放在了后续某个接口请求里,甚至是页面内JavaScript执行后才写入,稍后我会讲多轮验证的思路。
2.2 响应头信息:Server、X-Akamai-Edgescape与Akamai GHOST
第二个直接证据是响应头。Akamai作为全球CDN巨头,大量使用自己的边缘节点,所以响应头里的Server字段通常不会隐藏它的身份。
常见的Server值可能是AkamaiGHost(注意这个拼写,它经常被写成GHost而不是Ghost),也可能是AkamaiGHost配合版本号。另外X-Akamai-Edgescape这个头也很有特征,它携带着边缘节点基于IP判断的地理位置等数据,基本是Akamai专属的签名。
如果用curl来看会比较直观:
bash复制curl -I -s -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0 Safari/537.36" https://目标站点.example
如果返回里出现了Server: AkamaiGHost,基本可以直接实锤。但注意,有些站点会自定义隐藏或修改Server字段,所以不能只看这一个头,要结合Cookie和TLS指纹综合判断。
2.3 请求头顺序与Header Sort特征
这一节可能是很多人没注意过的点。Akamai的JavaScript保护脚本在发起XHR请求时,有时会对请求头顺序做特定排序,或者追加特定的Header序列。因为浏览器原生发请求时,请求头的顺序是由浏览器内核决定的,而HTTP客户端库(比如requests、curl)默认的Header顺序往往和浏览器不同。
如果你用抓包工具(Fiddler、Charles、Wireshark)观察站点的真实流量,发现请求头里多出了诡异的非标准Header,比如akai_dt、X-Akamai-Request-ID、Pragma: akamai-x-cache-on之类,那也大概率跟Akamai相关。不过这条特征不如Cookie直观,适合作为辅助证据。
2.4 快速分类清单
把上面的特征整理成一张清单,遇到疑似站点时直接对照:
| 特征项 | 典型证据 | 判断强度 |
|---|---|---|
| Cookie | _abck、bm_sz、ak_bmsc |
高 |
| 响应头Server | AkamaiGHost |
中高 |
| 专属响应头 | X-Akamai-Edgescape |
高 |
| Header特征 | Pragma: akamai-x-cache-on |
中 |
| TLS/ClientHello | 排除其他厂商后仍校验严格 | 低(辅助) |
对照完这一轮,你的判断大概率能达到七成把握。但七成还不够,因为存在混合部署或反代伪装的情况,需要继续用TLS指纹和探测脚本把把握拉高到95%以上。
3. TLS指纹:最诚实的身份ID
3.1 为什么TLS指纹这么关键,而且骗不了人
如果说Cookie可以被伪造、UA可以随便改、Header顺序可以手动调,那TLS指纹就是最接近"生理特征"的身份标识。
原因在于:每次HTTPS请求的第一步都是TLS握手,客户端会发送一个ClientHello消息,里面包含它支持的加密套件列表、TLS版本、扩展字段、椭圆曲线参数等。不同的HTTP客户端库(比如curl的TLS实现、Python的requests底层OpenSSL、Chrome内的BoringSSL)在这些参数的排列组合上会有细微但稳定的差异。把这些差异算成一个哈希,就是JA3指纹;更精细一点,考虑ClientHello的扩展顺序和长度,就催生了JA4指纹。
Akamai的Bot Manager非常看重TLS指纹,因为它能直接告诉你:对面这个"声称自己是Chrome 124"的客户端,实际上是不是真的BoringSSL,还是披着UA外衣的Python脚本。这也是为什么在Akamai防护下,纯requests不发任何高级设置几乎必死。
3.2 ClientHello里值得观察的几个点
用Wireshark抓一次TLS握手,或者用tshark导出TLS记录,你会看到ClientHello里有一个长长的字段列表。和指纹判定相关的关键点主要是:
- TLS版本:真实浏览器通常支持TLS 1.2和1.3,而且优先协商1.3;许多HTTP库默认只到TLS 1.2,或者虽然支持1.3但扩展列表和浏览器不同。
- 加密套件列表:Chrome、Firefox、Safari各自支持的套件顺序不同,而requests底层的OpenSSL会暴露一套"通用型"套件组合,和浏览器差异明显。
- 扩展列表及其顺序:Chrome有
application_settings、ech_config等扩展,而Python的ssl模块默认不发这些;扩展的顺序也有讲究。
这些细节单个看可能不起眼,但组合起来就成了独一无二的指纹。Akamai不需要百分之百解析你的行为,它只需要在指纹库中找到最接近的那个"客户端画像",不一致就会被标记为可疑。
3.3 用Python快速观察TLS指纹的简化方式
不引入重型依赖的话,可以先用tshark直接看某个pcap里的JA3。假设你已经抓了包:
bash复制tshark -r capture.pcap -Y "tls.handshake.type == 1" -T fields -e tls.handshake.ja3 -e tls.handshake.ja3_full
这会输出每条TLS ClientHello的JA3值。把这个结果和Chrome的参考JA3做对比,基本能区分客户端类型。
如果你想在代码里直接验证某个域名握手时的JA3,可以借助pyshark来解析,或者写一个简化版的ClientHello解析器。这里不贴完整实现,只给思路:解析出ClientHello后,依次提取TLS版本、CipherSuites、Extensions、EllipticCurves、ECPointFormats,然后按固定拼接规则做MD5或SHA256,就是JA3的核心逻辑。
有一个更实用的习惯是:把目标站点在真实浏览器里访问时的JA3,和requests访问时的JA3拉到一起对比。如果两个指纹差异极大,而站点对后者的响应明显更严格,那它大概率做了TLS层面的检测——这也是判断防护层级的重要实验。
4. 把特征串起来:一个可跑的识别流程
4.1 识别逻辑不是"一票定案"
前面讲的每个特征单独拿出来,都可能被误判或躲过。Server字段可能是改过的,_abck可能有延迟加载的,TLS指纹也可能因为目标站点本身跑在非Akamai边缘节点上而变得不明显。所以实战里的识别逻辑永远是多特征加权,而不是一票定案。
我一般按照"Cookie > TLS > 响应头 > 行为"的优先级来打分。只要_abck出现了,不管其他特征多模糊,先把Akamai嫌疑拉满;如果看到Server: AkamaiGHost和bm_sz同时存在,就可以基本确认了。
4.2 脚本实现:多特征采集与打分
下面给一个可以直接跑通的短脚本,它会主动访问目标站点,采集Cookie、响应头,以及基本的TLS协商结果,然后输出一个判断建议。注意这段代码只做识别,不包含任何对抗操作。
python复制import requests
import ssl
import socket
from collections import Counter
def get_tls_version(host: str, port: int = 443) -> str:
ctx = ssl.create_default_context()
with socket.create_connection((host, port), timeout=8) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as tls:
return tls.version()
def analyze(url: str) -> None:
score = 0
evidence = []
try:
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36"
),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
}
resp = requests.get(url, headers=headers, timeout=10)
host = resp.url.split("//")[1].split("/")[0]
# 字节级Cookie检查
cookie_names = [c.name for c in resp.cookies]
if "_abck" in cookie_names:
score += 3
evidence.append("发现 _abck Cookie")
if "bm_sz" in cookie_names:
score += 2
evidence.append("发现 bm_sz Cookie")
if "ak_bmsc" in cookie_names:
score += 2
evidence.append("发现 ak_bmsc Cookie")
# 响应头检查
server = resp.headers.get("Server", "")
if "akamai" in server.lower():
score += 2
evidence.append(f"Server 头包含 akamai 特征: {server}")
if "x-akamai" in resp.headers:
score += 2
evidence.append("存在 X-Akamai-* 响应头")
# TLS版本观察(只做记录,不构成强特征)
tls_ver = get_tls_version(host)
evidence.append(f"TLS 协商版本: {tls_ver}")
print(f"目标: {url}")
print(f"综合得分: {score}")
for item in evidence:
print(f" - {item}")
if score >= 5:
print("结论: 防护体系高度疑似 Akamai")
elif score >= 3:
print("结论: 存在 Akamai 特征,建议进一步抓包确认")
else:
print("结论: 未发现明显 Akamai 特征,需要扩大探测范围")
except Exception as e:
print(f"请求失败: {e}")
if __name__ == "__main__":
analyze("https://目标站点.example")
这段代码没有做任何复杂的运算,核心逻辑就是用普通requests去请求一次,然后把Cookie名、响应头、TLS版本记录成结构化证据。实际诊断时,我会重复请求三次以上,观察Cookie是否在不同轮次中出现或更新,因为Akamai可能在第一轮先放行、第二轮下发校验请求,只跑一次容易漏判。
4.3 结果怎么看:分清"边缘CDN"和"Bot Manager"
还有一个特别容易踩的认知陷阱:有些网站仅仅使用了Akamai的CDN加速,并没有启用Bot Manager反爬。这种情况下你也能看到AkamaiGHost或X-Akamai-*响应头,但访问起来非常顺畅,requests直接抓也能拿到HTML。
这说明你遇到了Akamai家产品线的"CDN层",而不是"防护层"。通过脚本判断时,如果Cookie里一直没有_abck、bm_sz,且请求都没有遇到质询或跳转,就不要急着把站点归类为"高深反爬"。真正启用Bot Manager的站点,几乎必然在某个环节给客户端植入这些Cookie,或者响应里带上ak_bmsc。
所以识别结果里我会写上"是CDN还是Bot Manager"的备注,避免把两类场景混为一谈。
5. 容易被误判的相似系统:Cloudflare、AWS WAF与Akamai的区分
5.1 Cloudflare的核心差异:cf-ray和__cf_bm
Cloudflare是目前最容易和Akamai混在一起讨论的厂商,因为两者都是大型CDN+安全方案提供商。但它们的识别特征区别很大。Cloudflare通常会在响应头里带cf-ray,这个头记录了请求经过的Cloudflare边缘节点编号。Cookie方面,Cloudflare的经典凭证是cf_clearance(通过质询后发放)和__cf_bm(用于Bot Management的会话Cookie)。
从技术路线上讲,Cloudflare更偏向"挑战-响应"模式:先让所有可疑请求跑一段JavaScript质询,算出一个PoW结果,验证通过后发放短时有效的cf_clearance。Akamai则更偏向"持续监督":它不发一次性质询,而是通过_abck在多轮请求里不断更新校验状态,悄悄观察你的行为。这种设计差异导致两者的应对策略完全不同。
5.2 其他防护方案:DataDome、PerimeterX与AWS WAF
另一个常见误判是DataDome。它的Cookie特征非常明显,会出现一个名字就叫datadome的Cookie,短横线或下划线都很常见。DataDome的拦截同样强悍,但它的指纹维度以HTTP2指纹和头部顺序为主,和Akamai偏TLS+行为侧的思路略有差别。
还有Humio或者说PerimeterX(现在叫Human Security),它的标志性Cookie是pxhd、px_captcha等。AWS WAF虽然也带反爬能力,但它更多依赖于规则组和托管规则,在不启用Bot Control时很少下发特征Cookie,从请求头上看往往只有x-amz-cf-id这类CloudFront痕迹。
简单整理一个区分表:
| 防护方案 | 特征头 | 特征Cookie | 关键词 |
|---|---|---|---|
| Akamai | AkamaiGHost, X-Akamai-Edgescape |
_abck, bm_sz, ak_bmsc |
TLS指纹, 持续校验 |
| Cloudflare | cf-ray, server: cloudflare |
cf_clearance, __cf_bm |
JS质询, PoW |
| DataDome | server: DataDome |
datadome |
HTTP2指纹 |
| Human Security | 无典型 | pxhd |
行为分析 |
| AWS WAF | x-amz-cf-id |
默认无 | 规则组 |
5.3 混合部署形态:识别要认"最后一层风控"
实际项目里,目标站点可能是Akamai CDN + Cloudflare DNS + 自研风控的组合,也可能前面套了一层阿里云WAF、后面才是Akamai Bot Manager。这种情况下,只看入口处的响应头容易得出错误结论。
我建议把识别目标定义成"最后一层风控是谁",而不是"第一层CDN是谁"。方法很简单:遍历几个关键路径(首页、登录API、搜索接口),看哪一层的特征会直接决定你请求的成败。如果首页响应头是Sun或nginx,但登录接口返回了_abck校验失败,那真正的boss是Akamai,而不是前面的nginx。
6. 从"认出来"到"知道该怎么准备":我的实战体会
6.1 识别结果如何影响后续技术选型
一旦确认目标防护是Akamai Bot Manager,你就要调整技术选型了。很多通用爬虫框架在它面前失灵,不是框架本身不好,而是它们默认的HTTP客户端指纹暴露得太明显。你需要配置更贴近真实浏览器的TLS客户端、维护完整的Header顺序、处理JavaScript采集到的环境参数,以及准备足够干净的代理资源。
反过来,如果确认只是CDN层而没有启用Bot Manager,那就可以用最常规的requests方案直接做,不需要过度工程。这一正一反的差别,每年能帮你省下大量的开发时间和服务器成本。
6.2 合规与边界:识别是技术研究,不是攻击许可
每次聊到反爬识别,我都想强调一个边界问题。识别防护厂商本身是安全研究和爬虫策略中常见的环节,这就像了解一个网站的登录机制一样,属于技术分析。但一旦把识别结果用于绕过防护、突破访问控制、抓取未授权数据,就可能触碰法律和平台规则的红线。
我在写这篇文章时也刻意把内容控制在"定位和识别"层面上。如果你是在做毕业设计、安全测试、或者对自己名下的站点做防护分析,那这些思路完全够用。如果目标是未授权抓取商业数据,建议先认真阅读目标站点的robots协议和服务条款,必要时咨询法务意见——这是负责任的做法,也是行业里成熟工程师的基本素养。
6.3 几个容易踩坑的细节补充
最后分享几个实际排查中的小细节,这些往往不在文档里。
第一个细节:_abck不是一次请求就固定的,它可能在页面交互中被更新,也可能在某些接口里忽然从无到有。所以识别时多跑几个路径,别只测首页。
第二个细节:如果你看到某个响应里同时出现Server: AkamaiGHost和HTTP/2 403,不要急着说"一定是Akamai拦截",先检查是否因为缺少某个必要的Cookie或Header,可能是站点自己的业务逻辑校验,而不是Bot Manager的防御。
第三个细节:Wireshark抓包观察TLS指纹时,注意从"HTTP/2连接前协商"看起,因为Akamai对HTTP/2的指纹检测比HTTP/1.1更严格。有时候你明明看到JA3是浏览器的,但还是被识别,问题可能出现在HTTP/2的SETTINGS帧参数上——这个信号同样能暴露客户端是不是真实浏览器。
第四个细节:如果你有多个代理出口IP,试着用不同IP访问同一站点,观察Akamai返回的bm_sz数值差异。同一客户端在不同IP下如果拿到完全不同的挑战页面,说明IP信誉度也是它评估的一部分。这个测试能帮你判断代理池质量对整体成功率的影响系数。
这些经验都来自我一次次抓包、对比、翻代码的实战过程。识别Akamai这件事本身并不复杂,难的是别在第一步就搞错方向。希望这篇能帮你在下次遇到"高深反爬"时,先稳稳地认出对面是谁,再做下一步打算。
