You’re building a web app and need to grab a ZIP or PNG straight from a GitHub release. You send a fetch() from the browser, but run into a CORS error. Let’s see why that happens and how you can fix it in two straightforward ways.

What’s the Problem?

1. Redirects break the pre-flight

The download URL GitHub gives you is just a 302 that bounces to an S3 blob. CORS pre-flights (OPTIONS requests) don’t follow redirects, so the browser stops right there.

curl -I https://github.com/OWNER/REPO/releases/download/TAG/file.zip
 # ... HTTP/2 302 Location: https://objects.githubusercontent.com/...

2. No CORS headers on the final asset

Even if you follow the redirect manually, the S3 file itself doesn’t send Access-Control-Allow-Origin, so the browser still refuses to hand over the bytes.

curl -I 'https://objects.githubusercontent.com/.../file.zip'
 # HTTP/2 200 (but no Access-Control-Allow-Origin)

Bottom line: GitHub’s release CDN isn’t set up for direct browser fetches.

Fixing GitHub Release CORS Errors

1. Relay Through Your Backend

Already have a server? Relay the request via your backend:

// Express example
app.get("/asset", async (req, res) => {
  const upstream = await fetch(
    "https://github.com/OWNER/REPO/releases/download/TAG/file.zip"
  );

  res.set("Content-Type", upstream.headers.get("content-type"));
  res.send(Buffer.from(await upstream.arrayBuffer()));
});

Your frontend now calls the relay endpoint, the server handles the redirect, and the browser never sees a CORS issue.

2. Use a CORS Proxy (No Backend Needed)

No server? Drop a CORS proxy in front of the GitHub URL, it follows the redirect and injects the right headers.

fetch(
  "https://proxy.corsfix.com/?https://github.com/OWNER/REPO/releases/download/TAG/file.zip"
).then((res) => res.blob());

Either route gives you a clean, CORS-friendly response in the browser.

Conclusion

GitHub release assets trigger CORS errors because the initial redirect breaks pre-flight checks and the final file lacks the needed headers. You can solve this by relaying the request through your own backend for full control or by inserting a CORS proxy for the quickest setup. Pick the approach that fits your stack and move on without CORS errors.

Need production-ready CORS proxy? Give Corsfix a try, it’s free to start and only upgrade when you go to production.