Python请求正常但Golang请求遭Cloudflare拦截问题咨询
问题原因分析
1. Cookie处理差异
Python的requests直接将完整的Cookie字符串写入Cookie请求头,而Golang使用AddCookie方法时,会自动为Cookie添加默认属性(如Path=/、Domain=kick.com),这可能与获取__cf_bm时的原始Cookie属性不符,导致Cloudflare验证失败。
2. 请求头顺序/隐式头缺失
Cloudflare的Bot检测会校验请求头的顺序和完整性:
- Golang的
http库默认按字典序发送请求头,与Python requests的头顺序不一致; - Python requests会自动添加部分隐式头(如
Accept-Language),而Golang代码中未配置,触发拦截。
3. TLS握手指纹差异
Golang标准库的TLS握手指纹与Chrome浏览器(或Python依赖的urllib3 TLS实现)不同,Cloudflare通过TLS特征识别出这是非浏览器请求,直接拦截。
解决方法
方法一:对齐Cookie与请求头配置
直接模拟Python的请求头构造方式,避免Golang自动修改Cookie属性,同时补全缺失的隐式头:
package main import ( "compress/gzip" "fmt" "io" "io/ioutil" "net/http" ) func MakeRequest(url string) (*string, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } // 完全对齐Python的请求头,直接设置Cookie字段而非AddCookie req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") req.Header.Set("Accept", "application/json") req.Header.Set("Cookie", "__cf_bm=yBP__EtLom8aR55x2yIow3GYMpKSMiAAATdk4xHO7CA-1687137561-0-AbAdr3HpoqE97ImTJi4fWsbDp8iOzl6PBzrSwDnFBoTENSfjb7ZOTVx5YX4fuuUMnrIxzqgyWE+kQlENR3ouM3vkVKSWPljxD/JRJJVGGWFy") req.Header.Set("Connection", "keep-alive") req.Header.Set("Accept-Encoding", "gzip, deflate") // 补全Python自动添加的隐式头 req.Header.Set("Accept-Language", "en-US,en;q=0.5") client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var reader io.ReadCloser reader, err = gzip.NewReader(resp.Body) if err != nil { // 处理非gzip压缩的情况 reader = resp.Body } bytes, err := ioutil.ReadAll(reader) if err != nil { return nil, err } body := string(bytes) return &body, nil } func main() { data, err := MakeRequest("https://kick.com/api/v1/channels/xqc") if err != nil { fmt.Println("请求错误:", err) return } fmt.Println(*data) }
方法二:自定义请求头顺序(可选)
如果方法一仍无效,可通过手动构造Request的RawHeader来强制指定头顺序,完全匹配Python的请求:
// 在创建req后,替换RawHeader req.RawHeader = []byte(`User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Accept: application/json Cookie: __cf_bm=yBP__EtLom8aR55x2yIow3GYMpKSMiAAATdk4xHO7CA-1687137561-0-AbAdr3HpoqE97ImTJi4fWsbDp8iOzl6PBzrSwDnFBoTENSfjb7ZOTVx5YX4fuuUMnrIxzqgyWE+kQlENR3ouM3vkVKSWPljxD/JRJJVGGWFy Connection: keep-alive Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.5 `) // 注意:设置RawHeader后,不要用Header.Set修改头,否则会覆盖RawHeader
方法三:模拟浏览器TLS指纹
如果前两种方法都失败,说明Cloudflare通过TLS指纹识别了Golang客户端,可使用utls库模拟Chrome的TLS握手:
// 先安装utls:go get github.com/refraction-networking/utls package main import ( "compress/gzip" "fmt" "io" "io/ioutil" "github.com/refraction-networking/utls" ) func MakeRequest(url string) (*string, error) { cfg := &utls.Config{ ServerName: "kick.com", } conn, err := utls.Dial("tcp", "kick.com:443", cfg) if err != nil { return nil, err } defer conn.Close() // 模拟Chrome 114的TLS握手 err = conn.Handshake() if err != nil { return nil, err } // 构造请求体,完全对齐Python的请求 reqStr := "GET /api/v1/channels/xqc HTTP/1.1\r\n" + "Host: kick.com\r\n" + "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36\r\n" + "Accept: application/json\r\n" + "Cookie: __cf_bm=yBP__EtLom8aR55x2yIow3GYMpKSMiAAATdk4xHO7CA-1687137561-0-AbAdr3HpoqE97ImTJi4fWsbDp8iOzl6PBzrSwDnFBoTENSfjb7ZOTVx5YX4fuuUMnrIxzqgyWE+kQlENR3ouM3vkVKSWPljxD/JRJJVGGWFy\r\n" + "Connection: keep-alive\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "Accept-Language: en-US,en;q=0.5\r\n\r\n" _, err = conn.Write([]byte(reqStr)) if err != nil { return nil, err } // 读取响应 respBuf := make([]byte, 4096) n, err := conn.Read(respBuf) if err != nil && err != io.EOF { return nil, err } // 处理gzip压缩(需要跳过响应头) respStr := string(respBuf[:n]) bodyStart := len(respStr[:respStr.Index("\r\n\r\n")+4]) bodyBytes := []byte(respStr[bodyStart:]) reader, err := gzip.NewReader(io.Reader(bodyBytes)) if err != nil { reader = io.Reader(bodyBytes) } decompressed, err := ioutil.ReadAll(reader) if err != nil { return nil, err } body := string(decompressed) return &body, nil } func main() { data, err := MakeRequest("https://kick.com/api/v1/channels/xqc") if err != nil { fmt.Println("请求错误:", err) return } fmt.Println(*data) }
注意事项
__cf_bm的有效期仅30分钟,需确保每次请求使用的是最新从浏览器获取的有效Cookie,且User-Agent必须与获取Cookie时完全一致;- Cloudflare的Bot检测规则会动态更新,若以上方法失效,需进一步对比浏览器/Python请求的完整数据包(可通过Wireshark或Charles抓包),找出差异点。
内容的提问来源于stack exchange,提问作者invictadux
相关产品推荐
相关产品推荐

