Refused to load (CSP) medium
"Refused to load … violates the following Content Security Policy directive"
A Content-Security-Policy header blocked a script, style, image, or inline code because its source isn't on the page's allowlist.
What you see
Refused to load the script 'https://cdn.example.com/widget.js' because it violates the following Content Security Policy directive: "script-src 'self' https://apis.google.com".
What’s actually happening
The page renders but something is broken — a widget doesn't appear, analytics never fire, a font or image is missing, a button does nothing. The clue is in the DevTools Console, not the Network tab: a red "Refused to load…" or "Refused to execute inline script…" line naming the exact resource and the directive that blocked it. The browser is enforcing your own policy correctly; the allowlist is just incomplete.
Common causes
- A third-party resource (CDN, analytics, tag manager, font host, embed) whose domain isn't listed in the relevant directive — script-src, style-src, img-src, connect-src, font-src, frame-src
- Inline <script> or onclick= handlers blocked because the policy lacks 'unsafe-inline' (and modern policies intentionally omit it)
- Inline styles or injected style attributes blocked by a strict style-src
- A strict-dynamic or nonce/hash-based policy where a script loaded without the matching nonce or hash
- connect-src too narrow, so fetch/XHR/WebSocket calls to an API or third-party endpoint get refused
How to fix it
- Read the directive in the console messageThe error tells you both halves: the blocked URL and the directive that rejected it (e.g. script-src). That's exactly what to change — you're either adding a host to that directive or allowing the inline case. Note whether it says "load" (external resource → add the host) or "execute inline" (inline code → needs a nonce/hash or, last resort, 'unsafe-inline').
- Add the host to the correct directiveEdit the Content-Security-Policy header where it's set — server config (nginx add_header, Apache Header set), a meta tag, or your app/CDN (Cloudflare Transform Rules, Next.js headers()). Append the exact origin to the matching directive, e.g. script-src 'self' https://apis.google.com https://cdn.example.com. Add the scheme and host; avoid wildcards like https: that defeat the policy.
- Handle inline code properlyFor blocked inline scripts/styles, prefer a nonce — add nonce-RANDOM to the directive and the same nonce attribute to the tag — or a sha256- hash of the inline content (the console often prints the expected hash). Reaching for 'unsafe-inline' works but reopens the XSS hole CSP exists to close; use it only as a stopgap.
- Verify with Report-Only before enforcingWhen tightening a policy, ship Content-Security-Policy-Report-Only first. Violations log to the console (and report-uri) without breaking anything, so you can enumerate every host you actually need, fold them in, then switch to the enforcing header.
Stop it recurring
Stage CSP changes with Content-Security-Policy-Report-Only and use nonces/hashes for inline code instead of 'unsafe-inline'.
Related errors