CORS origin * not being respected from fetch

Currently my app (ionic, running on localhost:8100) is doing a video pre-loading service, which goes ahead and runs a fetch on some video resources on the server to downloads and caches them.

fetch(url, {
method: ‘GET’,
headers: {
Accept: ‘video/mp4’,
‘Access-Control-Allow-Origin’: “*”,
“Access-Control-Allow-Methods”: “GET,HEAD,POST,OPTIONS”,
“Access-Control-Max-Age”: “86400”,
.then(res => {
return res.blob()})
.then(blob => {
let vidDataUrl = URL.createObjectURL(blob)

All working fine if I switch on development mode, but as soon as I switch it off, I get CORS errors

Access to fetch at ‘’ from origin ‘http://localhost:8100’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

Does anyone know if there is anything I can tweak to work around this?

Many thanks amicos! :slight_smile:


Thank you for reaching out to us. Have you tried ensuring that your server is configured to include the appropriate CORS headers in its responses? You may need to set the ‘Access-Control-Allow-Origin’ header to allow requests from your localhost:8100 origin. Also, you can try updating your fetch request to include the ‘mode’ option set to ‘cors’ explicitly. This should ensure that the request is made with CORS enabled, even when the response doesn’t include the necessary headers.

Please let us know if this helps.


Thank you Lili84

I have since inadvertently solved the problem. I’m still no exactly sure how, but a major culprit in the line-up is the google chrome inspector tool that is known to mis-report CORS error, hiding the actual network error from the developer.

Just for anyone else facing the same nervous-breakdown trauma, here are the parts of my codebase that are involved, and are currently working. I have now switched cloudflare back out of development mode and everything is awesome (thanks cloudflare).

Javascript (client fetch op)

 // Programatically download the slideshow data so that we 
  // can control the data flow and slide timer coordination better
  async getSlideshowSourceData(slideshowItem) : Promise<string> {
    slideshowItem.srcLoadedPercent = 0;
    return new Promise((resolve, reject) => {
      let url = environment.contentHost + slideshowItem.source.videoUrlXxs;

      fetch(url, {
        cache: 'no-store',
        method: 'GET',
        headers: {
          Accept: 'video/mp4',
          'Access-Control-Allow-Origin': "*",
          "Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
          "Access-Control-Max-Age": "86400",
      .then(res => {
        //console.log("res", res);
        return res.blob()
      .then(blob => {
        //console.log("blob", blob)
        let vidDataUrl = URL.createObjectURL(blob)
        // Force the videos to come down in the correct order (hopefully)
        // Nb - running too many concurrent fetches shows a false CORS ERROR on chrome dev tools (hides the real error)
        setTimeout(() => {
        }, 500)
      }, error => {

.Net Core 5 configuration (startup.cs)
Note that I have 2 use cors blocks. This has been a nightmare to configure. It works. I’m not touching it again!!!

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            if (env.IsDevelopment())
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApi v1"));
            var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
            Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();

            app.UseCors(x => x
             .SetIsOriginAllowed(origin => true));

            FileExtensionContentTypeProvider contentTypes = new FileExtensionContentTypeProvider();
            contentTypes.Mappings[".apk"] = "application/";
            app.UseStaticFiles(new StaticFileOptions
                ContentTypeProvider = contentTypes

            var fileExtensionProvider = new FileExtensionContentTypeProvider();
            fileExtensionProvider.Mappings[".webmanifest"] = "application/manifest+json";
            app.UseStaticFiles(new StaticFileOptions
                ContentTypeProvider = fileExtensionProvider,
                RequestPath = "/ng",
                FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot/ng"))

            string apkPath = Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot/apk"); // Your code goes here
            if (!System.IO.Directory.Exists(apkPath))

            var fileProvider = new PhysicalFileProvider(apkPath);
            var requestPath = "/apk";
            app.UseDirectoryBrowser(new DirectoryBrowserOptions { 
                FileProvider = fileProvider,
                RequestPath = requestPath


            app.UseCors(x => x
            .SetIsOriginAllowed(origin => true));


            app.UseEndpoints(endpoints =>
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");


                endpoints.MapFallbackToFile(@"/ng/{*path:nonfile}", @"ng/index.html");

.net web config
Note all the cors config is done in code. Adding more CORS stuff in the config causes duplicate header errors

<?xml version="1.0" encoding="utf-8"?>
  <location path="." inheritInChildApplications="false">
					<add name="Cross-Origin-Opener-Policy" value="same-origin" />
					<add name="Cross-Origin-Embedder-Policy" value="require-corp" />
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      <aspNetCore processPath="dotnet" arguments=".\Web.App.Core.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
          <requestLimits maxAllowedContentLength="2147483648" />
            <remove verb="OPTIONS" />
            <add verb="OPTIONS" allowed="true" />

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.