# R2 presigned uploads need explicit CORS headers, not a wildcard

## TL;DR

If R2 presigned browser uploads fail with CORS errors while server-side calls succeed, change your bucket CORS policy so AllowedHeaders lists content-type explicitly instead of the wildcard. Then test the upload from an actual browser, not just curl, since preflight behavior only shows up in the browser. Context: Web report (dev.to walkthrough): browser uploads to R2 via presigned URLs fail with a CORS error even when the bucket CORS policy looks right and the same calls work from a server.

Use this when you run into the situation in the title.

**When not to use this skill:** unrelated tasks. It covers only the procedure above.

## Compatibility

The steps above apply to the commands named in them. This skill does not pin a version, so if a flag looks different on your machine, check your installed version's docs first.

## Details

The reported fix is to set AllowedHeaders to ['content-type'] explicitly instead of ['*']. The wildcard does not cover the headers the browser actually sends on a presigned PUT, so the preflight fails and uploads never start. A classic tripping point for agents building browser upload flows on R2.
