Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

CORS Tester

See exactly why a browser blocks a cross-origin request, and the headers that fix it.

Network Uses live data Free, no sign-up

Request

MySmartCoPilot’s server sends the preflight and the request from its own address and returns only the response headers.

Public http:// or https:// address on the standard ports.

Scheme, host and port only, as in the browser’s Origin header — null for sandboxed iframes and file:// pages.

One per line. Values stay in your browser: only the names that need permission are sent. Leave out headers the browser adds itself (User-Agent, Sec-Fetch-…, Cookie).

Result

Enter the URL your code calls and the origin of the page that calls it. The test then shows:

  • whether the browser sends a preflight, and the exact request;
  • each check the browser runs on the answers, and the first one that fails;
  • the error message Chrome prints in the console;
  • which response headers your code can read, and caching problems;
  • the headers your server should send.

Next steps

About the CORS Tester

A browser lets a page read another site’s response only when the server says so with CORS headers. When it does not, your code gets a bare TypeError (“Failed to fetch” in Chrome) and the console a long red message. This tester runs the same checks the browser runs, in the same order, and tells you which one fails and what to change on the server.

Enter the URL your code calls, the origin of the calling page, the method and the headers your code sets. MySmartCoPilot’s server then sends the preflight (OPTIONS with Access-Control-Request-Method and Access-Control-Request-Headers) when a browser would send one, and the request itself with your Origin, follows redirects the way browsers do, and explains every Access-Control-* header in the answers: allowed origin, credentials, methods, headers, Max-Age, Expose-Headers and Vary: Origin. For APIs on localhost or behind a login, paste the response headers from your developer tools instead; they are checked in your browser.

How to use it

  1. Choose Live URL for a public API, or Paste headers for an API on localhost, a private network or behind a login.
  2. Enter the URL your code calls and the origin of the calling page (for example https://app.example.com or http://localhost:3000), and pick the method. Or paste the CORS error from the browser’s console into the URL field: the URL, the origin and, when the message names them, the method and header are filled in for you.
  3. List the headers your code sets, one per line (Content-Type: application/json, Authorization: Bearer <token>), and tick credentials if the call sends cookies (credentials: 'include'). Before you send anything, the panel shows whether a preflight comes first and its exact request.
  4. Press Test CORS (or Check headers): read the verdict, the check that fails, and the message Chrome prints in the console.
  5. Copy the headers that make this request work into your server or framework configuration, and test again. Copy report or Report (.txt) keeps the whole analysis.

Examples

A wildcard with credentials
Input
GET https://api.example.com/me from https://app.example.com, credentials: include
Response: Access-Control-Allow-Origin: *
Result
Blocked: the wildcard * is not allowed with credentials.
Fix: Access-Control-Allow-Origin: https://app.example.com, Access-Control-Allow-Credentials: true, Vary: Origin
A method missing from Access-Control-Allow-Methods
Input
PUT with Content-Type: application/json
Preflight answer: Access-Control-Allow-Methods: GET, POST and Access-Control-Allow-Headers: Content-Type
Result
Blocked at the preflight: "Method PUT is not allowed by Access-Control-Allow-Methods in preflight response."

GET, HEAD and POST always pass; every other method must be listed, in the same letter case your code sends.

A preflight that redirects
Input
DELETE https://api.example.com/v1/items/7 — the server answers OPTIONS with 301 to …/7/
Result
Blocked at the preflight: "Redirect is not allowed for a preflight request." Call the final URL directly.
A trailing slash in the allowed origin
Input
Origin: https://app.example.com
Access-Control-Allow-Origin: https://app.example.com/
Result
Blocked: the header names another origin — an origin never ends with a slash, and the comparison is exact.

Common uses

  • Finding out why fetch() from a single-page app fails with "has been blocked by CORS policy" before touching any code.
  • Checking a new API gateway, CDN or reverse-proxy rule before releasing it, including redirects and error responses.
  • Making sure a credentialed API (cookies or HTTP authentication) does not reflect every origin or trust "null".
  • Debugging an API on localhost by pasting the preflight and response headers from the browser’s network panel.
  • Getting the exact header lines to paste into server, framework or CDN configuration.

How a browser decides

The rules come from the Fetch Standard, which every current browser implements:

  • Simple or preflighted? GET, HEAD and POST with only CORS-safelisted headers (Accept, Accept-Language, Content-Language, Content-Type with application/x-www-form-urlencoded, multipart/form-data or text/plain, and a simple Range) are sent straight away. Anything else — another method, Content-Type: application/json, Authorization, any custom header — first gets a preflight: OPTIONS listing the method and the header names, sorted and in lower case.
  • The preflight passes only with a 2xx status, no redirect, an Access-Control-Allow-Origin that allows the origin, the method in Access-Control-Allow-Methods (GET, HEAD and POST always pass), and every header in Access-Control-Allow-Headers. Methods are compared case-sensitively, and * is a wildcard only without credentials. The standard says * never covers Authorization; current browsers still let it (Chrome with a warning), so list Authorization by name.
  • Every response, redirects included, must pass the CORS check: Access-Control-Allow-Origin is * (without credentials) or exactly the request’s origin, and with credentials Access-Control-Allow-Credentials is exactly true. After a redirect to another origin the browser sends Origin: null.
  • What your code can read: the status, the body and seven safelisted headers (Cache-Control, Content-Language, Content-Length, Content-Type, Expires, Last-Modified, Pragma), plus what Access-Control-Expose-Headers lists. Set-Cookie never.

Credentials, caching and Vary: Origin

With credentials: 'include' (or withCredentials in XMLHttpRequest) the server must name the exact origin and send Access-Control-Allow-Credentials: true; * fails in every header (Fetch Standard: CORS protocol and credentials). The preflight itself never carries cookies, so authentication must let OPTIONS through.

Browsers remember a successful preflight for Access-Control-Max-Age seconds, 5 when it is missing, per origin, URL and credentials mode, and cap it: Chrome at 7,200 seconds (Chromium source), Firefox at 86,400 (MDN) and Safari at 600 (WebKit source). Send digits only: Chrome and Safari fall back to 5 seconds for a value such as 10m, while Firefox then caches nothing at all (Firefox source), and a negative value turns the cache off everywhere.

When Access-Control-Allow-Origin depends on the request, send Vary: Origin, or a browser or CDN cache may serve one site’s answer to another (Fetch Standard: CORS protocol and HTTP caches). A fixed * needs no Vary.

What the live test sends

  • The preflight, only when a browser would send one: OPTIONS with your Origin, Access-Control-Request-Method and Access-Control-Request-Headers, without following redirects.
  • The request itself as GET (HEAD when you chose HEAD), with your Origin, following up to 4 redirects and switching to Origin: null after a redirect to another origin, as browsers do. PUT, PATCH, DELETE and POST are never sent, and no request body is sent: they could change data on your server.
  • Unless you untick it, the same GET once with Origin: https://unrelated-origin.example (a reserved domain nobody owns) and once with Origin: null, to see whether the server trusts any site.

Requests come from MySmartCoPilot’s server (a cloud data centre, usually near you) with the user agent MySmartCoPilotBot/1.0 and no cookies. Only the status lines and response headers come back; cookie values in Set-Cookie are hidden.

The console messages, decoded

  • No 'Access-Control-Allow-Origin' header is present — the response (or the preflight, when the message says "Response to preflight request…") has no such header. Often an error page from authentication, a proxy or a crashed handler.
  • …contains multiple values — the header arrives twice (application and proxy both add it) or holds a list. Send exactly one origin.
  • …is not equal to the supplied origin — a different origin, a trailing slash, another scheme, port or letter case.
  • **…must not be the wildcard '' when the request's credentials mode is 'include'* — use the exact origin with Access-Control-Allow-Credentials: true.
  • It does not have HTTP ok status — the preflight got 401, 404, 405 or 500: let OPTIONS through before authentication and routing.
  • Method … / Request header field … is not allowed — add it to Access-Control-Allow-Methods / Access-Control-Allow-Headers.

These are Chrome’s wordings (Chromium source); Firefox and Safari describe the same failures in their own words (MDN: CORS errors).

Limitations

  • The live test checks a GET (or HEAD) in place of PUT, PATCH, DELETE or POST. Servers that send different CORS headers per method can answer your real request differently; check it in the network panel.
  • Requests carry no cookies and come from a data centre with MySmartCoPilotBot’s user agent, so a server that changes its answer for signed-in users, browsers or regions (or blocks bots) may answer you differently.
  • Only public http:// and https:// URLs on the standard ports can be tested live; for localhost, private networks and other ports, paste the headers.
  • Browser features around CORS are not simulated: the HTTP cache, service workers, extensions, Chrome’s prompt for requests to local networks and mixed-content blocking.
  • When a preflighted request is redirected, the browser sends a second preflight to the new URL; the live test does not send that one, so it reports the result as open and suggests testing the final URL directly.
  • The raw view leaves out the Server header and a few headers added on the way to MySmartCoPilot’s server (a request ID, a cache status, connection details), because they would not show your server’s values. None of them affects CORS.
  • Console wording follows current Chrome and may change in later versions.

Privacy

In “Live URL” mode the URL, the Origin, the method and the names of the headers that need permission go to MySmartCoPilot’s server, which sends the requests and returns only status lines and response headers; nothing is stored, and the log keeps only the host name, status and time. Header values, cookies and everything pasted in “Paste headers” mode stay in your browser.

Frequently asked questions

Why does my request work in curl or Postman but not in the browser?

CORS is enforced by browsers only. curl and Postman ignore it; the browser sends the request too, but hides the answer from your page unless the CORS headers allow it — and for preflighted requests it does not send the request at all when the preflight fails.

Do I need a preflight for JSON?

Yes, if you set Content-Type: application/json: only application/x-www-form-urlencoded, multipart/form-data and text/plain are safelisted. The server must then answer OPTIONS and list Content-Type in Access-Control-Allow-Headers.

Is Access-Control-Allow-Origin: * safe?

For public data that any site may read, yes: * never works with cookies or HTTP authentication. Reflecting every request’s Origin together with Access-Control-Allow-Credentials: true is the dangerous setup, because then any website can read your signed-in visitors’ data — the trust check flags it.

How do I allow several origins?

The header takes one origin (or *), not a list. Check the request’s Origin against your allowed list on the server, send back the one that matched, and add Vary: Origin.

Why is my Origin "null"?

Browsers send Origin: null from sandboxed iframes, file:// pages and data: URLs, and after a redirect to another origin during a CORS request. Avoid allowing null: any site can create a document with that origin.

Can I test an API on localhost?

Not live — MySmartCoPilot’s server can reach only public websites. Choose Paste headers, then copy the response headers of the OPTIONS request and of the request itself from your browser’s network panel; they are analysed in your browser.

My server sends the right headers but the browser still blocks the call. Why?

Common causes: the headers are missing on the redirect or error response (the check runs on every response), a proxy or CDN adds a second Access-Control-Allow-Origin, an old cached response without Vary: Origin, or authentication rejecting the OPTIONS request, which never carries credentials.

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.