That 403 ERROR: The request could not be satisfied. Bad request. message is vague enough to make you want to throw your laptop. I've been there — it happened during a demo to a VP once. Not fun.
Good news: this error has a limited set of causes. I'll walk you through a flow that starts with the 30-second fix, moves to the 5-minute check, and ends with the 15-minute deep dive. Stop when your issue's gone.
Step 1: The 30-Second Fix — Clear CloudFront Cache
Sometimes the error is stale edge content colliding with a new origin response. CloudFront caches error responses too, so a previous 403 can stick around for your entire TTL.
Here's the quick test: request the file with a query string that bypasses the cache.
curl -I https://d123.cloudfront.net/image.jpg?nocache=12345If that returns 200, you've got a stale cache issue. Fix it by invalidating:
- Open CloudFront console.
- Select your distribution.
- Go to Invalidations → Create Invalidation.
- Enter
/*and hit Invalidate.
That takes about 2 minutes to propagate. If the error disappears, you're done. But if it persists, you've ruled out cache — move on.
Step 2: The 5-Minute Fix — Check Origin Settings
When the cache isn't the culprit, the origin is rejecting the request. The most common scenario I see is an S3 bucket without proper CloudFront access.
Check S3 Bucket Policy
If your origin is S3, make sure you're using an Origin Access Identity (OAI) or Origin Access Control (OAC). Without it, CloudFront can't read private objects.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EABCDEF123"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket/*"
}
]
}Replace the OAI ARN with yours. If you don't have an OAI, create one in the origin settings and update the bucket policy.
Check Custom Origin Headers
If your origin is an ALB or EC2, CloudFront might be sending a Host header that the origin rejects. Try setting Origin Protocol Policy to match your origin (HTTP or HTTPS) and add a custom header like X-Origin-Secret to bypass security layers.
Check Allowed HTTP Methods
Sometimes the request method (POST, PUT) isn't in the distribution's allowed list. Go to Behaviors → edit → Allowed HTTP Methods. If you're uploading, you need POST, PUT, PATCH — not just GET.
Step 3: The 15-Minute Fix — Signed URLs and Advanced Headers
If steps 1 and 2 didn't solve it, you're likely dealing with signed URLs or custom headers gone wrong.
Signed URL Expiry or Policy Mismatch
This error frequently appears when a signed URL's policy includes conditions that don't match the actual request. For example, you signed for https://d123.cloudfront.net/video.mp4 but the request hits https://d123.cloudfront.net/video.mp4?token=abc. Check these:
- Expiration time — are you using UTC?
- IP range — if you signed for a specific IP, test from that IP.
- Path pattern — must exactly match the URL (including query strings if you used custom policy).
Create a test signed URL with the AWS CLI to verify:
aws cloudfront sign --url https://d123.cloudfront.net/file.zip --key-pair-id KXXXXX --private-key-file-path private.pem --date-less-than 2025-01-01Custom Headers in Origin Response
Some security tools (like WAF) drop requests when a custom header is missing. If you added a header like X-Forwarded-Host in CloudFront behaviors, make sure it's spelled correctly and matches your origin's expectation.
Check WAF Rules
If you have AWS WAF attached, a rule might be blocking the request. Go to WAF console → your web ACL → Logs. Look for a match. I once spent an hour only to find a rate-based rule blocking our dev IP.
What If None of These Work?
If you've gone through all three steps and still see the error, grab the full response body and headers:
curl -v https://d123.cloudfront.net/path 2>&1 | grep -i "x-amz"Look for x-amz-error-code or x-cache headers. That will tell you if the error comes from CloudFront or the origin. Then open a support case with those details — they'll appreciate the specifics.
One last tip: keep a checklist. This error is a symptom, not a disease. Once you've fixed it once, you'll spot the pattern instantly next time.