To create an AWS S3 bucket, sign in with an IAM identity that can create buckets, choose a globally unique name and an AWS Region, keep ACLs disabled, and leave Block Public Access enabled. New S3 buckets are private by default. Make objects public only when anyone on the internet is meant to read them, and grant only s3:GetObject through a narrow bucket policy.
Most users should keep S3 private and share files through an application, a time-limited presigned URL, or CloudFront. Never place passwords, backups, private keys, customer data, or other confidential files in a public bucket.
Private bucket, public objects or static website?
| Use case | Public access | Recommended setup |
|---|---|---|
| Backups, application data and private downloads | None | Keep Block Public Access enabled. Use IAM roles or presigned URLs. |
| A public image or download folder | Read-only for a specific object or prefix | Use a narrow bucket policy granting only s3:GetObject. |
| Public static website | Public delivery is required | Prefer a private S3 origin behind CloudFront with Origin Access Control and HTTPS. |
Turning on S3 static website hosting and making an object publicly readable are separate actions. The ordinary S3 object endpoint does not become a website merely because a bucket policy allows reads. AWS also notes that S3 website endpoints support HTTP, not HTTPS; CloudFront is the safer public-delivery option when HTTPS is required.
Prerequisites and required IAM permissions
- An AWS account and an IAM user or role. Do not use the AWS account root user for routine S3 administration.
s3:CreateBucketto create a standard private bucket with the default settings.s3:PutBucketPublicAccessBlockif an approved use case requires changing bucket-level Block Public Access.s3:PutBucketPolicyto add or change the bucket policy.s3:PutObjectto upload test files ands3:GetObjectto retrieve private files as an authenticated identity.- A current AWS CLI configured with a limited IAM identity if you will use the command-line steps.
AWS may require additional permissions when you enable features such as Object Lock, tags, versioning or non-default Object Ownership. Grant only the actions required for the task instead of broad s3:* access.
Create a private S3 bucket in the AWS Console
1. Open Amazon S3
Sign in to the AWS Management Console, open S3, and choose Create bucket.

2. Choose a globally unique name and Region
For a general-purpose bucket, the name must be unique within its AWS partition. Use lowercase letters, numbers and hyphens, avoid sensitive information, and consider adding a random suffix. AWS recommends avoiding periods unless they are specifically needed for an S3 website because periods complicate virtual-hosted HTTPS addressing.
Select the Region closest to the workload while considering latency, cost and data-residency requirements. You cannot change a bucket’s name or Region after creation; moving later means creating another bucket and copying the objects.

3. Keep Object Ownership set to ACLs disabled
Keep the default Bucket owner enforced setting. It disables ACLs and makes the bucket owner responsible for every object. IAM and bucket policies are normally easier to audit than separate object ACLs.

4. Keep Block Public Access enabled
Leave all four Block Public Access settings enabled when you create the bucket. These controls can override bucket policies and ACLs that would otherwise expose data. S3 applies the most restrictive effective setting across AWS Organizations, the account, access points and the bucket.
5. Review options and create the bucket
Review versioning, tags and default encryption for your workload, then choose Create bucket. Open the bucket and choose Upload to add a harmless test file. A private object URL should return AccessDenied to an unauthenticated visitor; that is the secure default.

Make selected S3 objects public safely
Continue only if the files are intentionally public. Use a separate bucket or a dedicated prefix such as public/ so private and public data cannot be mixed accidentally.
1. Change bucket-level Block Public Access
Open the bucket, choose Permissions, find Block public access (bucket settings), and choose Edit. Change only the controls necessary for the approved public bucket policy, acknowledge the warning, and save. A stricter organisation-level or account-level setting can still block the policy.

2. Add a read-only bucket policy
Under Bucket policy, choose Edit. Replace YOUR-BUCKET-NAME with the exact name. This example makes only the public/ prefix readable:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForPublicPrefix",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/public/*"
}
]
}
The policy permits downloads only. It does not grant bucket listing, upload, overwrite or deletion. Never grant anonymous s3:PutObject, s3:DeleteObject, s3:ListBucket or wildcard s3:* access.
3. Upload only intended public files
Place public files under the permitted prefix. Everything outside it remains private unless another identity policy, bucket policy, access point or ACL grants access.
How S3 static website hosting is different
Static website hosting adds a website endpoint and lets you configure an index document such as index.html and an error document. To enable it, open the bucket’s Properties tab, find Static website hosting, choose Edit, enable the feature and enter the document names.
A directly public S3 website also needs public-read permission for the website files and the required Block Public Access changes. AWS recommends a CloudFront distribution with Origin Access Control when you want a public website while keeping the S3 bucket private. CloudFront also provides HTTPS, whereas an S3 website endpoint is HTTP-only.
Create an S3 bucket with the AWS CLI
Confirm the identity first so you do not create resources in the wrong account:
aws sts get-caller-identity
For a Region such as Mumbai (ap-south-1), include its location constraint:
aws s3api create-bucket \
--bucket YOUR-GLOBALLY-UNIQUE-BUCKET-NAME \
--region ap-south-1 \
--create-bucket-configuration LocationConstraint=ap-south-1
For us-east-1, omit --create-bucket-configuration:
aws s3api create-bucket \
--bucket YOUR-GLOBALLY-UNIQUE-BUCKET-NAME \
--region us-east-1
Check its Region, Object Ownership and public-access protection:
aws s3api get-bucket-location --bucket YOUR-BUCKET-NAME
aws s3api get-bucket-ownership-controls --bucket YOUR-BUCKET-NAME
aws s3api get-public-access-block --bucket YOUR-BUCKET-NAME
Do not paste long-term AWS access keys into scripts or articles. Prefer IAM roles, AWS IAM Identity Center, or another supported short-lived credential method.
Verify whether an object is public
Open an uploaded object and choose Copy URL. Test the URL in a private browser window where you are not signed in to AWS. You can also send an unauthenticated request:
curl -I "https://YOUR-BUCKET-NAME.s3.REGION.amazonaws.com/public/test-file.txt"
200 OKmeans the object is publicly readable.403 AccessDeniedmeans public read is not effective or the object is protected.301 PermanentRedirectusually means the request used the wrong regional endpoint.404 Not Foundmeans the key or path is wrong, although endpoint and permission behaviour can affect the visible response.

Troubleshoot S3 public-access problems
AccessDenied after adding the policy
- Confirm the bucket name, object key and capitalization are exact.
- Confirm the policy resource points to objects and ends with the intended path, such as
/public/*. - Check Block Public Access at the organisation, account, access-point and bucket levels.
- Check service control policies, permissions boundaries and explicit deny statements.
- Do not expect an anonymous visitor to decrypt an object protected by a private AWS KMS key.
The bucket policy will not save
Check that the JSON is valid, the ARN names the current bucket, and your identity has s3:PutBucketPolicy. If AWS reports that the policy conflicts with Block Public Access, review the active settings rather than disabling every protection without understanding the impact.
Object ownership or ACL errors
With Bucket owner enforced, ACL operations fail because ACLs are disabled. Use IAM and bucket policies. If another AWS account uploads objects, ensure the access design gives the bucket owner the expected control without reverting to public ACLs.
Wrong Region or redirect errors
Run aws s3api get-bucket-location and use the matching regional endpoint. Remember that the bucket Region cannot be changed after creation.
Make the bucket private again
Remove the public-read statement, enable all bucket-level Block Public Access settings, and retest the URL anonymously. Review CloudFront, access points, ACLs and other policies that may expose the same object separately. IAM Access Analyzer for S3 can help identify unintended public or cross-account access.
Frequently asked questions
Are new S3 buckets public by default?
No. New buckets and objects are private by default, Block Public Access is enabled, and Object Ownership defaults to Bucket owner enforced with ACLs disabled.
Can I make only one S3 object public?
Yes. With ACLs disabled, restrict the bucket policy resource to the exact object ARN. Use a presigned URL instead when access should be temporary or limited to selected people.
Does public read allow anonymous uploads?
No. The policy in this guide grants only s3:GetObject. Do not add public write permissions.
Official AWS references
- AWS: Creating a general purpose S3 bucket
- AWS: General purpose bucket naming rules
- AWS: Blocking public access to S3 storage
- AWS: Access control in Amazon S3
- AWS: Permissions for S3 website access
- AWS CLI: create-bucket command
If S3 stores database backups, keep them private and review our MySQL backup and restore guide. Administrators using S3-compatible object storage with collaboration platforms can also read the Nextcloud 34.0.3 maintenance update.
The safest S3 configuration is private by default, with narrow access added only for a documented requirement. Verify exposure from an unauthenticated session and review the policy whenever the bucket’s purpose changes.











Comments