fish2018/pansou · error
站点 已迁移并启用 Cloudflare 浏览器验证,当前服务端请求无法通过
Error message
站点 %s 已迁移并启用 Cloudflare 浏览器验证,当前服务端请求无法通过
What it means
doRequestWithRetry inspects the cf-mitigated response header; when its value is 'challenge', Cloudflare has explicitly signaled that the request was intercepted by a browser-verification challenge. The plugin closes the body and fails fast with this site-specific message instead of wasting retries.
Solutions
- Accept that the site cannot be scraped server-side and surface the message to users
- Switch to a headless browser that executes the challenge
- Use residential proxies or a different network egress
- Monitor the site and disable the plugin until protection is lifted
Defensive patterns
Strategy: fallback
Validate before calling
if strings.EqualFold(resp.Header.Get("cf-mitigated"), "challenge") {
return errCloudflareChallenge
} Try / catch
resp, err := doRequestWithRetry(req, client)
if err != nil && strings.Contains(err.Error(), "Cloudflare") {
return nil, err // fail fast, do not retry
} Prevention
- Check cf-mitigated header on every response
- Stop retrying once a challenge is signaled
- Consider headless-browser or proxy fallback
- Track which sites have enabled bot protection
When it happens
Trigger: Any request through doRequestWithRetry (search or detail pages) whose response carries header cf-mitigated: challenge, regardless of status code.
Common situations: Site enabled Cloudflare bot management/under-attack mode; requests originate from datacenter IPs; User-Agent or TLS fingerprint identified as automated.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/271335841aa751a4.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xdpan/xdpan.go:450
// 指数退避重试
backoff := time.Duration(1<<uint(i-1)) * 500 * time.Millisecond
if DebugLog {
fmt.Printf("[xdpan] 重试第%d次,等待%v\n", i, backoff)
}
time.Sleep(backoff)
}
// 克隆请求避免并发问题
reqClone := req.Clone(req.Context())
resp, err := client.Do(reqClone)
if err != nil {
lastErr = err
continue
}
if strings.EqualFold(resp.Header.Get("cf-mitigated"), "challenge") {
resp.Body.Close()
return nil, fmt.Errorf("站点 %s 已迁移并启用 Cloudflare 浏览器验证,当前服务端请求无法通过", p.baseURL)
}
if resp.StatusCode == http.StatusOK {
return resp, nil
}
lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
resp.Body.Close()
}
if lastErr == nil {
lastErr = fmt.Errorf("未知请求错误")
}
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", MaxRetries, lastErr)
}
// setRequestHeaders 设置请求头
func (p *XdpanPlugin) setRequestHeaders(req *http.Request) {
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("Referer", strings.TrimRight(p.baseURL, "/")+"/?p=baidu")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")View on GitHub (pinned to beaa561337)