Python使用requests发送bytes类型Cookie触发TypeError问题咨询
报错核心原因
- 你直接从Edge的SQLite Cookie库读出来的bytes值是DPAPI+AES-GCM加密后的密文,不是原始Cookie明文,且requests库的cookies参数仅接受字符串类型的键值对,传入bytes类型值时,内部处理逻辑会拿字符串
"调用bytes的startswith方法,触发类型错误。 - 你之前尝试UTF-8解码、强转字符串失败,是因为加密后的字节包含大量非UTF-8编码的不可打印字符,根本不是合法的文本编码内容,强行解码只会得到乱码。
- 你写的
get_cookies函数本身逻辑有误:返回的字典结构是「字段名对应该字段所有行的取值列表」,不是requests要求的「Cookie名对应单个Cookie值」的键值对,就算解密完成也无法直接使用。
可行解决步骤
1. 安装依赖
需要用到两个库完成解密和系统接口调用,执行安装命令:
pip install pycryptodome pywin32
2. 修正Cookie读取逻辑,完成解密
Chromium内核的Edge浏览器从v80版本开始,采用系统DPAPI加密存储AES主密钥,再用该主密钥以AES-GCM模式加密每个Cookie的具体值,必须按以下流程解密才能拿到可用的明文Cookie:
- 读取Edge配置目录下的
Local State文件,提取加密的主密钥,通过Windows DPAPI解密得到AES密钥 - 连接Cookie的SQLite数据库,查询每个Cookie的名称、加密值、域名、路径等属性
- 对每个加密的Cookie值,按AES-GCM规则拆分nonce、密文、认证标签,解密得到明文字符串
- 组装成requests可识别的Cookie字典或CookieJar对象
3. 可直接复用的实现代码
import os import json import base64 import sqlite3 import win32crypt from Crypto.Cipher import AES import requests def get_edge_cookies(target_domain=None): # 本地State文件路径,存储加密主密钥 state_path = os.path.join(os.environ['LOCALAPPDATA'], r'Microsoft\Edge\User Data\Local State') # Cookie数据库路径 cookie_db_path = os.path.join(os.environ['LOCALAPPDATA'], r'Microsoft\Edge\User Data\Default\Network\Cookies') # 解密AES主密钥 with open(state_path, 'r', encoding='utf-8') as f: state_data = json.load(f) encrypted_key = base64.b64decode(state_data['os_crypt']['encrypted_key']) # 去掉DPAPI前缀 encrypted_key = encrypted_key[5:] aes_key = win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1] # 连接Cookie数据库,注意读取前请完全关闭Edge,否则文件被锁会报错 conn = sqlite3.connect(cookie_db_path) cursor = conn.cursor() # 查询必要字段,支持按域名过滤 if target_domain: cursor.execute('SELECT name, encrypted_value FROM cookies WHERE host_key LIKE ?', (f'%{target_domain}%',)) else: cursor.execute('SELECT name, encrypted_value FROM cookies') cookies_dict = {} for name, encrypted_value in cursor.fetchall(): # 解密单个Cookie值,v10前缀代表是新加密模式的Cookie if encrypted_value[:3] == b'v10': nonce = encrypted_value[3:15] ciphertext = encrypted_value[15:-16] tag = encrypted_value[-16:] cipher = AES.new(aes_key, AES.MODE_GCM, nonce=nonce) # 解密得到明文bytes,转成字符串 cookie_value = cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8') cookies_dict[name] = cookie_value conn.close() return cookies_dict # 调用示例,传入目标网站域名过滤对应Cookie cookies = get_edge_cookies(target_domain='linktowebsite.com') r = requests.post('https://linktowebsite.com', cookies=cookies) print(r.status_code)
注意事项
- 运行代码前必须完全关闭所有Edge进程,否则Cookie数据库文件会被浏览器锁定,无法读取。
- 如果遇到Cookie跨域名、过期时间校验不通过的问题,可以把解密后的Cookie属性组装成
RequestsCookieJar对象传入,兼容性比纯字典更好。 - 该方法仅适用于Windows系统下的Edge/Chrome等Chromium内核浏览器,macOS/Linux下的密钥存储逻辑不同,需要对应调整密钥解密部分的代码。
内容的提问来源于stack exchange,提问作者Omaro_IB
相关产品推荐
相关产品推荐

