fish2018/pansou · warning

xunlei captcha required

Error message

xunlei captcha required

What it means

The Xunlei (迅雷) captcha-token fetch routine parses the upstream JSON response and, if the response carries a non-empty url field, the service refuses to proceed because Xunlei is demanding a CAPTCHA verification instead of issuing a captcha token. It is a sentinel error signaling that automation hit an anti-bot wall.

Solutions

  1. Open the returned response.URL in a browser, complete the CAPTCHA, then retry the operation.
  2. Slow down request rate and add jitter/backoff to avoid triggering the challenge.
  3. Refresh the Xunlei login session/token — expired sessions often trigger captcha demands.
  4. Route requests through a residential IP or the user's own credentials rather than a shared datacenter IP.

Example fix

token, err := s.getXunleiCaptchaToken(ctx)
if errors.Is(err, errXunleiCaptchaRequired) {
    return nil, fmt.Errorf("captcha needed, visit %s to verify", lastCaptchaURL)
}
Defensive patterns

Strategy: fallback

Try / catch

token, err := s.getXunleiCaptchaToken(ctx)
if err != nil && strings.Contains(err.Error(), "captcha required") {
    return manualVerificationRequired(err)
}

Prevention

When it happens

Trigger: Calling the xunlei captcha-token endpoint returns JSON with a url field set (a CAPTCHA/verification page link) instead of a captcha_token, e.g. after too many automated requests.

Common situations: Rate-limited or IP-flagged Xunlei account; running from a datacenter IP flagged for automation; expired login session forcing re-verification; sudden burst of link checks.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/e9a47434cedb3574. Report an issue: GitHub.

Appendix: source

Thrown at service/check_service.go:1086

		"accept":           "application/json;charset=UTF-8",
		"content-type":     "application/json",
		"x-device-id":      deviceID,
		"x-client-id":      clientID,
		"x-client-version": clientVersion,
	})
	if err != nil {
		return "", err
	}

	var response struct {
		CaptchaToken string `json:"captcha_token"`
		URL          string `json:"url"`
	}
	if err := utiljson.Unmarshal(body, &response); err != nil {
		return "", err
	}
	if response.URL != "" {
		return "", fmt.Errorf("xunlei captcha required")
	}
	return response.CaptchaToken, nil
}

func (s *CheckService) buildResult(item model.CheckItem, normalized string, state string, cacheHit bool, summary string) model.CheckResult {
	now := time.Now()
	expiresAt := now.Add(ttlForState(state))

	return model.CheckResult{
		DiskType:      item.DiskType,
		URL:           item.URL,
		NormalizedURL: normalized,
		State:         state,
		CacheHit:      cacheHit,
		CheckedAt:     now.UnixMilli(),
		ExpiresAt:     expiresAt.UnixMilli(),
		Summary:       summary,
	}

View on GitHub (pinned to beaa561337)