projectdiscovery/nuclei · error
HTTP %d when downloading Swagger spec
Error message
HTTP %d when downloading Swagger spec
What it means
SwaggerDownloader.Download fetched the spec URL but received a non-200 status; the status code is embedded in the message. Transport succeeded (otherwise you would see 'failed to download Swagger spec'), so this reflects the server's answer: auth failures, wrong paths, rate limits, or server errors.
Source
Thrown at pkg/input/formats/swagger/downloader.go:64
var client *http.Client
if httpClient != nil {
client = httpClient.HTTPClient
} else {
// Fallback to simple client if no httpClient provided
client = &http.Client{Timeout: 30 * time.Second}
}
resp, err := client.Get(urlStr)
if err != nil {
return "", errors.Wrap(err, "failed to download Swagger spec")
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP %d when downloading Swagger spec", resp.StatusCode)
}
bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, maxSpecSizeBytes))
if err != nil {
return "", errors.Wrap(err, "failed to read response body")
}
// Determine format and parse
var spec map[string]interface{}
var isYAML bool
// Try JSON first
if err := json.Unmarshal(bodyBytes, &spec); err != nil {
// Then try YAML
if err := yaml.Unmarshal(bodyBytes, &spec); err != nil {
return "", fmt.Errorf("downloaded content is neither valid JSON nor YAML: %w", err)
}
isYAML = trueView on GitHub (pinned to 265b3a3dec)
Solutions
- Reproduce with `curl -i <url>` from the same machine/proxy and confirm 200
- If auth is required, download with the needed headers and use `nuclei -l spec.json`
- Fix the URL if 404 (check the docs UI for the current spec path)
- Retry later for 429/5xx or use a local copy
Example fix
# before (auth-gated -> HTTP 401) nuclei -im swagger -u https://host/v2/swagger.json # after curl -sH "Authorization: Bearer $TOKEN" https://host/v2/swagger.json -o swagger.json nuclei -l swagger.json -im swagger
Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Head(url)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("spec URL answered %d; fix URL/auth or download manually", resp.StatusCode)
} Try / catch
for attempt := 0; attempt < 3; attempt++ {
path, err = downloader.Download(url, tmp, client)
if err == nil || !strings.Contains(err.Error(), "HTTP 5") && !strings.Contains(err.Error(), "HTTP 429") {
break
}
time.Sleep(time.Duration(attempt+1) * 2 * time.Second)
} Prevention
- Preflight spec URLs with curl -i from the scan host
- Keep local copies of auth-gated specs
- Alert on 404s so stale spec URLs get fixed before scan time
When it happens
Trigger: 401/403 on auth-protected spec endpoints; 404 for moved specs; 429 or 5xx under load; 407 from corporate proxies; CDN blocks returning 403 for non-browser user agents.
Common situations: Internal portals requiring cookies/tokens; stale URLs after API version migrations; CI networks behind intercepting proxies; anti-bot protection on public docs.
Related errors
- HTTP %d when downloading OpenAPI spec
- failed to download %s spec from url %s: %w
- downloaded content is not valid JSON: %w
- URL does not appear to be a Swagger spec (supported: %v)
- downloaded content is neither valid JSON nor YAML: %w
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/29b0ee8e4343f54c.
Report an issue: GitHub.