参考Instaloader源码用curl实现Instagram登录失败,该如何解决
Instagram curl复刻登录失败问题排查及解决方案
问题描述
使用Instaloader(一款Instagram爬虫工具)可以正常完成登录,尝试通过curl复刻该登录流程时遇到阻碍,参考Instaloader源码登录逻辑编写的curl请求如下:
curl -v -L -X POST -H "User-Agent: Mozilla/5.0 (Linux; Android 9; Redmi Note 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Mobile Safari/537.36" \ -H "X-Requested-With: XMLHttpRequest" \ -H "Referer: https://www.instagram.com/" \ -H "Connection: keep-alive" \ -H "Accept-Encoding: gzip, deflate" \ -H "Host: www.instagram.com" \ -H "Origin: https://www.instagram.com" \ -H "Accept-Language: en-US,en;q=0.8" \ -H "x-csrftoken: Bk67CZMxGjj63HqhSSDoCRiRJWWM3Oay" \ -H "X-Instagram-AJAX: 1" \ -H "Content-Type: application/json" \ -d '{"username": "dcent_07", "enc_password": "#PWD_INSTAGRAM_BROWSER:0:current_timestamp:mypassword_goes_here"}' \ https://www.instagram.com/accounts/login/ajax/
执行后返回结果如下,显示认证失败:
{"user":false,"authenticated":false,"status":"ok"}
抓取到的Instaloader实际生效请求头如下:
{'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Accept-Language': 'en-US,en;q=0.8', 'Content-Length': '0', 'Host': 'www.instagram.com', 'Origin': 'https://www.instagram.com', 'Referer': 'https://www.instagram.com/', 'X-Instagram-AJAX': '1', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRFToken': 'OTyiskTUqTv74s6csIJy7NmcweNj2ULW'}
问题根因
- Content-Type配置错误:Instagram登录ajax接口不接受
application/json格式的请求体,需要使用application/x-www-form-urlencoded格式传参,JSON格式会导致服务端解析参数失败,无法识别账号密码。 - 缺少
Accept: */*请求头:对比Instaloader的请求头,缺少该字段会被服务端判定为异常请求直接拦截。 - CSRFToken与会话不匹配:硬编码的csrftoken没有和请求携带的Cookie绑定,Instagram的CSRF校验要求请求头中的csrftoken必须和Cookie中的csrftoken值完全一致,否则直接拒绝认证。
- 没有携带初始会话Cookie:登录请求需要先GET访问Instagram主页拿到初始Cookie(包含csrftoken、mid等字段),再带着这些Cookie发送POST登录请求,否则服务端不会识别请求会话。
- 加密密码格式问题:
enc_password字段的时间戳需要是当前10位Unix时间戳,且新版Instagram要求密码按规则做AES加密后提交,直接明文拼接的方式大概率已经失效。
修复步骤
第一步:获取初始Cookie和CSRFToken
# 请求主页,将Cookie存入cookies.txt,同时提取csrftoken CSRF=$(curl -s -c cookies.txt https://www.instagram.com/ | grep -o 'csrf_token"[^"]*"[^"]*"' | cut -d '"' -f 3) # 生成当前10位时间戳 TS=$(date +%s) # 替换为实际账号密码 USERNAME="你的账号" PASSWORD="你的密码" # 构造enc_password(测试可使用0版本明文格式,正式使用需要参考Instaloader实现AES加密) ENC_PWD="#PWD_INSTAGRAM_BROWSER:0:${TS}:${PASSWORD}"
第二步:发起登录请求
curl -v -L -X POST \ -b cookies.txt \ -c cookies.txt \ -H "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \ -H "X-Requested-With: XMLHttpRequest" \ -H "Referer: https://www.instagram.com/" \ -H "Connection: keep-alive" \ -H "Accept-Encoding: gzip, deflate" \ -H "Host: www.instagram.com" \ -H "Origin: https://www.instagram.com" \ -H "Accept-Language: en-US,en;q=0.8" \ -H "x-csrftoken: ${CSRF}" \ -H "X-Instagram-AJAX: 1" \ -H "Accept: */*" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=${USERNAME}&enc_password=${ENC_PWD}" \ https://www.instagram.com/accounts/login/ajax/
注意事项
- 如果账号开启了二次验证,登录请求返回后还需要额外调用二次验证接口提交验证码才能完成登录。
- 频繁请求容易触发Instagram的风控机制,会要求进行人机验证或者临时封禁账号。
- 目前Instagram的enc_password已经升级到版本10,需要用公钥加密密码,0版本的明文拼接方式可能已经失效,建议直接参考Instaloader的密码加密逻辑实现加密后再传参。
内容的提问来源于stack exchange,提问作者Golu
相关产品推荐
相关产品推荐

