Skip to content
TaeyoungKim.dev

S3 object URL AccessDenied: Why a console download works but a browser gets 403

SecurityWritten 4 min readTaeyoungKim
LinkedInX

You upload a file to S3 and download it from the AWS console without trouble. Then you paste its object URL into a new browser window and get AccessDenied. The object has not changed. The identity making the request has changed.

What changes between a console download and an object URL?

The console makes the download request using the permissions of your signed-in AWS user or role. A plain object URL opened by someone else, or in a browser without suitable AWS credentials, does not carry those console permissions. The URL identifies the object; it is not a grant to read it.

The diagram contrasts two requests for the same private object. Anonymous access through the plain URL fails, while a valid, unexpired GET presigned URL can authorize a download within the signer's permissions. Signing a URL does not make the object public.

Suppose reports/summary.pdf is in a private bucket. Even if the address is correct, an anonymous request without s3:GetObject permission cannot read it. AWS explains how S3 evaluates access, including when an unauthorized request receives 403 AccessDenied.

Request for the same objectPermissions usedPossible result
Download in the AWS consolePermissions of the signed-in user or roleDownload succeeds
Open a plain object URL anonymouslyNo anonymous read grant for a private object403 AccessDenied
Open a valid GET presigned URLPermissions of the principal that signed the URLDownload succeeds while the URL is valid

This comparison assumes a private object and a console user who can read it. A real 403 can also involve an explicit deny, public access settings, another policy, or a request for the wrong object. One error message alone does not prove which condition caused it.

Should you make the bucket public to share a private file?

No. To share one private object temporarily, a principal allowed to read it can generate a GET presigned URL. The recipient can then make that specific request without signing in to AWS. AWS's presigned URL documentation describes the signer's permissions and expiration limits.

Treat a presigned URL as a temporary bearer credential: anyone who obtains the complete URL may use it until it becomes invalid. Limit it to the needed object and a short lifetime. Avoid putting the complete URL in chat archives, logs, or analytics. If it was signed with temporary credentials, it can stop working when those credentials expire, even before the URL's requested expiration.

A file that everyone should always read is a different use case and needs a deliberately designed public delivery path. Disabling a bucket's public access protections just to fix one failed private download grants far more access than that task requires.

What should you check when you see AccessDenied?

  1. Is it the same object? Compare the bucket and full object key used by the console and URL. A slash is part of an S3 key.
  2. Who is making the request? Distinguish an authenticated console request from an anonymous request to a plain URL. Console success does not establish public read access.
  3. What kind of sharing is needed? For a temporary private download, consider a GET presigned URL. For a permanent public asset, design a separate public delivery path.
  4. Does the presigned URL fail too? Check the signer's read permission, URL expiration, and credential lifetime. Do not paste the full signature or token into a support ticket or log.

This is a comparison of request identities and permissions, not a report of a live bucket test. Bucket policies, public access settings, and encryption requirements may require additional checks.

Key takeaways

A successful S3 console download does not mean the plain object URL is public. Identify the principal making each request first. For a temporary private download, use a narrowly scoped, valid GET presigned URL instead of opening up the entire bucket.

Author

TaeyoungKim

Connecting technical foundations with implementation, verification, and production decisions.

#Amazon S3#AccessDenied#Object URL#Presigned URL#S3 permissions

Read next