xpzouying/xiaohongshu-mcp · error
download failed with status %d for URL: %s
Error message
download failed with status %d for URL: %s
What it means
DownloadImage fetches a single image via HTTP and returns its bytes/local path. This error is thrown when the response status is not 200 OK, so the body is not trusted as image data and the download is abandoned.
Source
Thrown at pkg/downloader/images.go:70
// 设置 User-Agent,模拟浏览器请求
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
// 设置 Referer,使用图片 URL 的域名
parsedURL, _ := url.Parse(imageURL)
if parsedURL != nil {
req.Header.Set("Referer", fmt.Sprintf("%s://%s/", parsedURL.Scheme, parsedURL.Host))
}
// 下载图片数据
resp, err := d.httpClient.Do(req)
if err != nil {
return "", errors.Wrapf(err, "failed to download image from %s", imageURL)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download failed with status %d for URL: %s", resp.StatusCode, imageURL)
}
// 读取图片数据
imageData, err := io.ReadAll(resp.Body)
if err != nil {
return "", errors.Wrap(err, "failed to read image data")
}
// 检测图片格式
kind, err := filetype.Match(imageData)
if err != nil {
return "", errors.Wrap(err, "failed to detect file type")
}
if !filetype.IsImage(imageData) {
return "", errors.New("downloaded file is not a valid image")
}
View on GitHub (pinned to 332d196854)
Solutions
- Log the actual status code and URL; for 403 check whether the site requires the UA/Referer headers this downloader already sends, and whether the signed URL expired
- For 429, add throttling/delay between requests and retry with exponential backoff
- Re-parse the page to get fresh image URLs if they are expiring or the image was moved (404)
- Verify the URL scheme is correct (http vs https, no relative path passed through unchanged)
- For persistent 5xx, retry later or skip the image and continue the batch (DownloadImages already collects per-URL errors)
Example fix
// before
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download failed with status %d for URL: %s", resp.StatusCode, imageURL)
}
// after — retry on transient statuses with backoff
if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
time.Sleep(backoff)
return d.DownloadImage(imageURL) // retry
}
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download failed with status %d for URL: %s", resp.StatusCode, imageURL)
} Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Head(imageURL)
if err != nil || resp.StatusCode != http.StatusOK {
// 图片不可达(403/404/429),跳过或换源
} Try / catch
path, err := d.DownloadImage(imageURL)
if err != nil {
var statusErr interface{ Error() string }
_ = statusErr
if strings.Contains(err.Error(), "status 429") || strings.Contains(err.Error(), "status 5") {
time.Sleep(2 * time.Second)
path, err = d.DownloadImage(imageURL) // 退避重试一次
}
if err != nil { log.Printf("skip %s: %v", imageURL, err) }
} Prevention
- Send proper User-Agent/Referer headers to bypass hotlink protection
- Throttle requests per host to avoid 429 rate limiting
- Re-scrape page URLs if they are signed and expiring
- Validate the URL is absolute and scheme-correct before downloading
When it happens
Trigger: DownloadImages or ProcessImages calls d.DownloadImage(imageURL); the HTTP request succeeds but the server responds with e.g. 404 (image moved/deleted), 403 (hotlink protection / missing UA or Referer — note the UA/Referer headers this client sends), 429 (rate limited), or 5xx.
Common situations: Hotlink protection rejecting requests without proper Referer/User-Agent; images behind expiring signed URLs (S3/CDN token expired -> 403); rate limiting (429) when scraping many images from one host; image removed after the page HTML was parsed (stale URL); geo-blocked CDN.
Related errors
- 获取 SHA256SUMS: HTTP %d
- HTTP %d: %s
- failed to download %s: %w
- failed to create request
- failed to detect file type
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/4de7e425895cede1.
Report an issue: GitHub.