SecurityHeaders.com API Migration Guide (2026)

April 11, 2026 · 10 min read

The securityheaders.com API is shutting down in April 2026. If you have CI/CD pipelines, compliance scripts, or monitoring dashboards that call the securityheaders.com API, those integrations are about to break. This guide walks you through migrating to the DetectZeStack /security endpoint — step by step, with before/after examples you can copy-paste.

Time estimate: 5–15 minutes depending on how many scripts reference the old API. The endpoint URL, authentication, and response format all change, but the core workflow stays the same: send a URL, get a grade.

Step 1: Get Your API Key

DetectZeStack is available through RapidAPI. The free tier gives you 100 requests per month with no credit card required.

  1. Go to rapidapi.com/mlugoapx/api/detectzestack
  2. Click Subscribe to Test and select the Basic (free) plan
  3. Copy your API key from the X-RapidAPI-Key field in the code snippets panel

Store the key as an environment variable. You will reference it in all your scripts:

export RAPIDAPI_KEY="your-api-key-here"

Step 2: Update the Endpoint URL

Here is what the old securityheaders.com API call looked like:

Before: SecurityHeaders.com API

# Old securityheaders.com API (no longer working)
curl -s "https://securityheaders.com/?q=example.com&followRedirects=on" \
  -H "x-api-key: YOUR_SECURITYHEADERS_KEY"

The securityheaders.com API returned the grade in an HTTP response header (X-Grade) and the body was HTML. Extracting structured data required parsing HTML or relying on undocumented response headers.

After: DetectZeStack API

# DetectZeStack /security endpoint
curl -s "https://detectzestack.p.rapidapi.com/security?url=example.com" \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H "x-rapidapi-host: detectzestack.p.rapidapi.com"

The DetectZeStack API returns structured JSON in the response body. No HTML parsing. No undocumented headers. The grade, score, and per-header results are all explicit fields.

Step 3: Map the Response Format

Here is a side-by-side comparison of what you get back:

Field SecurityHeaders.com DetectZeStack
Letter grade X-Grade response header grade (JSON field)
Numeric score Not available score (0–130)
Per-header results Embedded in HTML body tests object (JSON)
Response format HTML JSON
Scan timing Not available scan_time_ms (integer)
Cache indicator Not available cached (boolean)

Here is the full JSON response from GET /security?url=example.com:

{
  "url": "https://example.com",
  "domain": "example.com",
  "grade": "F",
  "score": 15,
  "max_score": 130,
  "scan_time_ms": 287,
  "cached": false,
  "tests": {
    "strict-transport-security": {
      "pass": false,
      "score_modifier": 0,
      "result": "HSTS header missing",
      "value": "",
      "info": "No Strict-Transport-Security header found"
    },
    "content-security-policy": {
      "pass": false,
      "score_modifier": 0,
      "result": "CSP header missing",
      "value": "",
      "info": "No Content-Security-Policy header found"
    },
    "x-frame-options": {
      "pass": true,
      "score_modifier": 15,
      "result": "SAMEORIGIN",
      "value": "SAMEORIGIN",
      "info": "Clickjacking protection enabled"
    },
    "x-content-type-options": {
      "pass": true,
      "score_modifier": 15,
      "result": "nosniff enabled",
      "value": "nosniff",
      "info": "MIME-type sniffing blocked"
    }
  }
}

Key difference: With securityheaders.com, you extracted the grade from an HTTP response header. With DetectZeStack, the grade is a JSON field in the response body. This is more reliable and easier to parse in any language.

Step 4: Update Your Parsing Logic

If your old script extracted the grade from securityheaders.com, here is how to update it:

Before: Parsing SecurityHeaders.com

# Old: extract grade from X-Grade response header
GRADE=$(curl -sI "https://securityheaders.com/?q=$DOMAIN&followRedirects=on" \
  -H "x-api-key: $SH_API_KEY" \
  | grep -i "x-grade:" | awk '{print $2}' | tr -d '\r')

After: Parsing DetectZeStack

# New: extract grade from JSON response body
GRADE=$(curl -s "https://detectzestack.p.rapidapi.com/security?url=$DOMAIN" \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H "x-rapidapi-host: detectzestack.p.rapidapi.com" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['grade'])")

If you have jq installed, the parsing is even simpler:

# Using jq
GRADE=$(curl -s "https://detectzestack.p.rapidapi.com/security?url=$DOMAIN" \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H "x-rapidapi-host: detectzestack.p.rapidapi.com" \
  | jq -r '.grade')

Step 5: CI/CD Integration Script

Here is a complete bash script you can drop into any CI/CD pipeline. It scans your deployment URL, checks the grade, and fails the build if the grade is below your threshold:

#!/bin/bash
# ci-security-headers.sh
# Usage: RAPIDAPI_KEY=xxx DEPLOY_URL=example.com MINIMUM_GRADE=C ./ci-security-headers.sh

set -euo pipefail

DEPLOY_URL="${DEPLOY_URL:?DEPLOY_URL is required}"
RAPIDAPI_KEY="${RAPIDAPI_KEY:?RAPIDAPI_KEY is required}"
MINIMUM_GRADE="${MINIMUM_GRADE:-C}"

API_URL="https://detectzestack.p.rapidapi.com/security?url=$DEPLOY_URL"

echo "Scanning security headers for $DEPLOY_URL..."

RESPONSE=$(curl -sf "$API_URL" \
  -H "x-rapidapi-key: $RAPIDAPI_KEY" \
  -H "x-rapidapi-host: detectzestack.p.rapidapi.com")

GRADE=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['grade'])")
SCORE=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['score'])")

echo "Grade: $GRADE ($SCORE/130)"

# Grade ordering for comparison
grade_rank() {
  case "$1" in
    A+) echo 6 ;; A) echo 5 ;; B) echo 4 ;;
    C) echo 3 ;; D) echo 2 ;; F) echo 1 ;;
    *) echo 0 ;;
  esac
}

ACTUAL_RANK=$(grade_rank "$GRADE")
MIN_RANK=$(grade_rank "$MINIMUM_GRADE")

if [ "$ACTUAL_RANK" -lt "$MIN_RANK" ]; then
  echo "FAIL: Grade $GRADE is below minimum $MINIMUM_GRADE"
  # Print failing headers for quick debugging
  echo ""
  echo "Failing headers:"
  echo "$RESPONSE" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for header, result in data.get('tests', {}).items():
    if not result.get('pass', False):
        print(f'  {header}: {result.get(\"result\", \"unknown\")}')
"
  exit 1
fi

echo "PASS: Security headers grade $GRADE meets minimum $MINIMUM_GRADE"

GitHub Actions Example

Add this step to your deployment workflow:

# .github/workflows/deploy.yml
- name: Check security headers
  env:
    RAPIDAPI_KEY: ${{ secrets.RAPIDAPI_KEY }}
    DEPLOY_URL: ${{ env.DEPLOY_URL }}
    MINIMUM_GRADE: "C"
  run: |
    RESPONSE=$(curl -sf "https://detectzestack.p.rapidapi.com/security?url=$DEPLOY_URL" \
      -H "x-rapidapi-key: $RAPIDAPI_KEY" \
      -H "x-rapidapi-host: detectzestack.p.rapidapi.com")
    GRADE=$(echo "$RESPONSE" | jq -r '.grade')
    echo "Security headers grade: $GRADE"
    if [[ "$GRADE" == "D" || "$GRADE" == "F" ]]; then
      echo "::error::Security headers grade is $GRADE (minimum: C)"
      echo "$RESPONSE" | jq '.tests | to_entries[] | select(.value.pass == false) | "\(.key): \(.value.result)"'
      exit 1
    fi

GitLab CI Example

# .gitlab-ci.yml
security-headers-check:
  stage: test
  script:
    - |
      RESPONSE=$(curl -sf "https://detectzestack.p.rapidapi.com/security?url=$DEPLOY_URL" \
        -H "x-rapidapi-key: $RAPIDAPI_KEY" \
        -H "x-rapidapi-host: detectzestack.p.rapidapi.com")
      GRADE=$(echo "$RESPONSE" | jq -r '.grade')
      echo "Grade: $GRADE"
      if [ "$GRADE" = "D" ] || [ "$GRADE" = "F" ]; then
        echo "Security headers grade too low: $GRADE"
        exit 1
      fi

Step 6: Bulk Migration for Multiple Domains

If you were scanning multiple domains with the securityheaders.com API, here is a bash loop that migrates the workflow:

#!/bin/bash
# bulk-security-scan.sh
# Scan multiple domains and output a CSV report

DOMAINS=(
  "example.com"
  "staging.example.com"
  "api.example.com"
)

echo "domain,grade,score,hsts,csp,x_frame_options"

for domain in "${DOMAINS[@]}"; do
  RESPONSE=$(curl -s "https://detectzestack.p.rapidapi.com/security?url=$domain" \
    -H "x-rapidapi-key: $RAPIDAPI_KEY" \
    -H "x-rapidapi-host: detectzestack.p.rapidapi.com")

  ROW=$(echo "$RESPONSE" | python3 -c "
import sys, json
d = json.load(sys.stdin)
t = d.get('tests', {})
hsts = 'pass' if t.get('strict-transport-security', {}).get('pass') else 'FAIL'
csp = 'pass' if t.get('content-security-policy', {}).get('pass') else 'FAIL'
xfo = 'pass' if t.get('x-frame-options', {}).get('pass') else 'FAIL'
print(f\"${domain},{d['grade']},{d['score']},{hsts},{csp},{xfo}\")
")
  echo "$ROW"
  sleep 1  # Rate limiting
done

Pricing Comparison

Plan Requests/Month Price
Basic (Free) 100 $0/mo
Pro 1,000 $9/mo
Ultra 10,000 $29/mo
Mega 50,000 $79/mo

The free tier is enough for most CI/CD use cases: if you deploy once per day, 100 requests covers 3+ domains. For teams scanning larger portfolios or running multiple pipelines, the Pro plan at $9/month provides 1,000 requests — enough for 33 domains scanned daily.

What You Gain Beyond SecurityHeaders.com

The /security endpoint is a direct replacement for securityheaders.com, but your API key also unlocks endpoints that securityheaders.com never offered:

All endpoints share the same API key and the same request quota. No separate subscriptions.

Migration Checklist

  1. Get API key — Sign up on RapidAPI (free, no credit card)
  2. Set environment variable — export RAPIDAPI_KEY=your-key in CI/CD secrets
  3. Find all references — Search your codebase for securityheaders.com and list every file
  4. Update endpoint URL — Replace with https://detectzestack.p.rapidapi.com/security?url=DOMAIN
  5. Update auth headers — Replace x-api-key with x-rapidapi-key and add x-rapidapi-host
  6. Update response parsing — Read grade from JSON body instead of X-Grade response header
  7. Test against a known domain — Verify the grade matches your expectations
  8. Deploy and monitor — Check that your pipeline passes/fails correctly

You can also try an interactive scan on the Security Headers page — no API key needed.

Related Reading

Migrate from SecurityHeaders.com in 10 Minutes

100 requests per month free. Structured JSON. A+ to F grading. Drop-in replacement for CI/CD pipelines, compliance scripts, and monitoring dashboards.

Get Your Free API Key

Get API updates and tech detection tips

Join the mailing list. No spam, unsubscribe anytime.