Claude iOS 旧 session 卡死:Quantumult X 强制退出登录方案
Claude iOS 卡在 Something went wrong 时,如何用 Quantumult X 强制回到登录页
适用场景:Claude iOS App 打开后一直停在
Something went wrong / Try again,点击重试无效,卸载重装也没有恢复;同时你在 Quantumult X 的网络活动中能看到 Claude App 反复请求https://claude.ai/api/account?。这个方案不是用来修复代理线路、节点质量或 Claude 服务端故障。它的目标很单一:临时伪造一次“登录态已过期”的响应,让 Claude iOS App 主动退出异常 session,回到登录页。
重要提醒:成功看到登录页后,必须立刻关闭这条 rewrite 规则。不要长期启用。
适合解决什么问题
这个方法适合处理一种比较典型的卡死状态:
- Claude iOS App 启动后直接显示
Something went wrong或Try again。 - 点
Try again没有明显变化。 - 切换节点、重启 App、卸载重装后仍然卡住。
- Quantumult X 的网络活动里可以看到 Claude App 在请求:
https://claude.ai/api/account?
- 你怀疑 App 本地保存的旧登录态、cookie 或 session 已经异常,但 App 没有自动跳回登录页。
如果你的问题是完全无法连接 Claude、TLS 握手失败、节点不支持、DNS 错误、区域不可用,或者根本看不到 Claude App 发起 /api/account 请求,那么这篇方法不一定适用。先把网络和代理本身排查好。
原理说明
Claude iOS App 启动时会访问账号接口,大致是:
https://claude.ai/api/account?
正常情况下,这个接口会根据当前 cookies 判断你是否已经登录。如果旧 session 已经过期或异常,服务端应该返回未登录或 session 失效,然后 App 回到登录页。
但在某些情况下,App 可能持续带着旧的 session cookies 请求接口,却没有顺利完成退出登录流程,于是卡在错误页。
Quantumult X 的 MITM 和 rewrite 可以临时拦截这个请求,直接返回一个伪造的响应:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
Set-Cookie: sessionKey=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/; Domain=claude.ai; Secure; HttpOnly; SameSite=Lax
set-cookie: routingHint=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/; Domain=claude.ai; Secure; HttpOnly; SameSite=Lax
响应 body 返回:
{
"error": {
"type": "session_expired",
"message": "Session expired. Please log in again."
}
}
这样做的效果是:
- Claude App 认为当前登录态已经过期。
sessionKey和routingHint被设置为过期。- App 不再继续使用旧 session。
- App 回到登录页。
关键点是:Set-Cookie 必须写在响应头里,而不是请求头里。
不要把真实 cookie、sessionKey、routingHint 发给别人,也不要发到群里让别人帮你看。
操作前准备
你需要准备:
- iPhone 上已安装 Quantumult X。
- Quantumult X 已经可以正常代理 Claude 相关流量。
- Quantumult X 的 MITM 证书已经安装并在 iOS 中信任。
- 你能编辑 Quantumult X 配置文件。
- 你能在 iPhone 的“文件”App 里找到 Quantumult X 的
Scripts目录。
如果你平时没有开启 Quantumult X 的 rewrite 功能,记得稍后在 Quantumult X 里打开 rewrite 开关。
第一步:确认 Claude 请求域名
先打开 Quantumult X,进入网络活动或请求日志,重新打开 Claude App,观察 Claude 请求的是哪个域名。
优先确认有没有这类请求:
claude.ai:443
https://claude.ai/api/account?
如果看到的是:
https://claude.ai/api/account?
本文后面的默认配置就可以直接用。
如果你看到的是:
https://api.claude.ai/api/account?
先不要急着照抄默认规则,后面“如果请求变成 api.claude.ai”一节有对应改法。
第二步:配置 MITM
打开 Quantumult X 配置文件,找到 [mitm] 部分。
如果你已经有 [mitm],不要再新建一个 [mitm],只需要把 claude.ai 加到原来的 hostname 后面。
例如你原本是:
[mitm]
hostname = example.com, example.org
改成:
[mitm]
hostname = example.com, example.org, claude.ai
如果你原本没有配置过 MITM,可以添加:
[mitm]
hostname = claude.ai
保存配置后,确认 Quantumult X 的 MITM 开关是开启状态。
第三步:安装并信任 Quantumult X 证书
只有把 Quantumult X 的 CA 证书安装并信任,Quantumult X 才能解密 HTTPS 请求并让 rewrite 对 https://claude.ai/api/account? 生效。
一般流程是:
- 打开 Quantumult X。
- 进入设置或 MitM 相关页面。
- 生成并安装 CA 证书。
- iOS 会跳转到描述文件安装流程。
- 安装描述文件。
- 回到 iOS 设置,手动信任证书。
iOS 信任路径通常是:
iOS 设置
→ 通用
→ 关于本机
→ 证书信任设置
→ 打开 Quantumult X CA 的完全信任
这一步经常被漏掉。只安装证书但没有在“证书信任设置”里打开信任,MITM 仍然不会真正生效。
第四步:创建脚本文件
在 iPhone 上打开“文件”App,进入:
我的 iPhone / Quantumult X / Scripts
这是脚本必须存放的位置。建议按下面的方式逐级确认:
文件 App
→ 浏览
→ 我的 iPhone
→ Quantumult X
→ Scripts
如果你在“我的 iPhone”下面看不到 Quantumult X 文件夹,可以先打开一次 Quantumult X,确认应用已经创建本地目录;也可以在 Quantumult X 内部的脚本管理页面新建脚本。
建议准备两个脚本文件:
claude_force_logout_stable.js
claude_force_logout_aggressive.js
两个文件都放在:
我的 iPhone / Quantumult X / Scripts
注意文件名要完全一致,尤其是:
- 不要写成
.js.txt。 - 不要把下划线写成短横线。
- 不要改大小写。
- 不要放到
Downloads、iCloud Drive或其他目录。 - 不要把脚本内容粘到 Quantumult X 配置文件里,脚本和配置是两个不同位置。
第五步:稳定版脚本
稳定版用于第一轮尝试。它只处理 claude.ai 的 /api/account,匹配范围小,误伤概率最低。
新建文件:
claude_force_logout_stable.js
把下面脚本完整复制进去:
/**
* Claude iOS Force Logout for Quantumult X
*
* File name:
* claude_force_logout_stable.js
*
* Storage path on iPhone:
* 文件 App / 浏览 / 我的 iPhone / Quantumult X / Scripts
*
* Quantumult X usage:
* Use with "script-echo-response", not "script-response-body".
*
* Mode:
* Stable / precise.
*
* Purpose:
* Return a synthetic 401 response for Claude account endpoint,
* so Claude iOS App treats the old session as expired and goes
* back to the login page.
*/
const requestUrl = $request && $request.url ? $request.url : "";
const expiredAt = "Thu, 01 Jan 1970 00:00:00 GMT";
function expireCookie(name, domain) {
return [
`${name}=`,
`Expires=${expiredAt}`,
"Max-Age=0",
"Path=/",
`Domain=${domain}`,
"Secure",
"HttpOnly",
"SameSite=Lax"
].join("; ");
}
console.log("[Claude Force Logout][stable] matched: " + requestUrl);
$notify("Claude Force Logout", "stable matched /api/account", requestUrl);
const body = JSON.stringify({
error: {
type: "session_expired",
message: "Session expired. Please log in again."
}
});
const headers = {
"Content-Type": "application/json; charset=utf-8",
"Cache-Control": "no-store",
"Pragma": "no-cache",
"Expires": "0",
// Quantumult X 的 headers 是对象,重复 Set-Cookie 不一定稳定。
// 这里用不同大小写分别写出两条过期 cookie,提高兼容性。
"Set-Cookie": expireCookie("sessionKey", "claude.ai"),
"set-cookie": expireCookie("routingHint", "claude.ai")
};
$done({
status: "HTTP/1.1 401 Unauthorized",
headers: headers,
body: body
});
稳定版脚本做了三件事:
- 在日志里输出
[Claude Force Logout][stable] matched,方便确认是否命中。 - 弹出一条 Quantumult X 通知,显示脚本已匹配
/api/account。 - 返回
401 Unauthorized,并尝试清掉旧的sessionKey和routingHint。
第六步:更积极版脚本
如果稳定版没有效果,或者你在 Quantumult X 日志里看到 Claude 实际请求的是 api.claude.ai,再使用这个更积极版。
积极版做了两类加强:
- 配合 rewrite 同时匹配
claude.ai和api.claude.ai。 - 响应头里尝试清理更多 domain 变体,并增加
Clear-Site-Data。
新建文件:
claude_force_logout_aggressive.js
把下面脚本完整复制进去:
/**
* Claude iOS Force Logout for Quantumult X
*
* File name:
* claude_force_logout_aggressive.js
*
* Storage path on iPhone:
* 文件 App / 浏览 / 我的 iPhone / Quantumult X / Scripts
*
* Quantumult X usage:
* Use with "script-echo-response", not "script-response-body".
*
* Mode:
* Aggressive / broader account-endpoint matching.
*
* Use this only when:
* 1. Stable mode did not bring Claude iOS back to login page; or
* 2. Quantumult X logs show requests to api.claude.ai.
*
* Disable the rewrite immediately after Claude shows the login page.
*/
const requestUrl = $request && $request.url ? $request.url : "";
const expiredAt = "Thu, 01 Jan 1970 00:00:00 GMT";
const cookieNames = ["sessionKey", "routingHint"];
const cookieDomains = ["claude.ai", ".claude.ai", "api.claude.ai"];
function expireCookie(name, domain) {
return [
`${name}=`,
`Expires=${expiredAt}`,
"Max-Age=0",
"Path=/",
`Domain=${domain}`,
"Secure",
"HttpOnly",
"SameSite=Lax"
].join("; ");
}
const expiredCookies = [];
for (const domain of cookieDomains) {
for (const name of cookieNames) {
expiredCookies.push(expireCookie(name, domain));
}
}
console.log("[Claude Force Logout][aggressive] matched: " + requestUrl);
$notify("Claude Force Logout", "aggressive matched /api/account", requestUrl);
const body = JSON.stringify({
error: {
type: "session_expired",
message: "Session expired. Please log in again."
}
});
const headers = {
"Content-Type": "application/json; charset=utf-8",
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
"Pragma": "no-cache",
"Expires": "0",
// 部分客户端会忽略这个头,但加上它可以更积极地提示清理站点数据。
// 只在 claude.ai / api.claude.ai 的 /api/account 临时使用。
"Clear-Site-Data": "\"cookies\", \"storage\", \"cache\""
};
// Quantumult X 的 headers 是对象,不能自然表达多条同名 Set-Cookie。
// 这里故意使用不同大小写的 Set-Cookie 头名,尽量让多条过期 cookie 被写出。
// 如果 Quantumult X 或系统网络栈最终只保留其中一条,也不会影响 401 退出登录的核心逻辑。
const setCookieHeaderNames = [
"Set-Cookie",
"set-cookie",
"SET-COOKIE",
"Set-cookie",
"sEt-Cookie",
"seT-Cookie"
];
for (let i = 0; i < expiredCookies.length && i < setCookieHeaderNames.length; i++) {
headers[setCookieHeaderNames[i]] = expiredCookies[i];
}
$done({
status: "HTTP/1.1 401 Unauthorized",
headers: headers,
body: body
});
积极版仍然只建议用于 /api/account。不要写成匹配 Claude 的所有接口,否则登录后会继续异常。
第七步:添加 rewrite 规则
继续编辑 Quantumult X 配置文件,找到 [rewrite_local]。
稳定版 rewrite
^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_stable.js
如果你的配置里还没有 [rewrite_local],完整写法是:
[rewrite_local]
^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_stable.js
更积极版 rewrite
如果稳定版无效,或者日志里出现 api.claude.ai,把稳定版规则注释掉,改用这一条:
^https:\/\/(?:claude\.ai|api\.claude\.ai)\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
完整写法是:
[rewrite_local]
^https:\/\/(?:claude\.ai|api\.claude\.ai)\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
这里有几个容易写错的地方:
- 使用的是
script-echo-response。 - 不是
script-response-body。 - 规则匹配的是
/api/account。 - 稳定版脚本名是
claude_force_logout_stable.js。 - 积极版脚本名是
claude_force_logout_aggressive.js。 - 规则应该放在
[rewrite_local]下面。 - 稳定版和积极版不要同时开启,先开稳定版,无效再切积极版。
为什么用 script-echo-response?
因为这个场景需要 Quantumult X 直接构造一个完整响应,包括 HTTP 状态码、headers 和 body。script-echo-response 更接近 Charles Rewrite 里“直接返回一个伪造响应”的效果。
第八步:确认 Quantumult X 开关
在运行 Claude App 前,检查 Quantumult X:
- 代理已开启。
- MITM 已开启。
- Rewrite 已开启。
- 配置文件已保存并重新加载。
[mitm]里包含claude.ai。[rewrite_local]里有刚才那条规则。Scripts目录里有对应脚本。- 稳定版只开启
claude_force_logout_stable.js对应 rewrite。 - 积极版只开启
claude_force_logout_aggressive.js对应 rewrite。
如果你不确定配置是否重新加载,可以在 Quantumult X 里手动更新或重新载入配置。
第九步:触发修复
按下面顺序操作:
- 打开 Quantumult X。
- 确认代理、MITM、rewrite 都已经开启。
- 后台彻底划掉 Claude App。
- 重新打开 Claude App。
- 观察 Quantumult X 的日志或网络活动。
如果稳定版规则命中,你应该能看到日志:
[Claude Force Logout][stable] matched
如果积极版规则命中,你应该能看到日志:
[Claude Force Logout][aggressive] matched
也可能看到 Quantumult X 弹出通知:
Claude Force Logout
stable matched /api/account
这说明 Claude App 的 /api/account 请求已经被脚本接管。
如果一切正常,Claude iOS App 应该会从 Something went wrong / Try again 返回登录页。
第十步:成功后立刻关闭规则
这是最重要的一步。
一旦 Claude App 出现登录页,马上回到 Quantumult X,把 rewrite 规则关掉。
如果你用的是稳定版,把这一行注释掉:
;^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_stable.js
如果你用的是积极版,把这一行注释掉:
;^https:\/\/(?:claude\.ai|api\.claude\.ai)\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
也可以直接删除这行。
如果你不再需要 MITM Claude,也可以从 [mitm] 的 hostname 里移除:
claude.ai
api.claude.ai
为什么必须关闭?
因为只要这条规则还开着,Claude App 每次请求 /api/account 都会被 Quantumult X 强制返回 401 Unauthorized。你即使重新登录,App 也可能继续被踢回登录态失效,导致新的异常。
这个规则只应该短时间开启,用完就关。
如何判断 MITM 和 rewrite 是否生效
在 Quantumult X 网络活动里观察 Claude 请求。
如果看到:
claude.ai:443
https://claude.ai/api/account?
旁边有绿色开锁,一般说明 MITM 已经生效。
如果请求旁边有粉色铅笔图标,通常说明 rewrite 规则命中了。
如果日志中出现:
[Claude Force Logout][stable] matched
或:
[Claude Force Logout][aggressive] matched
说明脚本已经执行。
如果既没有绿色开锁,也没有脚本日志,大概率是 MITM、证书信任、rewrite 开关或域名匹配没有配置好。
如果没有效果,按这个顺序排查
先检查 MITM:
[mitm]里是否有hostname = claude.ai。- Quantumult X 的 MITM 功能是否开启。
- iOS 是否已经信任 Quantumult X CA。
- 网络活动中
claude.ai:443是否显示绿色开锁。
再检查 rewrite:
- 规则是否写在
[rewrite_local]下面。 - Quantumult X 的 rewrite 开关是否开启。
- 规则是否是
script-echo-response。 - 规则里的正则是否匹配
/api/account。
再检查脚本:
- 脚本是否放在
我的 iPhone / Quantumult X / Scripts。 - 稳定版文件名是否严格为
claude_force_logout_stable.js。 - 积极版文件名是否严格为
claude_force_logout_aggressive.js。 - 文件是否真的以
.js结尾,而不是.js.txt。 - 脚本内容是否完整复制。
最后检查 Claude 实际请求:
- Claude App 是否真的请求
https://claude.ai/api/account?。 - 是否请求了别的域名。
- 是否根本没有发起
/api/account请求。
如果请求变成 api.claude.ai
有些情况下,你在日志里看到的可能不是:
https://claude.ai/api/account?
而是:
https://api.claude.ai/api/account?
这时需要同时改 MITM 和 rewrite。
MITM 改成:
[mitm]
hostname = claude.ai, api.claude.ai
rewrite 改为积极版:
^https:\/\/(?:claude\.ai|api\.claude\.ai)\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
也可以写成两条更直观的规则:
[rewrite_local]
^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
^https:\/\/api\.claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
不过没有必要一开始就扩大范围。建议先根据 Quantumult X 网络活动里实际看到的域名来配置。
常见错误
1. 把 Set-Cookie 写到了请求头
这个方案需要伪造响应,让 App 接收 401 Unauthorized 和过期 cookie。
所以 Set-Cookie 必须写在 response headers。写在 request headers 不会达到清理 App session 的效果。
2. 用了 script-response-body
script-response-body 更偏向修改服务端已经返回的 body。
这个场景需要直接构造响应,建议使用:
script-echo-response
3. 忘记信任证书
只在 Quantumult X 里生成或安装证书还不够。iOS 必须在“证书信任设置”里打开完全信任。
4. 成功后忘记关闭规则
这是最容易导致新问题的错误。
如果规则一直开着,Claude App 会一直拿到伪造的 401 Unauthorized,登录后也可能继续异常。
5. 请求域名不一致
规则默认只匹配:
claude.ai
如果实际请求是:
api.claude.ai
就需要按前面的方式修改 MITM 和 rewrite。
推荐的完整配置片段
如果你的 Claude App 请求的是 claude.ai,稳定版最终配置可以像这样:
[rewrite_local]
^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_stable.js
[mitm]
hostname = claude.ai
如果你需要同时兼容 claude.ai 和 api.claude.ai,积极版最终配置可以像这样:
[rewrite_local]
^https:\/\/(?:claude\.ai|api\.claude\.ai)\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_aggressive.js
[mitm]
hostname = claude.ai, api.claude.ai
如果你的配置文件里已经有 [rewrite_local] 和 [mitm],不要重复创建同名 section,只把对应规则和 hostname 合并进去。
例如:
[rewrite_local]
原来的规则 1
原来的规则 2
^https:\/\/claude\.ai\/api\/account\/?(?:\?.*)?$ url script-echo-response claude_force_logout_stable.js
[mitm]
hostname = 原来的域名1, 原来的域名2, claude.ai
最后提醒
这个方法本质上是一次临时的登录态清理动作,不是长期代理规则。
正确使用方式是:
- 开启 MITM 和 rewrite。
- 让 Claude App 命中一次
/api/account。 - App 回到登录页。
- 立刻关闭 rewrite。
- 重新登录 Claude。
不要把真实 cookie 发给别人,也不要长期拦截 Claude 的账号接口。这个规则只用于解决 iOS App 卡在旧 session 的问题。