You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python requests请求Snapptrip航班接口返回403未授权错误求助

403报错原因及修复方案

核心报错原因

返回403无权限是三类问题共同导致的:

  • 请求上下文完全不匹配:目标URL是德黑兰(THR)到基什岛(KIH)2022-07-01的航班页面,但POST请求体里填的目的地是马什哈德(MHD)、出发日期是2022-06-30,referer请求头也填的是马什哈德航线的旧页面地址。站点服务端会做全链路参数一致性校验,跨航线、跨日期复用旧请求上下文会被直接判定为异常请求,拒绝访问。
  • 鉴权凭证失效且绑定资源不匹配:对照提供的浏览器请求截图可以确认,你复制的x-access-token、x-request-id、x-session-id、x-customer-key以及Cookie里的会话字段,都是之前访问马什哈德航线页面时生成的短时效凭证,有效期通常只有数分钟,且和当时访问的航线资源强绑定,无法用于请求基什岛的航班资源。
  • 请求传参写法存在错误:调用requests.post时,给json参数传入了json.dumps(data)的序列化结果,会导致请求体被二次JSON编码,服务端无法正常解析参数;同时手动写死了content-length: 147请求头,这个值是之前旧请求的请求体长度,参数修改后实际请求体长度已经变化,错误的content-length也会触发服务端拦截规则。

修复步骤

  1. 统一全链路请求参数
    • 修改POST请求体内容,将destination字段值改为"KIH",departDate字段值改为"2022-07-01",和URL里的航线、日期参数完全一致
    • 修改referer请求头的值为目标基什岛航班页面地址,删除值开头多余的空格,不要保留旧的马什哈德航线地址
  2. 修正requests库传参逻辑
    • 删除手动编写的content-length请求头,requests会自动根据实际请求体计算并填充正确的长度值
    • 发POST请求时直接传json=data即可,不需要额外对data做json.dumps处理;如果要自行序列化参数,就通过data=json.dumps(data)传参,不要和json参数混用
  3. 替换硬编码的失效凭证
    直接复制浏览器里的固定鉴权头和Cookie复用成功率极低,这类短时效凭证必须动态获取:
    • 初始化requests.Session()对象维持会话,首先用GET请求访问目标基什岛航班的前端页面,让服务端自动给当前会话下发合法Cookie
    • 从GET返回的页面内容、或者页面加载时触发的接口响应中,动态提取当前会话对应的x-access-token、x-session-id等鉴权字段,填充到请求头后再发POST查询请求
    • 注意不要直接把前端页面URL当POST接口地址,要从浏览器网络面板里抓取实际处理航班查询的XHR接口地址作为POST目标
  4. 若调整后仍被拦截,检查是否存在动态签名参数:这类航旅站点通常会在页面加载时生成短期请求签名,签名和当前查询的航线、日期、会话强绑定,必须从当前访问的页面动态获取,不能复用旧页面的签名值。

修正后的核心请求参考代码:

import requests

# 初始化会话自动维持Cookie
session = requests.Session()
page_url = "https://www.snapptrip.com/flights/THR-tehran/KIH-kish-island?roundTrip=false&adultCount=1&childCount=0&inLapCount=0&date=2022-07-01&cabinType=E"
# 从浏览器网络面板抓实际的查询接口地址替换下方值
api_url = "实际航班查询POST接口地址"

base_headers = {
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36',
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'en-US,en;q=0.9',
    'origin': 'https://www.snapptrip.com',
    'referer': page_url
}

# 先访问页面获取合法会话凭证
session.get(page_url, headers=base_headers)
# 此处补充逻辑:从页面响应或者后续接口返回中提取动态鉴权头,加入base_headers

# 构造和URL参数完全匹配的请求体
query_data = {
    "origin": "THR",
    "destination": "KIH",
    "roundTrip": False,
    "passengers": {"adults": 1, "children": 0, "infants": 0},
    "cabinType": "E",
    "departDate": "2022-07-01"
}

# 发起查询请求,不手动传content-length,不二次序列化JSON
resp = session.post(url=api_url, json=query_data, headers=base_headers)
print(resp.status_code, resp.text)

内容的提问来源于stack exchange,提问作者Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:21:31