October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
COEP

How to Check Cross-Domain Policy Headers (CORS, CORP, COEP and COOP)

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Start in your browser’s DevTools: open Network, reload the page, select the failed request, and compare its Origin request header with the response’s CORS headers. For a non-simple request, inspect the preceding OPTIONS preflight as well. This shows whether the server authorized the method, headers and credentials that the browser actually sent.

When the failure involves an embedded resource or cross-origin isolation rather than JavaScript reading a response, check Cross-Origin-Resource-Policy (CORP), Cross-Origin-Embedder-Policy (COEP) and Cross-Origin-Opener-Policy (COOP) separately. They are related policies, but they are enforced at different stages.

What you are checking

Cross-origin policy is determined by the page’s origin: scheme, host and port. A page at https://app.example and an API at https://api.example are different origins even though they share a registrable domain.

CORS is an HTTP-header protocol for deciding whether a browser may expose a cross-origin response to script. A successful request at the network layer does not necessarily mean JavaScript can read the body. The browser applies the policy after receiving the response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Record these facts first

  • Failing URL, including scheme, host, port and any redirect.
  • Origin of the page that initiated the request.
  • Request mode (cors, no-cors or another mode) and credentials mode.
  • HTTP method and non-safelisted request headers.
  • Status code, response headers and the exact console error.

Check CORS in browser DevTools

  1. Open the page that makes the request.
  2. Open Developer Tools and choose Network.
  3. Enable Preserve log, disable cache if useful, and reload.
  4. Select the failed request. In Headers, expand Request Headers and note Origin, method, credentials-related headers and any custom headers.
  5. In Response Headers, inspect Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Expose-Headers, and, where relevant, Access-Control-Allow-Methods and Access-Control-Allow-Headers.
  6. Check every redirect hop. A CORS header on an earlier response does not authorize a later redirected response.

Interpret the main response headers

Header What to verify Typical failure
Access-Control-Allow-Origin It matches the requesting origin, or is * when no credentials are used. Missing header, wrong scheme/port, or an origin not on the allow list.
Access-Control-Allow-Credentials For credentialed requests, the response explicitly permits credentials. Cookies or HTTP authentication are sent, but credentials permission is absent.
Access-Control-Expose-Headers Lists response headers that browser JavaScript is allowed to read beyond the safelist. The response is usable, but a needed header appears unavailable to script.
Vary: Origin Present when the server returns different authorization headers for different origins. A cache serves one origin’s CORS response to another origin.

For credentialed requests, do not combine a wildcard origin with credentials. Return the specific permitted origin and the credential permission instead. Keep the allow list narrow: allowing an arbitrary origin can expose data to untrusted sites.

Test an OPTIONS preflight

Browsers preflight requests that are not “simple”, such as many requests using methods other than GET, HEAD or POST, or requests with non-safelisted headers. The browser sends OPTIONS before the actual request.

What the browser sends

OPTIONS /v1/items HTTP/1.1
Host: api.example
Origin: https://app.example
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: authorization, content-type

What a valid preflight response needs

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Allow-Credentials: true

The method and header names in Access-Control-Allow-Methods and Access-Control-Allow-Headers must authorize what the browser requested. A preflight that returns a successful status but omits one of these permissions still fails in the browser.

Reproduce the preflight with curl

curl -i -X OPTIONS 'https://api.example/v1/items' 
  -H 'Origin: https://app.example' 
  -H 'Access-Control-Request-Method: PUT' 
  -H 'Access-Control-Request-Headers: authorization,content-type'

Replace the URL, origin, method and header list with the values shown in DevTools. This tests server behavior, but it does not reproduce browser enforcement of redirects, request mode or credentials. Compare the command’s response with the actual preflight captured in the browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Distinguish CORS, CORP, COEP and COOP

Policy Where it is set Primary question Important values or checks
CORS Response to a cross-origin request May script read this response? Access-Control-Allow-Origin, credentials, methods and headers.
CORP Resource response May this resource be embedded by another origin in a no-cors load? Cross-Origin-Resource-Policy: same-origin, same-site or cross-origin.
COEP Document response Must cross-origin subresources opt in before this document can use them? require-corp or credentialless.
COOP Document response Should this browsing context be isolated from cross-origin opener windows? For cross-origin isolation, commonly same-origin together with COEP.

CORP: embedding protection

Inspect Cross-Origin-Resource-Policy on images, scripts, fonts and other resources loaded in no-cors mode. same-origin restricts use to the exact origin, same-site permits the same registrable site, and cross-origin permits other origins. CORP can cause the browser to hide the response body even when the server returned a successful status.

COEP: document-wide embedding rules

On the top-level document response, check Cross-Origin-Embedder-Policy. require-corp requires eligible no-cors subresources to be same-origin or explicitly opt in through CORP. credentialless permits certain no-cors loads without credentials. A request made in CORS mode still needs normal CORS permission.

COOP and cross-origin isolation

Cross-Origin-Opener-Policy: same-origin separates the document’s opener browsing context. When paired with COEP require-corp or credentialless, it can enable cross-origin isolation. Verify the result in the page with window.crossOriginIsolated; a policy header alone is not proof that isolation succeeded.

A repeatable troubleshooting workflow

  1. Identify the exact exchange. Capture the page origin, URL, method, mode and credentials mode.
  2. Follow redirects. Inspect the response actually received at each hop, not just the initial URL.
  3. Find the preflight. If an OPTIONS request exists, compare its requested method and headers with the server’s allow lists.
  4. Classify the block. A JavaScript read failure usually points to CORS; a blocked image, script or font may be CORP/COEP; isolation failures involve COOP and COEP.
  5. Check cache behavior. If authorization varies by origin, ensure intermediaries do not reuse one origin’s response for another and that Vary: Origin is handled.
  6. Document evidence. Save the URL, status, exact header values and console message in the defect report.

Common symptoms and fixes

  • “No Access-Control-Allow-Origin header.” Add a response header for the requesting origin on the API response and on any relevant error or redirect response.
  • Wildcard fails with cookies. Replace * with the explicit origin and return Access-Control-Allow-Credentials: true when credentials are intentionally supported.
  • Preflight method is not allowed. Add the requested method to Access-Control-Allow-Methods, or change the client to an allowed method.
  • Request header is not allowed. Add each requested non-safelisted header to Access-Control-Allow-Headers, including its actual spelling as shown by DevTools.
  • Response header is invisible to JavaScript. Add it to Access-Control-Expose-Headers.
  • Works with curl but not in the browser. Curl does not enforce browser CORS, redirects, credentials and embedding rules. Reproduce the browser’s exact origin and request sequence.
  • Resource blocked under COEP. Make the resource same-origin, serve it with suitable CORP, or fetch it with CORS and a server response that authorizes the page.
  • Isolation remains false. Check both document headers, every subresource, and the console for a single resource that violates COEP.

Performance, reliability and security considerations

Preflight requests add a network round trip. Servers can advertise a suitable preflight cache lifetime with Access-Control-Max-Age, but changing permissions may appear delayed while a browser uses a cached result. Keep authorization responses deterministic and cache-aware.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not treat CORS as authentication. It controls which browser scripts may read responses; it does not stop a non-browser client from sending requests. Enforce authentication and authorization on the server, validate origins deliberately, and avoid reflecting arbitrary Origin values.

For incident reports, include a DevTools HAR or screenshots only after removing tokens, cookies and personal data. Never paste an Authorization header or session cookie into a public bug.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you need a clean visual record of how a page renders after policy changes, ScreenshotNeo can capture the page through one HTTP call. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; bot checks, blank pages, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools to AI agents such as Claude and Cursor.

ScreenshotNeo does not replace DevTools for reading HTTP headers; use the browser or an HTTP client for that evidence. It is useful when you also need a reproducible screenshot or PDF of the affected page.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for output and options. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Best Value
Sale
The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws
  • Comes with secure packaging
  • It can be a gift item
  • Easy to read text

Other client examples

Python

import requests

r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Frequently Asked Questions

Does a 200 status prove that CORS is configured correctly?

No. The server can return 200 while the browser withholds the response from script because the CORS headers do not authorize the requesting origin, credentials, method or headers.

Why is there no OPTIONS request in Network?

The request may be simple, the browser may have a cached preflight result, or the request may have been blocked before a preflight was sent. Disable cache and inspect the complete network log.

Can CORP replace CORS?

No. CORP governs embedding of resources in no-cors mode, while CORS governs whether script may read a cross-origin response. A resource can require both checks in different contexts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.