HTTP Inspector API

Base URL: https://http.netray.info

HTTP header inspection and security audit. Three concurrent probes — HTTPS chain, HTTP port-80 upgrade, and CORS with an evil origin — analyse CSP, HSTS, security headers, cookies, and redirect behaviour.

See also: interactive API reference (auto-generated OpenAPI)

Endpoints

GET /api/inspect?url=

Inspect a URL's HTTP headers and security posture. Returns a synchronous JSON response.

curl -s 'https://http.netray.info/api/inspect?url=https%3A%2F%2Fexample.com' | jq .

POST /api/inspect

Same inspection via POST body.

curl -s -X POST https://http.netray.info/api/inspect \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://example.com"}' | jq .

Response Structure

The response contains several top-level sections:

{
  "url": "https://example.com",
  "probes": [
    {
      "type": "https",
      "status": 200,
      "headers": { ... },
      "csp": { ... },
      "hsts": { "max_age": 31536000, "include_subdomains": true, "preload": false },
      "cookies": [ ... ],
      "cdn": "cloudflare"
    },
    {
      "type": "http_upgrade",
      "status": 301,
      "redirect_target": "https://example.com/"
    },
    {
      "type": "cors",
      "origin_reflected": false,
      "allows_credentials": false,
      "allowed_methods": ["GET"]
    }
  ],
  "redirects": [
    { "url": "http://example.com", "status": 301, "location": "https://example.com/" }
  ],
  "quality": {
    "verdict": "Pass",
    "checks": [
      { "name": "hsts", "label": "HSTS", "status": "pass", "message": "HSTS enabled with adequate max-age" },
      { "name": "csp", "label": "Content Security Policy", "status": "warn", "message": "CSP present but uses unsafe-inline" },
      ...
    ]
  }
}

Quality Checks

The quality.checks array contains up to 11 checks. Each check has a status of pass, skip, warn, or fail:

CheckWhat It Tests
hstsHSTS header present with adequate max-age
cspContent Security Policy present and effective
corsCORS configuration is not overly permissive
x_frame_optionsX-Frame-Options set to DENY or SAMEORIGIN
x_content_type_optionsX-Content-Type-Options: nosniff is present
referrer_policyReferrer-Policy is set and not unsafe
permissions_policyPermissions-Policy restricts sensitive features
cookiesSession cookies have Secure, HttpOnly, SameSite
redirect_chainHTTP-to-HTTPS redirect is present and correct
content_typeContent-Type header includes charset
redirect_limitRedirect chain is not excessively long

Useful One-Liners

# Get the overall verdict
curl -s 'https://http.netray.info/api/inspect?url=https%3A%2F%2Fexample.com' \
  | jq '.quality.verdict'

# List all failing checks
curl -s 'https://http.netray.info/api/inspect?url=https%3A%2F%2Fexample.com' \
  | jq '[.quality.checks[] | select(.status == "fail")]'

# Check HSTS max-age
curl -s 'https://http.netray.info/api/inspect?url=https%3A%2F%2Fexample.com' \
  | jq '.probes[] | select(.type == "https") | .hsts'

# CI gate: fail if verdict is not Pass
curl -sf 'https://http.netray.info/api/inspect?url=https%3A%2F%2Fexample.com' \
  | jq -e '.quality.verdict == "Pass"'

Rate Limits

Per-IP GCRA rate limiting. Each request triggers up to three outbound probes (HTTPS, HTTP upgrade, CORS), so the effective cost is higher than a simple GET request.

When rate-limited, you receive a 429 response with a Retry-After header.

Errors

{
  "error": {
    "code": "bad_request",
    "message": "Missing required parameter: url"
  }
}

Common error codes:

CodeMeaning
bad_requestMissing or invalid url parameter
rate_limitedToo many requests; check Retry-After
target_not_allowedTarget URL is in a disallowed range (private IP, localhost)
internal_errorServer error; include X-Request-Id in reports