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

curl调用Doordash GraphQL接口正常,其他工具请求返回403问题排查

解决Doordash GraphQL接口curl正常但其他工具返回403的问题

可能的原因与解决思路

1. 请求头不完整或不一致

  • 终端curl可能自动携带了部分隐含请求头(如Accept-Encoding),或者你复制的curl命令包含了浏览器会话的Cookie,而其他工具未添加这些关键头。
  • 用curl -v <你的curl命令>查看完整请求头,对比Postman/requests的请求头,确保所有字段完全匹配,特别是Cookie、user-agent、content-type。

2. 请求体编码或格式差异

  • curl的--data-raw $'...'使用shell转义处理了字符串中的换行和特殊字符,其他工具可能因编码问题导致请求体与curl不一致。
  • 验证方法:将curl的请求体复制到其他工具时,确保换行、转义字符(如\u0021)完全保留;Python中建议用json参数传入payload,避免手动编码出错。

3. 会话Cookie缺失

  • Doordash的接口可能需要有效的会话Cookie才能通过验证,curl命令如果是从浏览器复制的,通常包含当前登录状态的Cookie,而其他工具默认没有携带。
  • 解决:从浏览器开发者工具的"网络"面板中复制完整的Cookie字符串,添加到请求头的Cookie字段中。

4. TLS客户端指纹识别

  • 部分网站会通过TLS握手参数识别请求来源,curl、浏览器与其他工具的TLS指纹不同,可能被判定为非合法请求拦截。
  • 解决:Python中可使用curl_cffi库模拟curl的TLS指纹;Postman可尝试开启"模拟浏览器请求"的相关设置,调整TLS版本匹配浏览器。

5. 压缩设置差异

  • curl的--compressed参数会自动处理gzip/deflate压缩,确保其他工具也开启了相应的压缩支持(Python requests默认支持,Postman需在设置中启用)。

Python requests示例代码

import requests

url = "https://www.doordash.com/graphql/searchWithFilterFacetFeed?operation=searchWithFilterFacetFeed"

headers = {
    'authority': 'www.doordash.com',
    'accept': '*/*',
    'accept-language': 'en-US',
    'content-type': 'application/json',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
    # 替换为你从浏览器复制的Cookie
    'Cookie': 'your_session_cookie_here'
}

payload = {
    "operationName": "searchWithFilterFacetFeed",
    "variables": {
        "cursor": "eyJvZmZzZXQiOjUwLCJ2ZXJ0aWNhbF9pZHMiOltdLCJjcm9zc192ZXJ0aWNhbF9wYWdlX3R5cGUiOiJHTE9CQUxfU0VBUkNIX1BBR0UiLCJwYWdlX3N0YWNrX3RyYWNlIjpbXSwibGF5b3V0X292ZXJyaWRlIjoiVU5TUEVDSUZJRUQiLCJpc19wYWdpbmF0aW9uX2ZhbGxiYWNrIjpudWxsLCJzb3VyY2VfcGFnZV90eXBlIjpudWxsLCJ2ZXJ0aWNhbF9uYW1lcyI6e319",
        "filterQuery": "",
        "query": "street food",
        "isDebug": False
    },
    "query": "query searchWithFilterFacetFeed($cursor: String, $filterQuery: String, $query: String!, $isDebug: Boolean, $fromFilterChange: Boolean, $serializedBundleGlobalSearchContext: String, $address: String) {\n  searchWithFilterFacetFeed(\n    cursor: $cursor\n    filterQuery: $filterQuery\n    query: $query\n    isDebug: $isDebug\n    fromFilterChange: $fromFilterChange\n    serializedBundleGlobalSearchContext: $serializedBundleGlobalSearchContext\n    address: $address\n  ) {\n    ...FacetFeedV2ResultFragment\n    __typename\n  }\n}\n\nfragment FacetFeedV2ResultFragment on FacetFeedV2Result {\n  body {\n    id\n    header {\n      ...FacetV2Fragment\n      __typename\n    }\n    body {\n      ...FacetV2Fragment\n      __typename\n    }\n    layout {\n      omitFooter\n      __typename\n    }\n    __typename\n  }\n  page {\n    ...FacetV2PageFragment\n    __typename\n  }\n  header {\n    ...FacetV2Fragment\n    __typename\n  }\n  custom\n  logging\n  __typename\n}\n\nfragment FacetV2Fragment on FacetV2 {\n  ...FacetV2BaseFragment\n  childrenMap {\n    ...FacetV2BaseFragment\n    __typename\n  }\n  __typename\n}\n\nfragment FacetV2BaseFragment on FacetV2 {\n  id\n  childrenCount\n  component {\n    ...FacetV2ComponentFragment\n    __typename\n  }\n  name\n  text {\n    ...FacetV2TextFragment\n    __typename\n  }\n  images {\n    main {\n      ...FacetV2ImageFragment\n      __typename\n    }\n    icon {\n      ...FacetV2ImageFragment\n      __typename\n    }\n    background {\n      ...FacetV2ImageFragment\n      __typename\n    }\n    accessory {\n      ...FacetV2ImageFragment\n      __typename\n    }\n    custom {\n      key\n      value {\n        ...FacetV2ImageFragment\n        __typename\n      }\n      __typename\n    }\n    __typename\n  }\n  events {\n    click {\n      name\n      data\n      __typename\n    }\n    __typename\n  }\n  style {\n    spacing\n    background_color\n    border {\n      color\n      width\n      style\n      __typename\n    }\n    sizeClass\n    __typename\n  }\n  layout {\n    omitFooter\n    gridSpecs {\n      Mobile {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      Phablet {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      Tablet {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      Desktop {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      WideScreen {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      UltraWideScreen {\n        ...FacetV2LayoutGridFragment\n        __typename\n      }\n      __typename\n    }\n    dlsPadding {\n      top\n      right\n      bottom\n      left\n      __typename\n    }\n    __typename\n  }\n  custom\n  logging\n  __typename\n}\n\nfragment FacetV2ComponentFragment on FacetV2Component {\n  id\n  category\n  __typename\n}\n\nfragment FacetV2TextFragment on FacetV2Text {\n  title\n  titleTextAttributes {\n    textStyle\n    textColor\n    __typename\n  }\n  subtitle\n  subtitleTextAttributes {\n    textStyle\n    textColor\n    __typename\n  }\n  accessory\n  accessoryTextAttributes {\n    textStyle\n    textColor\n    __typename\n  }\n  description\n  descriptionTextAttributes {\n    textStyle\n    textColor\n    __typename\n  }\n  custom {\n    key\n    value\n    __typename\n  }\n  __typename\n}\n\nfragment FacetV2ImageFragment on FacetV2Image {\n  uri\n  placeholder\n  local\n  style\n  logging\n  events {\n    click {\n      name\n      data\n      __typename\n    }\n    __typename\n  }\n  __typename\n}\n\nfragment FacetV2LayoutGridFragment on FacetV2LayoutGrid {\n  interRowSpacing\n  interColumnSpacing\n  minDimensionCount\n  __typename\n}\n\nfragment FacetV2PageFragment on FacetV2Page {\n  next {\n    name\n    data\n    __typename\n  }\n  onLoad {\n    name\n    data\n    __typename\n  }\n  __typename\n}\n"
}

response = requests.post(url, headers=headers, json=payload)
print(response.status_code)
print(response.json())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:09:51