将 key code 批量转换为 ChatGPT Web 会话 JSON,输出 CPA 和 Sub2API 两种格式。
运行前必须满足以下条件:
- 安装 Python 3.9+
- 安装依赖
pip install -r requirements.txt- 安装 Patchright Chrome
patchright install chrome- 启动本地 FlareSolverr
默认地址为 http://127.0.0.1:8191/v1。程序会在使用浏览器代理时调用它预解 Cloudflare。
- 如果使用代理
- 代理只作用于浏览器和 FlareSolverr 链路,不作用于邮件接口请求
- 推荐格式:
http://...、https://...、socks4://...、socks5://... - 代理较慢时,可能需要调大
config.py里的EMAIL_FORM_STABILIZE_SECONDS和EMAIL_POST_SUBMIT_TIMEOUT_SECONDS - 邮件接口请求超时由
MAIL_API_TIMEOUT控制 - 如果 key 取件服务器不是默认地址,可以用
--mail-server-base-url覆盖 --mail-server-base-url只影响mail-keys/mail-code两个接口,不影响浏览器代理或 FlareSolverr
- 如果要启用 CPA 存活邮箱过滤(可选)
- 需要一个可访问的 CLIProxyAPI 管理接口
- 需要能访问
/v0/management/auth-files的 Bearer Token - 程序会先取回 CPA 里仍可用的邮箱,再和 key 接口返回的邮箱比对,跳过已存在且仍存活的账号
准备你自己的输入文件,例如 keys.txt。仓库只保留脱敏样例 keys.example.txt。
python main.py --key "AAAA-BBBB-CCCC"python main.py --input keys.txtpython main.py --input keys.txt --mail-server-base-url "https://plus.keria.cc.cd"也支持直接传到 /api/pickup:
python main.py --input keys.txt --mail-server-base-url "https://plus.keria.cc.cd/api/pickup"也可以通过环境变量提供:
set MAIL_SERVER_BASE_URL=https://plus.keria.cc.cd
python main.py --input keys.txtpython main.py --input keys.txt --proxy "socks5://127.0.0.1:1080"python main.py --input keys.txt --skip-active-cpa-emails --cpa-management-url "http://127.0.0.1:8317" --cpa-management-key "<MANAGEMENT_TOKEN>"也可以通过环境变量提供:
set CPA_MANAGEMENT_URL=http://127.0.0.1:8317
set CPA_MANAGEMENT_KEY=<MANAGEMENT_TOKEN>
python main.py --input keys.txt --skip-active-cpa-emailspython main.py [选项]
选项:
--key KEY
--input FILE
--format {cpa,sub2api,both}
--headless
--proxy PROXY
--flaresolverr-url FLARESOLVERR_URL
--mail-server-base-url MAIL_SERVER_BASE_URL
--skip-active-cpa-emails
--cpa-management-url CPA_MANAGEMENT_URL
--cpa-management-key CPA_MANAGEMENT_KEY程序会按下面的页面状态推进,并在关键节点检查当前页面是否符合预期:
email填邮箱前会额外等待一段时间,避免代理环境下页面尚未稳定导致空提交password(可选) 某些账号会先落到密码页;程序会自动点击“使用一次性验证码登录”one_time_code获取最新验证码并提交logged_in提取https://chatgpt.com/api/auth/session
成功后会立即:
- 导出 session
- 写入
output/ - 关闭浏览器窗口
这属于当前设计,不是异常。
生成的文件位于 ./output/:
{email_key}_cpa.json{email_key}_sub2api.json
程序默认不会清空整个 output/ 目录,只会创建目录并覆盖同名账号文件。
这些文件包含真实会话信息,默认不应提交到仓库。
启用 --skip-active-cpa-emails 后,程序会请求 CLIProxyAPI 的管理接口 /v0/management/auth-files,读取其中的邮箱,并按下面规则认定为“仍存活”:
- 有有效
email unavailable不为truestatus不属于error、expired、invalid、revoked、unavailable
disabled 状态不会被额外处理。
如果不想在命令行里重复输入,可以使用下面几个环境变量:
MAIL_SERVER_BASE_URLCPA_MANAGEMENT_URLCPA_MANAGEMENT_KEY
每次运行都会生成:
logs/run-YYYYMMDD-HHMMSS.log- 失败时的
artifacts/*.png - 失败时的
artifacts/*.html - 失败时的
artifacts/*.txt
建议排障顺序:
- 先看控制台里的失败摘要
- 再看对应的
logs/run-*.log - 如果是页面问题,再打开
artifacts/下的截图和 HTML
仓库默认忽略以下内容:
keys.txtoutput/logs/artifacts/browser_profile/browser_profile_probe*/- 调试截图和临时 bundle
如果需要分享仓库,请只保留代码、文档和脱敏样例,不要保留:
- key 输入文件
- 导出的 session JSON
- 浏览器 profile
- 调试截图
这是正常行为。程序已经提取 session 并写入 output/,随后自动关闭浏览器。
先看日志里的页面状态输出:
- 如果还停在
email,通常是代理环境下页面接管较慢 - 如果跳到
password,程序会自动回退到“一次性验证码登录” - 如果长时间未到
one_time_code,优先调大config.py中的等待时间
- 先确认
http://127.0.0.1:8191/返回FlareSolverr is ready! - 程序会打印错误并继续尝试原始浏览器流程
优先调整:
EMAIL_FORM_STABILIZE_SECONDSEMAIL_POST_SUBMIT_TIMEOUT_SECONDSFLARESOLVERR_MAX_TIMEOUT
检查控制台是否出现:
Session extracted successfullySaved CPASaved Sub2API
如果已经看到 Session extracted successfully,但最后仍然失败,优先看:
output/是否可写- 运行日志里是否出现
Failed to save ... - 控制台打印的绝对输出路径是否符合预期
现在失败信息会附带:
- 当前阶段的页面状态
- 失败时保存下来的截图 / HTML / 文本状态文件路径
- 本次运行的日志文件路径
keytoauth/
├── api_client.py
├── browser_automation.py
├── config.py
├── keys.example.txt
├── main.py
├── README.md
├── requirements.txt
├── session_converter.py
├── test_browser_automation_helpers.py
└── test_runtime_helpers.py
ruff check api_client.py browser_automation.py config.py main.py test_browser_automation_helpers.py test_runtime_helpers.py
python -m unittest test_browser_automation_helpers.py test_runtime_helpers.py