Cross-Origin requests fetch request to another web-site probably fails origin  – a domain/port/protocol Cross-origin requests  are sent to another domain (even a subdomain) or protocol or port Cross-origin requests are allowed, but with explicit allowance by the server, expressed in special headers that policy is called  CORS :  C ross- O rigin  R esource  S haring CORS exists to protect the internet from  hackers There are two types of cross-origin requests: safe requests & all others Safe requests A request is safe if it satisfies two conditions... has one of methods: GET or POST or HEAD allowed custom headers:  Accept ,  Accept-Language ,  Content-Language ,  Content-Type  with the value  application/x-www-form-urlencoded ,  multipart/form-data  or  text/plain 'safe' requests are sent right away, with the Origin header For requests w/o credentials (not sent by default), the server sets:  Access-Control-Allow-Origin  to  *  or same value as  Origin For requests with credentials, the server should set:  Access-Control-Allow-Origin  to same value as  Origin  and  Access-Control-Allow-Credentials  to  true JS automatically get access to response headers   Cache-Control ,  Content-Language ,  Content-Type ,  Expires ,  Last-Modified  or  Pragma Additional headers should be listed by server in  Access-Control-Expose-Headers  header Safe request can be made with a  <form>  or a  <script> , w/o any special methods CORS for safe requests If a request is cross-origin, the browser always adds the  Origin  header Origin: https://javascript.info  for HTTP-request Access-Control-Allow-Origin: *  for HTTP-response Response headers For cross-origin request, by default JS may access “safe” response headers Cache-Control ,  Content-Language ,  Content-Type ,  Expires ,  Last-Modified ,  Pragma There’s no  Content-Length  header in the list Additional permission is required to access that header to track the percentage of progress To grant JavaScript access to any other response header, the server must send the  Access-Control-Expose-Headers  header It contains a comma-separated list of unsafe header names that should be made accessible Bellow script is allowed to read the  Content-Length  and  API-Key  headers of the response 
      200 OK
      Content-Type:text/html; charset=UTF-8
      Content-Length: 12345
      API-Key: 2c9de507f2c54aa1
      Access-Control-Allow-Origin: https://javascript.info
      Access-Control-Expose-Headers: Content-Length,API-Key
       Unsafe requests for “unsafe” requests browser firstly sends “preflight” request, to ask for permission Preflight request occurs “behind the scenes”, it’s invisible to JavaScript JS only gets the response to the main request or an error if there’s no server permission A preflight request uses the method 'OPTIONS', no body and two headers: Access-Control-Request-Method  method of the unsafe request Access-Control-Request-Headers  provides a comma-separated list of its unsafe HTTP-headers If the server agrees to serve the requests, it should respond with empty body, status 200 and headers... Access-Control-Allow-Origin  must be either  *  or the requesting origin to allow it Access-Control-Allow-Methods  must have the allowed method Access-Control-Allow-Headers  must have a list of allowed headers Access-Control-Max-Age  header may specify a number of seconds to cache the permissions. So the browser won’t have to send a preflight for subsequent requests that satisfy given permissions. Take a look at step-by-step example  https://javascript.info/fetch-crossorigin Credentials A cross-origin request from JavaScript by default does not bring credentials (cookies or HTTP authentication) but HTTP requests have them to include credentials in fetch and send cookies need to use  credentials: "include"  property option If the server agrees to accept the request with credentials, it should add... header  Access-Control-Allow-Credentials: true  to the response, in addition to  Access-Control-Allow-Origin Access-Control-Allow-Origin  is prohibited from using a star  *  for requests with credentials, must provide the exact origin there 
      fetch('http://another.com', { credentials: "include" })
       Fetch page content  
      function FetchComponent() {
        return (
          <div>
            <button onClick={fetchPage}>Fetch this page content and put into console</button>
          </div>
        )
      }
      async function fetchPage() {
        const response = await fetch('/posts/fetch') // resolves with response headers
        const result = await response.text()
        console.log(result)
      }