Back to Blog
9 min read
Web

S3 CORS Policy Generator: Create AWS Bucket CORS JSON for Browser Uploads

Generate AWS S3 CORS policies for browser uploads, public reads, signed downloads, and presigned URLs. Learn CORSRules, AllowedOrigins, AllowedMethods, AllowedHeaders, ExposeHeaders, MaxAgeSeconds, and put-bucket-cors.

By Spoold Editorial TeamReviewed for tool accuracy
Editorial Policy

Build an S3 CORS policy for frontend uploads and reads

Use Spoold's S3/R2 CORS Generator to create an AWS S3 bucket CORS policy for browser uploads, public reads, signed downloads, and presigned URL flows. The tool produces editable policy JSON, an AWS CLI file with CORSRules, and a preflight curl for testing.

What is an S3 CORS policy?

An S3 CORS policy is a bucket-level rule set that tells Amazon S3 which browser origins can access objects, which HTTP methods are allowed, which request headers can be sent, and which response headers JavaScript can read. It is separate from IAM, bucket policies, ACLs, and presigned URL authorization.

S3 console JSON vs AWS CLI JSON

The S3 console commonly shows the rules themselves. The AWS CLI put-bucket-cors command expects a wrapper object with CORSRules. This small difference is easy to miss, so the generator outputs both.

Rule list

[
  {
    "AllowedOrigins": ["https://app.example.com"],
    "AllowedMethods": ["GET", "PUT", "HEAD"],
    "AllowedHeaders": ["Content-Type"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]

AWS CLI file

{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://app.example.com"],
      "AllowedMethods": ["GET", "PUT", "HEAD"],
      "AllowedHeaders": ["Content-Type"],
      "ExposeHeaders": ["ETag"],
      "MaxAgeSeconds": 3600
    }
  ]
}

Recommended S3 CORS policies by use case

Use caseMethodsHeadersExpose
Public asset readGET, HEADUsually emptyContent-Length
Presigned PUT uploadPUT, HEADContent-Type, x-amz-*ETag
Presigned POST uploadPOST, HEADContent-Type, x-amz-*ETag
Signed downloadGET, HEADAuthorization if sentETag

Console, CLI, and infrastructure-as-code checks

S3 CORS can be edited from the AWS console, applied with aws s3api put-bucket-cors, or managed through infrastructure code. The rules are conceptually the same, but the surrounding JSON shape changes by tool. When a policy works in the console but fails from the CLI, check whether the file includes the CORSRules wrapper. When a policy is managed by Terraform, CloudFormation, CDK, or another deploy system, avoid manual console edits that will be overwritten on the next deployment.

A good generator should therefore give you more than one copy format. Use the rule list for review, the AWS CLI wrapper for command-line application, and the table output as a checklist before translating the policy into your infrastructure tool.

aws s3api put-bucket-cors \
  --bucket my-upload-bucket \
  --cors-configuration file://cors-aws-cli.json

aws s3api get-bucket-cors \
  --bucket my-upload-bucket

How to generate an S3 CORS policy

  1. Open the S3 CORS policy generator and select AWS S3.
  2. Pick a preset for public read, presigned upload, signed download, or assets.
  3. Add exact origins such as https://app.example.com and http://localhost:3000.
  4. Add all request headers your frontend sends.
  5. Copy the policy or download the AWS CLI JSON file.
  6. Apply it with aws s3api put-bucket-cors --bucket BUCKET --cors-configuration file://cors-aws-cli.json.

Common S3 CORS mistakes

  • Using the wrong wrapper: AWS CLI expects CORSRules, not only a bare array.
  • Forgetting localhost: your production origin does not cover local dev.
  • Allowing GET but uploading with PUT: the preflight method must be allowed.
  • Missing upload headers: every header in Access-Control-Request-Headers must be covered.
  • Not exposing ETag: uploads may succeed, but JavaScript cannot read ETag unless it is in ExposeHeaders.

How narrow should an S3 CORS policy be?

For production uploads, prefer exact origins such as https://app.example.com instead of *. Exact origins make it easier to reason about which frontend can send browser requests to the bucket. If you have separate admin, staging, and customer-facing apps, list each origin deliberately. If the app uses credentials or signed cookies, a wildcard origin is usually the wrong shape because the browser expects a specific origin response.

Headers should be narrow enough to review but broad enough to match the actual upload library. Many teams start with Content-Type and x-amz-*, then tighten the policy after inspecting real preflight traffic. Methods should follow the workflow: GET and HEAD for reads, PUT or POST for uploads, and no delete method unless your browser UI truly deletes objects directly.

If one bucket serves multiple apps, separate rules can make reviews easier. For example, a public marketing site may need only read access, while an authenticated dashboard needs upload access from a different origin. Keeping those workflows distinct prevents a convenience setting for one app from silently widening access for another.

Use the debugger for failed preflight requests

Paste your current S3 CORS policy into the S3/R2 CORS debugger, then enter the browser origin, method, request headers, and console error. The debugger shows whether the request fails because of origin, method, request headers, exposed response headers, or wildcard origin with credentials.

S3 CORS policy FAQ

Is CORS the same as a bucket policy?

No. A bucket policy decides who is authorized. CORS decides what the browser is allowed to send and read after the request is otherwise valid.

Why does the AWS CLI reject my CORS JSON?

The CLI expects a JSON object with CORSRules. A bare array may be useful for review, but it is not the file shape used by put-bucket-cors.

Can one S3 CORS rule cover uploads and downloads?

Yes, but separate rules can be easier to audit. Use one rule when the same app origin owns both workflows, and split rules when public reads and authenticated uploads have different origins.

Try It Now

Put this guide into practice with our free tools. No sign-up required.

Generate S3 CORS Policy
S3 CORS Policy Generator: Create AWS Bucket CORS JSON for Browser Uploads | Blog | Spoold