Content-Security-Policy header examples (nginx, Apache, HTML)
A Content-Security-Policy (CSP) header tells the browser which sources may load scripts, styles, images and frames. Below is one sensible starting policy in three formats, each tested.
1. The policy
default-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'none';
form-action 'self';
script-src 'self' https://cdn.example.com 'sha256-abc+/=';
img-src 'self' data:;
style-src 'self' 'unsafe-inline';
upgrade-insecure-requests
Everything comes from your own origin by default; scripts may also come from one CDN and from one inline script identified by its hash. 'sha256-abc+/=' is a placeholder: replace it with the real hash of your inline script (Chrome's console prints it when the script is blocked), or remove it. frame-ancestors 'none' stops other sites from framing yours.
2. nginx
Inside the server or location block:
add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'; script-src 'self' https://cdn.example.com 'sha256-abc+/='; img-src 'self' data:; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests" always;
always adds the header to error pages (404, 500) too. Note that an add_header inside a location replaces all add_header lines inherited from server, so keep your security headers together.
3. Apache
In the virtual host or .htaccess (needs mod_headers):
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'; script-src 'self' https://cdn.example.com 'sha256-abc+/='; img-src 'self' data:; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests"
</IfModule>
4. HTML meta tag (when you cannot set headers)
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; script-src 'self' https://cdn.example.com 'sha256-abc+/='; img-src 'self' data:; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests">
Put it at the top of <head>. A meta CSP ignores frame-ancestors (removed above), report-only mode and reporting, so prefer the header when you can.
5. Check it
curl -s -D - -o /dev/null https://your-site.example | grep -i content-security-policy
On both test servers this printed:
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'; script-src 'self' https://cdn.example.com 'sha256-abc+/='; img-src 'self' data:; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests
6. Roll out safely
Send the same value as Content-Security-Policy-Report-Only first: the browser reports violations in the console but blocks nothing. Fix what it reports, then switch the header name. The free CSP & security headers generator builds the policy and all three formats (plus Netlify and Express), with a report-only switch; PlainHeaders lets you try a policy on a live site in your own browser before deploying it.
Frequently asked questions
Why does my CSP header not appear on some pages?
In nginx, add_header lines in a location block replace the ones from the server block, and without 'always' they are skipped on error responses.
Can I use a CSP meta tag instead of a header?
Yes, for most directives. frame-ancestors, sandbox, report-uri and report-only mode only work as a real HTTP header.
Written with AI assistance. On 2026-10-01 the nginx and Apache examples were loaded into real nginx (alpine) and Apache httpd (alpine) servers: nginx -t and httpd -t passed, and curl showed the exact header below on both. PlainHeaders is our extension; the other methods are free.