Content Security Policy for Vercel — Generate and Deploy
Vercel does not add a Content Security Policy by default. You define it in vercel.json under the headers key. Start with report-only mode to collect violations before enforcing.
Step 1 — Find what your page loads first
Before writing a CSP, you need to know what external resources your page loads. Open DevTools → Network, reload the page, and note every external domain in the requests list. Or use CSPFixer — it scans your live URL automatically.
Step 2 — Build your vercel.json config
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://www.google-analytics.com; frame-ancestors 'none'; object-src 'none';"
}
]
}
]
}
Step 3 — Start with report-only
Use Content-Security-Policy-Report-Only first. It logs violations to the console without blocking anything, so you can see what needs to be added before enforcing:
{
"key": "Content-Security-Policy-Report-Only",
"value": "default-src 'self'; script-src 'self'; report-uri https://your-reporting-endpoint.com/csp"
}
Common Vercel stack additions
| Service | Directive to add |
|---|---|
| Google Fonts | style-src + https://fonts.googleapis.com; font-src + https://fonts.gstatic.com |
| Google Analytics | script-src + https://www.googletagmanager.com; connect-src + https://www.google-analytics.com |
| Stripe.js | script-src + https://js.stripe.com; frame-src + https://js.stripe.com |
| Intercom | script-src + https://widget.intercom.io; connect-src + https://api.intercom.io |
| Hotjar | script-src + https://static.hotjar.com; connect-src + https://*.hotjar.com |
After deploying
Open DevTools Console and look for CSP violation messages. Each one tells you exactly which domain needs to be added to which directive. Keep iterating until violations stop.
Generate your CSP from your live page →