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

  1. Accept that the site cannot be scraped server-side and surface the message to users
  2. Switch to a headless browser that executes the challenge
  3. Use residential proxies or a different network egress
  4. 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

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)