fish2018/pansou · error

HTTP 403 Forbidden - 可能需要重新登录

Error message

HTTP 403 Forbidden - 可能需要重新登录

What it means

searchWithScraper received an HTTP 403 Forbidden from the site's search endpoint. A 403 usually means the session cookie is expired/invalid or Cloudflare is challenging the client, so the plugin surfaces this hint to trigger re-login by the caller (the search wrapper retries via reloginUser).

Solutions

  1. Re-login to obtain a fresh session (the plugin does this automatically on 403 — ensure credentials are valid).
  2. Update cloudscraper so the Cloudflare challenge can be solved.
  3. Persist cookies so sessions survive restarts and avoid frequent re-logins.
  4. Use a different IP/proxy if the address is blocked by the site.
Defensive patterns

Strategy: retry

Validate before calling

// before searching, ensure a session exists
if _, ok := p.scrapers.Load(user.Hash); !ok {
    if err := p.reloginUser(user); err != nil {
        return err
    }
}

Try / catch

results, err := p.Search(keyword)
if err != nil && strings.Contains(err.Error(), "403") {
    // plugin auto-relogins; fall back to manual refresh if that also fails
    if refreshErr := p.reloginUser(user); refreshErr != nil {
        return fmt.Errorf("session expired and refresh failed: %w", refreshErr)
    }
}

Prevention

When it happens

Trigger: Performing a search whose HTTP response status is 403: expired session cookie, missing Cloudflare clearance, IP blocked by the site, or request fingerprint flagged.

Common situations: Cookie store not persisted between restarts; long-lived session expired; site tightened anti-bot rules; scraping from a datacenter IP that is blocked.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at plugin/gying/gying.go:2481

				preview = preview[:500] + "..."
			}
			fmt.Printf("[Gying] 响应预览: %s\n", preview)
		}
	}

	// 检查403错误
	if statusCode == http.StatusForbidden {
		if DebugLog {
			fmt.Printf("[Gying] ❌ 收到403 Forbidden - Cookie可能已过期或被网站拒绝\n")
			if len(body) > 0 {
				preview := string(body)
				if len(preview) > 300 {
					preview = preview[:300] + "..."
				}
				fmt.Printf("[Gying] 403响应内容: %s\n", preview)
			}
		}
		return nil, fmt.Errorf("HTTP 403 Forbidden - 可能需要重新登录")
	}

	// 2. 提取 _obj.search JSON
	matches := searchDataPattern.FindSubmatch(body)

	if DebugLog {
		fmt.Printf("[Gying] 正则匹配结果: 找到 %d 个匹配\n", len(matches))
	}

	if isLoginShell(body) {
		return nil, fmt.Errorf("HTTP 403 Forbidden - 需要重新登录")
	}

	if len(matches) < 2 {
		if DebugLog {
			fmt.Printf("[Gying] ❌ 未找到 _obj.search JSON数据\n")

			// 尝试查找是否有其他模式

View on GitHub (pinned to beaa561337)