CORS vs CSP connect-src Explained
Two separate browser mechanisms can stop a fetch() to another origin, and they are constantly mistaken for one another. Content-Security-Policy’s connect-src decides whether the page is even allowed to make the request; CORS decides whether the page is allowed to read the response after the server answers. They live on different servers, produce different console messages, and require different fixes.
This page is part of CORS & Related Security Header Interactions, which maps how CORS relates to the other cross-origin security layers.
The Two Error Strings
A CSP connect-src violation (Chrome):
Refused to connect to 'https://api.example.com/v1/data' because it violates the
following Content Security Policy directive: "connect-src 'self' https://cdn.example.com".
A CORS failure (Chrome):
Access to fetch at 'https://api.example.com/v1/data' from origin 'https://app.example.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource.
If the message contains “Refused to connect” and names a Content Security Policy directive, it is CSP — the request never left the browser. If it says “blocked by CORS policy”, the request was sent and the response was rejected.
Root Cause
The two mechanisms gate different steps of the same request. Content-Security-Policy is defined by the W3C CSP specification and is enforced on the requesting document: connect-src is an allowlist of destinations the page’s scripts may open connections to (via fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon). The browser checks it before dispatching the request. CORS, defined by the WHATWG Fetch Standard, is enforced after the server responds: it governs whether JavaScript may read a cross-origin response. Because CSP fires first, a connect-src block means the API server never even receives the request — so no amount of server-side Access-Control-Allow-Origin configuration will resolve it.
Prerequisite State
- You can see the exact console error text (open DevTools → Console).
- You can edit either the page’s
Content-Security-Policyheader (for CSP) or the API server’s CORS config.
Step-by-Step
Step 1 — Identify which gate fired
Read the console message. “Refused to connect … Content Security Policy” → CSP. “blocked by CORS policy” → CORS. This determines which server you fix.
Step 2a — Fix a CSP connect-src block
Add the API origin to the connect-src directive in the Content-Security-Policy header served by the page’s origin:
# On the server that serves the HTML page (not the API)
add_header Content-Security-Policy
"default-src 'self'; connect-src 'self' https://api.example.com" always;
Step 2b — Fix a CORS block
Add the correct Access-Control-Allow-Origin on the API server:
// On the API server that receives the fetch
res.setHeader('Access-Control-Allow-Origin', 'https://app.example.com');
res.setHeader('Vary', 'Origin');
Step 3 — Re-test both gates
A request can clear CSP and then hit CORS. Fix one, reload, and read the next error. Only when neither message appears is the request fully permitted.
Verification
Security Boundary Note
Do not loosen connect-src to * or drop CSP entirely just to clear the error — that removes a defense against exfiltration by injected scripts. Add only the specific API origin you need. Likewise, do not respond to a CORS error by reflecting every origin; keep the API’s allowlist tight. The two headers are independent defenses, and weakening one to fix a symptom in the other leaves both weaker.
Common Mistakes
| Issue | Technical impact | Mitigation |
|---|---|---|
| Editing API CORS headers to fix a CSP error | The request never reached the API; nothing changes | Fix connect-src on the page’s origin instead |
Adding the API to connect-src to fix a CORS error |
Request was already sent; the response is still blocked | Fix Access-Control-Allow-Origin on the API |
Setting connect-src * to make the error go away |
Removes exfiltration protection for the whole page | Allowlist only the specific API origin |
FAQ
Can a CSP connect-src violation look like a CORS error?
They produce different console messages, but developers confuse them because both stop a cross-origin fetch. A CSP violation says the request was “Refused to connect” for violating a Content-Security-Policy directive; a CORS error says the response was “blocked by CORS policy”. CSP fires first — the request is never sent — so fixing the server’s CORS headers will not help a CSP block.
Which fires first, CSP or CORS?
CSP connect-src is evaluated before the request leaves the browser. If the destination is not allowed, the browser refuses to send the request and CORS is never reached. Only if connect-src permits the destination does the request go out and CORS then govern whether the response may be read.
Do I fix connect-src on the server or the client?
connect-src is part of the Content-Security-Policy header sent by the page’s own server (or a page meta tag). You add the API origin to that directive on the document that runs the script. CORS is fixed on the API server that receives the request — a different server.