CORS on Amazon S3
S3 uses the same CORS policy shape as Cloudflare R2 (the spec is shared).
This guide walks the AWS Console path; if you use aws s3api put-bucket-cors
or Terraform / CloudFormation, the JSON below works the same.
Apply the policy
Section titled “Apply the policy”-
Sign into the AWS Console and navigate to S3 → Buckets.
-
Click your bucket name, then the Permissions tab in the top navigation.
-
Scroll to “Cross-origin resource sharing (CORS)” and click Edit.
-
Paste the JSON below, replacing
https://studio.relyn.appwith your studio URL if you self-host:[{"AllowedOrigins": ["https://studio.relyn.app","http://localhost:5173"],"AllowedMethods": ["GET", "PUT", "HEAD", "POST", "DELETE"],"AllowedHeaders": ["*"],"ExposeHeaders": ["ETag"],"MaxAgeSeconds": 3600}] -
Save changes. AWS applies CORS within seconds.
-
Back in Relyn, open the bucket and click Diagnose. The yellow warning clears once the preflight confirms.
CLI alternative
Section titled “CLI alternative”aws s3api put-bucket-cors --bucket YOUR_BUCKET --cors-configuration '{ "CORSRules": [ { "AllowedOrigins": ["https://studio.relyn.app", "http://localhost:5173"], "AllowedMethods": ["GET", "PUT", "HEAD", "POST", "DELETE"], "AllowedHeaders": ["*"], "ExposeHeaders": ["ETag"], "MaxAgeSeconds": 3600 } ]}'The CLI shape wraps the same rules in a CORSRules array — content is identical.
Notes on the AWS dashboard
Section titled “Notes on the AWS dashboard”- Block Public Access doesn’t affect CORS. You can keep “Block all public access” enabled — the CORS preflight is unauthenticated by spec but reading objects still requires presigned URLs.
- If your bucket lives behind CloudFront with custom origin headers, CORS headers need to be passed through. That’s a CloudFront behaviour config separate from this.
Further reading
Section titled “Further reading”- AWS S3: Using CORS — official docs
- AWS CLI: put-bucket-cors