Configure S3 CORS for one web origin
📑 On this page
Part 33 of AWS from Zero. This lesson keeps the scope to one S3 behavior you can verify from the terminal.
What we are learning
CORS tells browsers which cross-origin requests may be made. It does not grant S3 permission; IAM, bucket policy, and presigned authorization still apply.
Before you run it
aws sts get-caller-identity
REGION="ap-south-1"
BUCKET="replace-with-your-private-demo-bucket"Use a private general purpose bucket that you own. Replace every placeholder before running a write or delete command.
The command
cat > cors.json <<'EOF'
{
"CORSRules": [{
"AllowedOrigins": ["https://app.example.com"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3000
}]
}
EOF
aws s3api put-bucket-cors \
--bucket "$BUCKET" \
--cors-configuration file://cors.jsonA successful configuration command may return no output. Treat inspection as a separate required step.
Inspect the result
aws s3api get-bucket-cors \
--bucket "$BUCKET" \
--output jsonS3 evaluates CORS rules in order and uses the first matching rule.
One tiny variation
aws s3api delete-bucket-cors --bucket "$BUCKET"
aws s3api get-bucket-cors --bucket "$BUCKET"Deleting the configuration should make the second command return NoSuchCORSConfiguration.
Common mistake
Do not use AllowedOrigins: ["*"] with broad write methods merely to silence a browser error. Match the real origin and only the methods your application needs.
Cleanup
aws s3api delete-bucket-cors --bucket "$BUCKET" 2>/dev/null || true
rm cors.jsonThe bucket remains private and the temporary CORS configuration is removed.
Next, we will learn Add tags to an S3 object.