TL;DR: AWS knows who you are but says no. Your IAM user or role lacks permission for the S3 action, or a bucket policy explicitly denies it. Grant the permission in IAM and retry.

```text
boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden
[?xml version="1.0" encoding="UTF-8"?]
[Error][Code]AccessDenied[/Code][Message]Access Denied[/Message][/Error]
```

## Fix it

1. Identify the IAM identity behind the key (IAM console, access key id). Expected: you know the user or role.
2. Attach a policy allowing the action, e.g. s3:GetObject / s3:ListBucket on the bucket ARN. Expected: policy attached.
3. Check the bucket policy for explicit denies; an explicit deny beats any allow. Expected: no conflicting deny.
4. Retry the S3 call. Expected: 200.

## When this applies
- S3ResponseError 403 with AccessDenied on S3 calls.

## When it doesn't
- InvalidAccessKeyId in the XML: the key itself is wrong; fix credentials.
- SignatureDoesNotMatch: the secret is wrong.

## Compatibility
- boto 2.x (boto3 surfaces the same as ClientError 403).

## Why it happens
S3 evaluates IAM policies, bucket policies, and ACLs together. Valid credentials with no allow, or any explicit deny, produce 403.

## Edge cases
- KMS-encrypted objects need kms:Decrypt too, not just S3 permissions.
- New buckets in another region: check the endpoint boto uses matches the bucket region.
