projectdiscovery/nuclei · error

URL does not appear to be a Swagger spec (supported: %v)

Error message

URL does not appear to be a Swagger spec (supported: %v)

What it means

SwaggerDownloader.Download (pkg/input/formats/swagger/downloader.go) rejects URLs whose path does not end with one of the supported extensions reported by SupportedExtensions(): .json, .yaml, or .yml (case-sensitive strings.HasSuffix, checked before any request). Swagger mode must know the document format in advance, hence the extension gate.

Source

Thrown at pkg/input/formats/swagger/downloader.go:40

// NewDownloader creates a new Swagger downloader
func NewDownloader() formats.SpecDownloader {
	return &SwaggerDownloader{}
}

// This function downloads a Swagger 2.0 spec from the given URL and saves it to tmpDir
func (d *SwaggerDownloader) Download(urlStr, tmpDir string, httpClient *retryablehttp.Client) (string, error) {
	// Swagger can be JSON or YAML
	supportedExts := d.SupportedExtensions()
	isSupported := false
	for _, ext := range supportedExts {
		if strings.HasSuffix(urlStr, ext) {
			isSupported = true
			break
		}
	}
	if !isSupported {
		return "", fmt.Errorf("URL does not appear to be a Swagger spec (supported: %v)", supportedExts)
	}

	const maxSpecSizeBytes = 10 * 1024 * 1024 // 10MB

	// Use provided httpClient or create a fallback
	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")
	}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Use a URL ending in .json, .yaml or .yml
  2. Strip query strings and fragments
  3. If the server cannot serve an extensioned URL, download manually (curl -o spec.yaml) and run `nuclei -l spec.yaml`
  4. Check the printed supported list in the error to confirm the exact suffixes accepted

Example fix

# before
nuclei -im swagger -u https://api.example.com/v2/spec

# after
curl -s https://api.example.com/v2/spec -o spec.json
nuclei -l spec.json -im swagger
Defensive patterns

Strategy: validation

Validate before calling

func isSwaggerDownloadable(u string) bool {
    for _, ext := range []string{".json", ".yaml", ".yml"} {
        if strings.HasSuffix(u, ext) {
            return true
        }
    }
    return false
}

Try / catch

if _, err := downloader.Download(u, tmp, client); err != nil {
    if strings.Contains(err.Error(), "does not appear to be a Swagger spec") {
        // download manually and pass the local file: nuclei -l spec.json -im swagger
    }
}

Prevention

When it happens

Trigger: `nuclei -im swagger -u https://host/swagger` (no extension); URL with query string after the filename (swagger.json?access=x); uppercase .YAML; extension-less gateway routes like /v2/spec.

Common situations: Spec URLs behind API gateways or doc portals without file extensions; URLs with auth query parameters; copy-pasting the docs UI route instead of the raw spec.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/fdab74f06a68c402. Report an issue: GitHub.