Android v391.0.0.42.82 登录流程¶
igapi-rs 的 Android 平台支持 多版本并存:v428(默认,5 步 Bloks 流程)与 v391(7 步 CAA 流程)。
本文档说明 v391 的 7 步 CAA 登录流程、版本选择方式,以及必须知悉的 attestation 现实边界。
完整端点覆盖状态见 Android v391.0.0.42.82 能力索引。
⚠️ 现实边界:登录成功依赖硬件 attestation¶
v391 登录第 6 步 send_login_request 需在 X-IG-Attest-Params 头携带 Android Keystore
硬件密钥证明(key_hash / signed_nonce)。真机是硬件绑定的 AndroidKeyStore / StrongBox 签名。
本 SDK 默认使用纯软件 EC 签名器(SoftwareAttestationProvider),它保证协议结构合法、
流程能推进到 send_login_request,但会被登录风控拒绝(服务端返回 SLR error)。因此:
- ✅ 可用:完整 7 步协议、请求头/体与真机抓包对齐、可跑到 send_login。
- ❌ 不保证:端到端登录成功——需通过
with_attestation_provider注入 真机/Frida 硬件签名的 provider。
完整生命周期¶
v391 支持 init → 登录 → 2FA 验证 全流程:
- 登录:下方 7 步 CAA 流程。
- 2FA 验证:登录返回需二次验证时,
login()抛TwoFactorRequired并暂存two_step_verification_context;随后调用complete_two_factor(code)完成two_step_verification.entrypoint→verify_code.async。判定依据真机抓包: 成功响应含logged_in_user且由IG-Set-Authorization下发 Bearer 令牌落地会话; 验证码错误时 HTTP 200 但无logged_in_user(服务端提示 “check the security code and try again”), 此时保留上下文可用新验证码重试。 - init 收尾:登录成功后自动 best-effort 拉取一批预热端点(aed/current、loom/fetch_config、 get_account_family、ndx_ig_steps、fetch_onetap、process_contact_point_signals 等),失败不阻断登录。
two_step_verification_context的提取依据two_step_verification.entrypoint响应中 文档记录的 Bloksmap.Make结构(键数组含字段名、值数组按位对齐)解析,非猜测; 但触发 2FA 的send_login响应本身未单独留档,且因 attestation 阻断,端到端仍需注入 真机硬件签名后才能验证。
7 步时序¶
来源:一手抓包 docs/api/android/v391.0.0.42.82/(Redmi Note 9 / M2007J22C)。
| # | 端点 | 作用 |
|---|---|---|
| 1 | POST /launcher/mobileconfig/ |
无会话配置同步(signed_body=SIGNATURE.<明文JSON>,非签名) |
| 2 | POST /attestation/create_android_keystore/ |
提交 key_hash → 取 challenge_nonce |
| 3 | POST /bloks/async_action/...login.process_client_data_and_redirect/ |
客户端数据处理与重定向 |
| 4 | POST /bloks/async_action/...phone.number.prefill.async.controller/ |
手机号/用户名预填 |
| 5 | POST /bloks/async_action/...caa.login.oauth.token.fetch.async/ |
OAuth Token 获取 |
| 6 | POST /bloks/async_action/...caa.login.async.send_login_request/ |
提交加密密码 + X-IG-Attest-Params |
| 7 | POST /zr/dual_tokens/ |
Zero-Rating 双 Token(仅登录成功后有意义) |
设备标识映射(v391)¶
| 头 / 字段 | 形态 | 说明 |
|---|---|---|
X-IG-Android-ID / body device_id(android) |
android-<16hex> |
由系统 ANDROID_ID 派生 |
X-IG-Device-ID / app_scoped_device_id / custom_device_id |
带连字符 UUID | guid 形态 |
X-IG-Family-Device-ID / family_device_id |
带连字符 UUID | mobileconfig 中为大写 |
授权新账号 / 注册链路边界¶
v391 原始文档还覆盖授权新账号与注册后 onboarding 链路。Rust core 已提供版本 API、 流程对象和稳定摘要响应:
client.reg():fxcal/get_sso_accounts、spc_create_profile、caa.reg.username、caa.reg.ac_optin、caa.reg.create.account,并提供RegistrationFlow串联上下文。client.attestation():create_android_keystore与create_android_playintegritychallenge 请求;真实硬件签名或 Googleintegrity_token仍由调用方/provider 提供。client.onboarding():动态 onboarding、contact point prefill、头像 rupload、change_profile_picture、fxcal_link、fxcal_link_log,并提供OnboardingFlow。client.home():feed timeline、Direct inbox、users info、notifications badge 等高价值接口 提供HomeResponse摘要模型。
响应模型只提升稳定摘要字段,完整原始响应仍保留在 raw 中:注册使用
RegistrationResponse,onboarding 使用 OnboardingResponse,home/profile/feed 使用
HomeResponse。注册响应中的 reg_context、auth_token、event_request_id、waterfall_id
等服务端/Bloks 不透明上下文仍由 flow 保存并传递;SDK 不伪造缺失上下文。
错误语义采用现有 InstagramError 映射,注册 flow 额外记录 RegistrationFlowFailure
用于表达用户名不可用、challenge、rate limit、attestation 缺失等失败上下文。
Python 暴露部分稳定 typed wrapper,包括 SSO 查询、用户名校验、dynamic steps、contact prefill、 feed timeline、Direct inbox 和 users info。CLI 只暴露 provider 本地预检与 home smoke,不提供完整 注册/onboarding 命令。原因是完整注册仍依赖真实硬件 attestation / Play Integrity provider、上传状态 和服务端不透明上下文;过早包装成命令会制造看似可用、实际无法稳定完成注册的接口。
使用方式¶
Rust¶
use igapi_core::android::v391::Client;
use igapi_core::ClientConfig;
let client = Client::new(ClientConfig::default())?;
// 默认软件 attestation:能跑完 7 步,但 send_login 预期返回 SLR error。
match client.login("username", "password").await {
Ok(()) => println!("登录成功"),
Err(e) => println!("登录未成功(默认软件 attestation 预期被拒):{e}"),
}
版本目录规范:v391 独有流程必须位于
src/core/src/android/versions/v391/,Rust 入口使用igapi_core::android::v391::Client。
注入硬件 attestation¶
实现 AndroidAttestationProvider 接口,包裹真机/Frida 硬件签名,然后注入。
旧实现只需要 key_hash() + sign(challenge_nonce);推荐新实现覆盖
try_key_hash()、try_sign(challenge_nonce) 和 play_integrity_token(challenge_nonce),
用于返回 unavailable、challenge_expired、signing_failed、token_missing、
device_unsupported 等明确错误语义。
use std::sync::Arc;
let client = Client::new(ClientConfig::default())?
.with_attestation_provider(Arc::new(MyHardwareAttestation::new()));
SDK 只负责请求 Instagram challenge、调用外部 provider、组装 keystore header 或接收
Play Integrity token;不会伪造 Android Keystore 硬件证明,也不会伪造 Google
Play Integrity token。默认 SoftwareAttestationProvider 对 Play Integrity 会返回
token_missing。
可用 CLI 做本地 provider 预检:
Python¶
import igapi
# 版本命名空间(推荐):固定使用 v391 / v428 版本边界
client = igapi.android.v391.Client() # 7 步 CAA
client = igapi.android.v428.Client() # 5 步 Bloks(= 默认)
try:
await client.login("username", "password")
except Exception:
# 触发 2FA 时:提交验证码完成登录
await client.complete_two_factor("123456")
注意:Python 模块名不能以数字开头,所以规范使用
igapi.android.v391,不使用igapi.android.391。
CLI¶
# 默认 v428;用 --android-version 391 切到 7 步 CAA 流程
ig-cli --android-version 391 login --username <u> --password <p>
# 触发 2FA 时提供验证码(不加则交互式从标准输入读取)
ig-cli --android-version 391 login -u <u> -p <p> --two-factor-code 123456
# 使用已登录 Android AccountInfo 做 home smoke
ig-cli --android-version 391 v391-home-smoke -a "<account>" --target feed