AWS S3: Access Denied (403 Forbidden)
Educational use only. Content explains errors and defensive fixes for systems you own or are authorised to test. Do not use any technique here to access data, accounts, or networks without permission.
Root Cause
A 403 Forbidden error from Amazon S3 means your request reached the bucket, but AWS Identity and Access Management (IAM) evaluated your credentials and permissions and denied the action. This is notoriously difficult to debug because AWS returns the same generic 403 error for a multitude of reasons: the IAM user lacks `s3:GetObject` or `s3:PutObject` permissions, the Bucket Policy explicitly blocks the action, public access is blocked at the account level, the object is encrypted with a KMS key you don't have access to, or you simply mistyped the bucket name and are hitting someone else's private bucket.
Fix / Solution
Use the AWS IAM Policy Simulator to verify your user/role permissions. Check the S3 Bucket Policy to ensure it allows access from your specific IAM role. If the bucket is meant to be public for website hosting, verify that 'Block Public Access' is turned off and a public read policy is attached. Ensure your application is actually loading its AWS credentials (Access Key ID and Secret) correctly from environment variables.
Code Snippet
// ❌ AWS SDK throws AccessDeniedException
const s3 = new AWS.S3();
await s3.putObject({ Bucket: 'my-bucket', Key: 'file.txt', Body: 'data' }).promise();
// ✅ Required IAM Policy JSON for the executing role
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}