向美国运通(AMEX)发送POST登录请求失败问题排查
问题背景
通过网页访问https://www.americanexpress.com/en-us/account/login可正常登录,但使用Python的requests库直接向登录接口https://global.americanexpress.com/myca/logon/us/action/login发送POST请求时,返回Access Denied错误。
已配置的Payload
payload = { 'UserID': MY_USERNAME, 'Password': MY_PASSWORD, 'request_type': 'login', 'Face': 'en_US', 'Logon': 'Logon', 'version': '4', 'inauth_profile_transaction_id': 'LOGIN-9d976fcf-6f67-446f-a7ce-ef665bc3d902', 'DestPage': 'https%3A%2F%2Fglobal.americanexpress.com%2Fdashboard', 'channel': 'Web', 'REMEMBERME': 'off', 'b_hour': '11', 'b_minute': '45', 'b_second': '38', 'b_dayNumber': '14', 'b_month': '4', 'b_year': '2024', 'b_timeZone': '-5' }
已配置的Headers
headers = { 'User-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36', }
执行代码
URL_LOGIN = 'https://global.americanexpress.com/myca/logon/us/action/login' r = requests.post(URL_LOGIN, data=PAYLOAD, headers=headers)
返回错误
<TITLE>Access Denied</TITLE> </HEAD><BODY> <H1>Access Denied</H1> You don't have permission to access "http://global.americanexpress.com/myca/logon/us/action/login" on this server.<P> Reference #18.5fc94d17.1713113139.39df67f <P>https://errors.edgesuite.net/18.5fc94d17.1713113139.39df67f</P> </BODY> </HTML>
遗漏的关键要素及修复方案
1. 未保持会话并获取前置Cookie
网页登录前,访问登录页会生成必要的会话Cookie(比如AMEX_SSO、JSESSIONID等),直接发送POST请求没有这些Cookie会被反爬拦截。
修复:使用requests.Session()创建会话,先GET登录页获取Cookie,再用同一个会话发送POST:
import requests from datetime import datetime import pytz session = requests.Session() LOGIN_PAGE_URL = 'https://www.americanexpress.com/en-us/account/login' # 先访问登录页,获取会话Cookie和动态参数 login_page_response = session.get(LOGIN_PAGE_URL, headers=headers) # 后续需从login_page_response.text中提取动态参数
2. 缺失关键请求头
仅设置User-Agent远远不够,AMEX会验证多个请求头,必须完全复制Chrome开发者工具中真实请求的所有Headers,比如:
Referer:必须是登录页URLhttps://www.americanexpress.com/en-us/account/loginOrigin:https://www.americanexpress.comAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language:en-US,en;q=0.5Content-Type:application/x-www-form-urlencodedSec-Ch-Ua、Sec-Ch-Ua-Mobile、Sec-Ch-Ua-Platform等现代浏览器标识头
修复:从Chrome的Network面板中复制完整的Request Headers,替换到你的headers字典中。
3. 动态参数未实时生成
Payload中的inauth_profile_transaction_id是每次访问登录页时动态生成的,使用固定值会被识别为异常请求。此外,b_hour、b_minute等时间参数需要根据当前时区实时生成。
修复:
- 从登录页的HTML源码中提取
inauth_profile_transaction_id(可使用BeautifulSoup解析) - 用当前时间生成时间参数:
# 生成美国东部时区(UTC-5)的时间参数 eastern_tz = pytz.timezone('US/Eastern') now = datetime.now(eastern_tz) time_params = { 'b_hour': now.strftime('%H'), 'b_minute': now.strftime('%M'), 'b_second': now.strftime('%S'), 'b_dayNumber': now.strftime('%d'), 'b_month': now.strftime('%m'), 'b_year': now.strftime('%Y'), 'b_timeZone': '-5' }
4. 可能存在JS反爬检测
AMEX的登录页面可能包含JS验证逻辑(比如生成隐藏参数、检测浏览器环境),单纯的requests无法执行JS,会被识别为非浏览器请求。
修复:如果上述方案都无效,改用Selenium或Playwright模拟真实浏览器的登录流程,完全复现用户操作(比如输入账号密码、点击登录按钮),绕过JS检测。
内容的提问来源于stack exchange,提问作者Gus Montano

