# How to debug CSP violations in Chrome DevTools (/en/blog/debug-csp-violations-devtools)





When a Content Security Policy (CSP) blocks something, the browser tells you in the console, and the message names both the resource it refused and the directive that did the refusing. The fastest way to debug a violation is to read that message, then open the DevTools Issues panel, which breaks the same violation into the blocked resource, the violated directive, the source location, and a link to the element that triggered it. From there you map the directive to the fix.

This post walks through reading the "Refused to..." console message, opening and using the [Chrome DevTools](https://developer.chrome.com/docs/devtools) Issues panel, the common messages you will see and what each one means, and how to turn a message into the directive change that fixes it. It ends with the one thing DevTools cannot tell you.

## Read the console message first [#read-the-console-message-first]

The console line is the quickest signal. A blocked script produces something like this:

```text
Refused to load the script 'https://cdn.example/widget.js' because it
violates the following Content Security Policy directive: "script-src 'self'".
```

Read it in three parts:

* **The verb and resource.** "Refused to load the script '[https://cdn.example/widget.js](https://cdn.example/widget.js)'" tells you what the browser blocked and its URL. The verb changes by type: "Refused to load", "Refused to execute inline script", "Refused to apply inline style", "Refused to connect to", "Refused to frame".
* **The directive that blocked it.** "violates the following Content Security Policy directive: script-src 'self'" is the rule that did not match. This is the directive you will change, or the one whose source list is missing the origin you need.
* **The mode.** If the message says the resource "would be blocked" or mentions report-only, the policy is on [`Content-Security-Policy-Report-Only`](/en/blog/csp-enforce-vs-report-only) and nothing was actually blocked yet. An enforced policy says "Refused to" outright.

The console is enough for a quick read, but it does not always link you to the element or show the source cleanly. For that, use the Issues panel.

## Use the Issues panel [#use-the-issues-panel]

The Issues panel turns each violation into a structured card instead of a one-line string. For one violation it shows:

* the **violated directive** (for example `script-src`),
* the **blocked resource** (the URL, or "inline" for inline code),
* the **source location** (the file and line that loaded the resource),
* a **link to the element** in the Elements panel that caused it.

To open it: click the **Issues** counter in the DevTools top action bar, or use **More tools** then **Issues** from the DevTools menu (the three-dot overflow). Reload the page with DevTools open so the violations are captured. The Issues panel groups identical violations, so a script blocked on every navigation shows once with a count, which is easier to scan than the repeated console lines.

The element link is the part that saves time. Click it and DevTools jumps to the exact `<script>`, `<link>`, `<img>`, or `<iframe>` that triggered the block, so you can see whether it is your code or an injected third party.

## Common messages and what they mean [#common-messages-and-what-they-mean]

The verb in the message tells you the resource type, and the resource type tells you the directive. The frequent ones:

* **"Refused to load the script ..."** A script from a URL was blocked by [`script-src`](/en/docs/web-security/policies/content-security-policy/directives/script-src) (or `default-src` as fallback). The origin is not on the source list.
* **"Refused to execute inline script ..."** An inline `<script>` or an inline event handler (`onclick=...`) was blocked because `script-src` has no `'unsafe-inline'`, nonce, or matching hash. This is the intended behaviour of a strict policy.
* **"Refused to apply inline style ..."** An inline `style=` attribute or `<style>` block was blocked by `style-src` for the same reason.
* **"Refused to connect to ..."** A `fetch`, `XMLHttpRequest`, WebSocket, or `EventSource` request was blocked by `connect-src`.
* **"Refused to load the image ..."** An image URL was blocked by `img-src`.
* **"Refused to frame ..."** An `<iframe>` source was blocked by `frame-src`.
* **"Refused to evaluate a string as JavaScript ..."** A call to `eval`, `new Function`, or similar was blocked because `script-src` does not include `'unsafe-eval'`. The fix is usually to remove the `eval`, not to add the keyword.

Inline script and `eval` violations are the two that catch people out, because they are not about an origin you forgot. They mean the policy is doing its job and the page is relying on inline execution. The right response is a nonce or a hash for the inline block you control, not `'unsafe-inline'`, which switches the protection back off for everything. The reasoning is in [why you should never use unsafe-inline in CSP](/en/blog/unsafe-inline-csp).

## Map the message to the fix [#map-the-message-to-the-fix]

Once you know the directive and the resource, the change is mechanical:

* **A legitimate cross-origin resource was blocked.** Add its exact origin to the directive the message named. If `connect-src` blocked `https://api.example`, add that origin to `connect-src`. Add the specific origin, not a wildcard.
* **Your own inline script or style was blocked.** Give it a nonce (a fresh per-response random value in the directive and on the element) or a hash. See [get started with Content Security Policy](/en/blog/get-started-with-csp) for the nonce setup.
* **An `eval` was blocked.** Find the code that calls `eval` or `new Function` and replace it. A dependency that needs `eval` is worth flagging; adding `'unsafe-eval'` weakens the whole policy.
* **You do not recognise the resource at all.** That is the interesting case. An origin you did not add, on a page you did not change, can be an extension, or it can be an injected script. Do not allow it reflexively. Check the element link in the Issues panel to see where it came from.

If you want to confirm the change is sound before shipping it, the [CSP evaluator](/tools/csp-evaluator) scores a policy and flags weak sources, and [MDN's CSP guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) has the per-directive reference. After editing, reload with the Issues panel open and confirm the violation is gone.

## DevTools only sees your machine [#devtools-only-sees-your-machine]

The Issues panel shows violations on **your** browser, on **this** page, in **this** session, with **your** extensions. That is exactly what you want while you are fixing one page. It is not what tells you the policy is safe to enforce for everyone.

Real users hit violations you will never see locally: third-party scripts that only load in some regions, an extension you do not have, a page you did not test, a vendor tag that changed overnight. None of those show up in your DevTools. To enforce a policy without breaking the long tail, you collect violation reports from real traffic instead of relying on one machine. For what those reports contain and how the fields map to what you see in DevTools, see [CSP violation report fields](/en/blog/csp-violation-report-fields).

That collection is what the [CentralCSP CSP suite](/platform/csp-builder) does: it ingests the reports your real users generate, groups them by directive and origin, separates extension noise from genuine issues, and shows the scripts running on each page, so you debug from production evidence instead of a single browser tab. You can [start a free trial](/register), point a Report-Only header at it, and watch the violations arrive from real traffic.

<img alt="Violations from every visitor, grouped by directive and blocked origin" src="__img0" width="1365" height="691" />

## Sources [#sources]

* [Chrome DevTools documentation](https://developer.chrome.com/docs/devtools)
* [Chrome DevTools, the Issues panel](https://developer.chrome.com/docs/devtools/issues)
* [MDN, Content Security Policy guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)
* [W3C, Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)

## Related [#related]

* [Get started with Content Security Policy](/en/blog/get-started-with-csp)
* [Why you should never use unsafe-inline in CSP](/en/blog/unsafe-inline-csp)
* [CSP enforce vs report-only mode](/en/blog/csp-enforce-vs-report-only)
