如何在Node.js中绕过myfitnesspal登录的“启用Cookie和JavaScript”错误
问题
在Glitch环境中用Node.js调用MyFitnessPal接口时,遇到如下问题:
- 流程验证:先通过HTTP GET获取会话Cookie,再用HTTP POST提交登录信息获取JSON数据,该流程在Postman中手动执行完全成功。
- Node.js代码复现异常:POST请求返回403错误,提示内容为:
Enable JavaScript and cookies to continue
- 已排除Cookie缺失问题:确认GET请求的Cookie已通过
request-promise的jar: true配置自动传递给POST请求。 - 核心疑问:
- Postman不会运行页面JavaScript,为何能成功?难道Postman后台偷偷执行了网站的JS?
- 浏览器访问时,首次GET请求会下载并执行大量JS,这些JS是否是完成认证的必要环节?
附上Node.js代码片段:
const rp = require("request-promise").defaults({ jar: true }); var server='https://www.myfitnesspal.com/reports/printable-diary/'; var resp={success : false}; let agent='PostmanRuntime/7.43.0'; var options = { method: 'GET', uri: server+request.query.uid, headers: { 'accept' : '*/*', 'User-Agent': agent, "Accept-Language": "en-US,en;q=0.9", 'Connection': 'keep-alive', 'cache-control': 'no-cache' }, query: { from: '2025-01-05', to: '2025-01-05' }, resolveWithFullResponse: true }; rp(options) // First request gets session cookies .then(function (response) { // prepare 2nd request to login and get data let options2={ method: 'POST', uri: 'https://www.myfitnesspal.com/api/services/authenticate_diary_key', headers: { 'accept' : '*/*', 'User-Agent': agent, 'Accept-Language': 'en-US,en;q=0.9', 'cache-control': 'no-cache', 'Referer': 'https://www.myfitnesspal.com/reports/printable-diary/'+ request.query.uid +'?from=2025-01-05&to=2025-01-05', 'Connection': 'keep-alive' }, body: { "key":request.query.key, "show_food_diary":1, "show_exercise_diary":0, "show_food_notes":0, "show_exercise_notes":0, "username":request.query.uid, "from":"2025-01-05", "to":"2025-01-05" }, resolveWithFullResponse: true, json: true }; return rp(options2); }) .then (function (response){ console.log(response.headers); resp={success : true}; }) .finally(function (){ reply.code(200).send(resp); }) .catch(function (err) { // POST failed... console.log("ERROR!"); console.log(err); reply.code(err.statusCode).send({result: 0}); });
分析与解决思路
为什么Postman能成功?
Postman虽不渲染页面JS,但它的请求模拟更贴近浏览器的细节行为:
- 自动抓取隐藏验证参数:部分网站会在GET页面时生成隐藏表单字段(如CSRF token、会话标识),Postman会自动识别并在POST请求中携带这些参数,而你的Node.js代码仅传递了自定义的body参数,漏掉了这类关键验证字段。
- 请求头完整性更高:Postman会自动补充浏览器默认的请求头(如
Accept-Encoding、Origin),你的代码可能缺少这些头,导致服务器判定为非浏览器请求。 - 会话状态完整传递:除了Cookie,Postman会保留并传递GET响应中的其他会话标识(如响应头内的token),而你的代码仅处理了Cookie。
浏览器下载的JS是否必要?
是的,这些JS大概率是完成人机验证或会话初始化的核心环节:
- 网站可能通过JS生成额外会话参数(如动态CSRF token),并存储到Cookie或本地存储中,后续POST请求必须携带这些参数才能通过验证。
- 部分反爬机制(如Cloudflare JS挑战)需要执行JS生成验证凭证,只有通过验证后,服务器才会接受后续请求。
修复建议
- 抓取浏览器完整请求参数:用浏览器开发者工具监控POST请求,对比你的Node.js请求,找出遗漏的参数(如
csrf_token、__RequestVerificationToken),将其加入POST的body中。 - 补全请求头:复制浏览器的所有请求头到代码中,不要仅保留部分,尤其注意
Origin、Accept-Encoding、Content-Type这类易忽略的头。 - 改用无头浏览器:若网站存在JS验证机制,单纯HTTP请求库无法绕过,建议使用Puppeteer这类无头浏览器工具,模拟真实浏览器的完整行为(加载JS、执行验证、提交表单)。
- 替换request-promise:
request-promise已停止维护,建议改用axios或node-fetch,这些库维护更活跃,更易处理复杂请求场景。
内容的提问来源于stack exchange,提问作者Ardent837
相关产品推荐
相关产品推荐

