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 keySign up on RapidAPI (free, no credit card)
  2. Set environment variableexport 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.