Why does my JavaScript code receive a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error, while Postman does not?

Asked 2023-09-20 20:18:35 View 204,101

Mod note: This question is about why XMLHttpRequest/fetch/etc. on the browser are subject to the Same Access Policy restrictions (you get errors mentioning CORB or CORS) while Postman is not. This question is not about how to fix a "No 'Access-Control-Allow-Origin'..." error. It's about why they happen.

Please stop posting:

  • CORS configurations for every language/framework under the sun. Instead find your relevant language/framework's question.
  • 3rd party services that allow a request to circumvent CORS
  • Command line options for turning off CORS for various browsers

I am trying to do authorization using JavaScript by connecting to the RESTful API built-in Flask. However, when I make the request, I get the following error:

XMLHttpRequest cannot load http://myApiUrl/login. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'null' is therefore not allowed access.

I know that the API or remote resource must set the header, but why did it work when I made the request via the Chrome extension Postman?

This is the request code:

$.ajax({
  type: 'POST',
  dataType: 'text',
  url: api,
  username: 'user',
  password: 'pass',
  crossDomain: true,
  xhrFields: {
    withCredentials: true,
  },
})
  .done(function (data) {
    console.log('done');
  })
  .fail(function (xhr, textStatus, errorThrown) {
    alert(xhr.responseText);
    alert(textStatus);
  });

Answers

If I understood it right you are doing an XMLHttpRequest to a different domain than your page is on. So the browser is blocking it as it usually allows a request in the same origin for security reasons. You need to do something different when you want to do a cross-domain request.

When you are using Postman they are not restricted by this policy. Quoted from Cross-Origin XMLHttpRequest:

Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.

Answered   2023-09-20 20:18:35

  • The browser is not blocking the request. The only browsers that outright block cross-origin ajax requests is IE7 or older. All browsers, other than IE7 and older, implement the CORS spec (IE8 & IE9 partially). All you need to do is opt-in to CORS requests on your API server by returning the proper headers based on the request. You should read up on CORS concepts at mzl.la/VOFrSz. Postman sends requests via XHR as well. If you are not seeing the same problem when using postman, this means that you are unknowingly not sending the same request via postman. - anyone
  • @MD.SahibBinMahboob Postman is NOT sending a request "from your java/python" code. It is sending the request directly from the browser. XHR in Chrome extensions does work a bit differently, especially when cross-origin requests are involved. - anyone
  • Found a detailed example on this post: stackoverflow.com/questions/66486610/… - anyone
  • Happens to us locally only when certain request param equal 10 rofl? Works in all other scenarios. what the heck? :D - anyone

WARNING: Using Access-Control-Allow-Origin: * can make your API/website vulnerable to cross-site request forgery (CSRF) attacks. Make certain you understand the risks before using this code.

It's very simple to solve if you are using PHP. Just add the following script in the beginning of your PHP page which handles the request:

<?php header('Access-Control-Allow-Origin: *'); ?>

If you are using Node-red you have to allow CORS in the node-red/settings.js file by un-commenting the following lines:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
  origin: "*",
  methods: "GET,PUT,POST,DELETE"
},

If you are using Flask same as the question; you have first to install flask-cors

pip install -U flask-cors

Then include the Flask cors package in your application.

from flask_cors import CORS

A simple application will look like:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

For more details, you can check the Flask documentation.

Answered   2023-09-20 20:18:35

  • You shouldn't turn off CORS because you don't know what its for. This leaves your users in a fundamentally unsafe state. - anyone
  • Even though it might not be secure, the question was not about security, but how to accomplish the task. This is one of the options that a developer has to choose from when dealing with cross-domain AJAX requests. It helped me resolve the issue, and for my application, I don't care where the data came from. I sanitize all the input with PHP on the destination domain, so, if someone wants to post some junk to it, let them try. The main point here is, cross-domain AJAX can be allowed from the destination domain. +1 for the answer. - anyone
  • @meagar Agreeing with you that we shouldn't turn of CORS but at times we need to test the application while developing it and for that, the easiest way is to turn of CORS and check if everything works fine. Many times frontend devs don't have access to the backend system where they can change things or they need to write a proxy for the same. The best way to add a chrome extension that turns off CORS for development purposes, as written in the answer which is deleted. - anyone
  • It should be much helpful if the answer (or the edit with the WARNING on top) would explain to whom is risky if using that header() script in php. The question here is about a foreign site where we have no control, and that only allows us to navigate and see it from a browser, while if we need to access the resources from our server instead it launches the CORS protection (to not let us make too much inquiries per second). Therefore, my question still stands, what dangers do we visitors have if using in OUR server that header() script ?? Did the editor confused the visitor (us) with the host? - anyone
  • @ShadyMohamedSherif so isn't true that there was a time, historically, when people were allowed to 'consume' a website exposed at an IP /through a certain port/ with any means (browsers, apps, whatever), and after abuses occurred the website owners started to limit to the browsers only any connection to their page? In other words, when people just requested slowly a webpage (on a browser). I mean, even a ddos cannot happen through a browser, to not speak here about other devious ways to inquiry a website content that probably exist - anyone

Because
$.ajax({type: "POST" - calls OPTIONS
$.post( - calls POST

Both are different. Postman calls "POST" properly, but when we call it, it will be "OPTIONS".

For C# web services - Web API

Please add the following code in your web.config file under the <system.webServer> tag. This will work:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Please make sure you are not doing any mistake in the Ajax call.

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

Note: If you are looking for downloading content from a third-party website then this will not help you. You can try the following code, but not JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

Answered   2023-09-20 20:18:35

Deep

In the below investigation as API, I use http://example.com instead of http://myApiUrl/login from your question, because this first one working. I assume that your page is on http://my-site.local:8088.

NOTE: The API and your page have different domains!

The reason why you see different results is that Postman:

  • set header Host=example.com (your API)
  • NOT set header Origin
  • Postman actually not use your website url at all (you only type your API address into Postman) - he only send request to API, so he assume that website has same address as API (browser not assume this)

This is similar to browsers' way of sending requests when the site and API has the same domain (browsers also set the header item Referer=http://my-site.local:8088, however I don't see it in Postman). When Origin header is not set, usually servers allow such requests by default.

Enter image description here

This is the standard way how Postman sends requests. But a browser sends requests differently when your site and API have different domains, and then CORS occurs and the browser automatically:

  • sets header Host=example.com (yours as API)
  • sets header Origin=http://my-site.local:8088 (your site)

(The header Referer has the same value as Origin). And now in Chrome's Console & Networks tab you will see:

Enter image description here

Enter image description here

When you have Host != Origin this is CORS, and when the server detects such a request, it usually blocks it by default.

Origin=null is set when you open HTML content from a local directory, and it sends a request. The same situation is when you send a request inside an <iframe>, like in the below snippet (but here the Host header is not set at all) - in general, everywhere the HTML specification says opaque origin, you can translate that to Origin=null. More information about this you can find here.

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

If you do not use a simple CORS request, usually the browser automatically also sends an OPTIONS request before sending the main request - more information is here. The snippet below shows it:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

You can change the configuration of your server to allow CORS requests.

Here is an example configuration which turns on CORS on nginx (nginx.conf file) - be very careful with setting always/"$http_origin" for nginx and "*" for Apache - this will unblock CORS from any domain (in production instead of stars use your concrete page adres which consume your api)

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Here is an example configuration which turns on CORS on Apache (.htaccess file)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

Answered   2023-09-20 20:18:35

  • Great great explained and easy to catch up! Thank u! - anyone
  • This answer clearly demonstrates what this comment describes: If you are not seeing the same problem when using postman, this means that you are unknowingly not sending the same request via postman. Well done! - anyone

Applying a CORS restriction is a security feature defined by a server and implemented by a browser.

The browser looks at the CORS policy of the server and respects it.

However, the Postman tool does not bother about the CORS policy of the server.

That is why the CORS error appears in the browser, but not in Postman.

Answered   2023-09-20 20:18:35

The error you get is due to the CORS standard, which sets some restrictions on how JavaScript can perform ajax requests.

The CORS standard is a client-side standard, implemented in the browser. So it is the browser which prevent the call from completing and generates the error message - not the server.

Postman does not implement the CORS restrictions, which is why you don't see the same error when making the same call from Postman.

Why doesn't Postman implement CORS? CORS defines the restrictions relative to the origin (URL domain) of the page which initiates the request. But in Postman the requests doesn't originate from a page with an URL so CORS does not apply.

Answered   2023-09-20 20:18:35

  • @MrJedi: The accepted answer does not explain why the request succeeds in Postman, which was the original question. - anyone
  • The servers originally were meant to send streams to clients (browser software programs) not to various desktop or server applications instead that could behave in twisted ways. A browser establishes a handshake protocol with the server, receives the confirmation in regard to the connection then the data stream resumes. There were (DDOS) situations where bot farms servers sent millions of inquiries and the host committed many resources (opened processes) to each of these stalled connections that eventually never occurred - thus blocking its ability to answer to other legit requests - anyone
  • @Eve: CORS is a client side measure implemented in the browser and therefore not something which can prevent DDOS attacks from bot farms. - anyone
  • this is actually the best explanation, and a 'aha moment' to realize that CORS is a browser standard! - anyone

Solution & Issue Origins

You are making a XMLHttpRequest to different domains, example:

  1. Domain one: some-domain.com
  2. Domain Two: some-different-domain.com

This difference in domain names triggers CORS (Cross-Origin Resource Sharing) policy called SOP (Same-Origin Policy) that enforces the use of same domains (hence Origin) in Ajax, XMLHttpRequest and other HTTP requests.

Why did it work when I made the request via the Chrome extension Postman?

A client (most Browsers and Development Tools) has a choice to enforce the Same-Origin Policy.

Most browsers enforce the policy of Same-Origin Policy to prevent issues related to CSRF (Cross-Site Request Forgery) attack.

Postman as a development tool chooses not to enforce SOP while some browsers enforce, this is why you can send requests via Postman that you cannot send with XMLHttpRequest via JS using the browser.

Answered   2023-09-20 20:18:35

For browser testing purposes:

Windows - Run:

chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security

The command above will disable chrome web security. So for example if you work on a local project and encounter CORS policy issue when trying to make a request, you can skip this type of error with the above command. Basically it will open a new chrome session.

Answered   2023-09-20 20:18:35

  • Could you please explain it ? - anyone
  • @ZebraCoder The command above will disable chrome web security. So for example if you work on a local project and encounter CORS policy issue when trying to make a request, you can skip this type of error with the above command. Basically it will open a new chrome session. - anyone
  • Can you add the information to the answer itself? Comments may be deleted at any time. (But *********************************** without ******************************* "Edit:", "Update:", or similar - the answer should appear as if it was written today) - anyone

You might also get this error if your gateway timeout is too short and the resource you are accessing takes longer to process than the timeout. This may be the case for complex database queries etc. Thus, the above error code can be disguishing this problem. Just check if the error code is 504 instead of 404 as in Kamil's answer or something else. If it is 504, then increasing the gateway timeout might fix the problem.

In my case the CORS error could be removed by disabling the same origin policy (CORS) in the Internet Explorer browser, see How to disable same origin policy Internet Explorer. After doing this, it was a pure 504 error in the log.

Answered   2023-09-20 20:18:35

  • If you gettimeout you doesn't get CORS error - anyone
  • Well, I did in trouble shooting a system and the CORS error threw me off, that it was just the timeout that was too short, which resulted in a closed connection. After increasing the timeout, the system performed perfectly. So yes the timeout caused a No 'Access-Control-Allow-Origin' error which got me into this thread in the first place. So this might be helpful to others having this thrown along with a 504. - anyone
  • It rather mean something wrong iscwith your app config. You shouldn't get this error on timeout - anyone
  • I also was getting a confusing CORS 504 error when nginx, in my case, timed out. Increasing timeout got the service back online without CORS errors. Thanks for the hint. - anyone

To resolve this issue, write this line of code in your doGet() or doPost() function whichever you are using in backend

response.setHeader("Access-Control-Allow-Origin", "*");

Instead of "*" you can type in the website or API URL endpoint which is accessing the website else it will be public.

Answered   2023-09-20 20:18:35

You can allow the CORS by adding below scripts in web.config file in server.

<system.webServer>
     <httpProtocol>
         <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Methods" value="*" />
            <add name="Access-Control-Allow-Headers" value="*" />
         </customHeaders>
     </httpProtocol>
</system.webServer>

Answered   2023-09-20 20:18:35

Your IP address is not whitelisted, so you are getting this error. Ask the backend staff to whitelist your IP address for the service you are accessing.

Access-Control-Allow-Headers

Answered   2023-09-20 20:18:35

For me I got this issue for different reason, the remote domain was added to origins the deployed app works perfectly except one end point I got this issue:

Origin https://mai-frontend.vercel.app is not allowed by Access-Control-Allow-Origin. Status code: 500

and

Fetch API cannot load https://sciigo.herokuapp.com/recommendations/recommendationsByUser/8f1bb29e-8ce6-4df2-b138-ffe53650dbab due to access control checks.

I discovered that my Heroku database table does not contains all the columns of my local table after updating Heroku database table everything worked well.

Answered   2023-09-20 20:18:35

If you have the backend built using Node.js (Express.js), try using npm i cors

....
const cors = require("cors");
.....

app.use(cors());
...

Answered   2023-09-20 20:18:35

  • This doesn't answer the question. - anyone

It works for me by applying this middleware in globally:

<?php

    namespace App\Http\Middleware;

    use Closure;

    class Cors {
       public function handle($request, Closure $next) {
           return $next($request)
                   ->header('Access-Control-Allow-Origin', '*')
                   ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
                   ->header('Access-Control-Allow-Headers', "Accept,authorization,Authorization, Content-Type");
       }
    }

Answered   2023-09-20 20:18:35

  • What do you mean by "applying this middleware in globally"? Can you elaborate? - anyone
  • How does this answer the question? The question is tagged with JavaScript, jQuery, and CORS. If it does, it ought to be explained. The class has the name "Cors", but how does that relate? What is the gist? - anyone