Security Headers on Vercel — Complete vercel.json Configuration

Updated April 2026

Quick Answer Add security headers to Vercel via vercel.json: create a headers array with a source: "/(.*)" entry and list each header as key-value pairs. The headers apply to every deployment automatically. For Next.js, use the async headers() function in next.config.js instead.

Vercel sets security headers via vercel.json. No server config needed — just add a headers array and every deployment gets them automatically.

Scan your live Vercel site → HeadersFixer

Complete vercel.json — copy and paste

{ "headers": [ { "source": "/(.*)", "headers": [ { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }, { "key": "X-Frame-Options", "value": "SAMEORIGIN" }, { "key": "X-Content-Type-Options", "value": "nosniff" }, { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }, { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=(), interest-cohort=()" }, { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } ] } ]
}

Place this in vercel.json at the root of your project. Redeploy and headers will appear on every response.

Adding CSP

vercel.json Strict-Transport-Security example

The most searched vercel.json security header — exact copy-paste:

{ "headers": [ { "source": "/(.*)", "headers": [ { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" } ] } ]
}

Add ; preload to the value only after verifying all subdomains support HTTPS and you've submitted at hstspreload.org.

CSP requires knowing your sources first. Add it as another entry in the headers array:

{ "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'self';"
}
Start with Content-Security-Policy-Report-Only instead of Content-Security-Policy — it logs violations without blocking anything. Switch to enforcing once violations stop appearing in the browser console.

Path-specific headers

Apply different headers to different paths using separate source patterns:

{ "headers": [ { "source": "/(.*)", "headers": [ {"key": "X-Content-Type-Options", "value": "nosniff"}, {"key": "X-Frame-Options", "value": "SAMEORIGIN"} ] }, { "source": "/api/(.*)", "headers": [ {"key": "Cache-Control", "value": "no-store"}, {"key": "Access-Control-Allow-Origin", "value": "https://your-frontend.com"} ] }, { "source": "/static/(.*)", "headers": [ {"key": "Cache-Control", "value": "public, max-age=31536000, immutable"} ] } ]
}

Next.js — headers in next.config.js

For Next.js projects, you can set headers in next.config.js instead:

/** @type {import('next').NextConfig} */
const nextConfig = { async headers() { return [ { source: '/(.*)', headers: [ { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' }, { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, ], }, ] },
}

module.exports = nextConfig

Vercel Edge Middleware

For dynamic header logic (e.g. different CSP per route), use Edge Middleware:

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) { const response = NextResponse.next() response.headers.set('X-Frame-Options', 'SAMEORIGIN') response.headers.set('X-Content-Type-Options', 'nosniff') return response
}

export const config = { matcher: '/(.*)',
}

Verifying your headers

After deploying, paste your Vercel URL into HeadersFixer to confirm all headers are present and correctly configured:

Verify headers on your live site → HeadersFixer