BEGINNERAWS-CLIS3

Generate a Presigned URL for an S3 Object

Use aws s3 presign to generate a time-limited download URL for a private S3 object. Share files without making the bucket public.

Published Apr 28, 2026
aws-clis3presigned-urlsecurityshell

aws s3 presign generates a temporary URL for a private S3 object that anyone can use to download the file until the URL expires. This is the standard way to share private files (logs, exports, backups) without making the bucket public or fiddling with bucket policies.

Tested on AWS CLI v2.17.

When to Use This

  • Sharing a private file with a customer or teammate temporarily
  • Generating download links for user-specific exports
  • Letting a third-party service fetch a file without IAM access
  • Embedding a download button in an email or Slack message

Don't use this when the file is already public (use the public URL directly) or when you need true authentication on the download (use a signed cookie or backend proxy).

Code

# Default expiry (1 hour)
aws s3 presign s3://$BUCKET/$KEY
 
# Custom expiry — 24 hours
aws s3 presign s3://$BUCKET/$KEY --expires-in 86400
 
# Maximum allowed: 7 days
aws s3 presign s3://$BUCKET/$KEY --expires-in 604800
 
# With a specific profile
aws s3 presign s3://$BUCKET/$KEY --expires-in 3600 --profile prod

The output is a long HTTPS URL containing the signature, expiry, and credentials reference. Send it to whoever needs the file.

Usage

A shell function I keep in .zshrc for ad-hoc sharing:

# Usage: s3share my-bucket path/to/file.zip [hours]
s3share() {
  local bucket="$1"
  local key="$2"
  local hours="${3:-1}"
  local seconds=$((hours * 3600))
 
  aws s3 presign "s3://$bucket/$key" --expires-in "$seconds"
}
$ s3share customer-exports invoices/2026-q1.pdf 24
https://customer-exports.s3.amazonaws.com/invoices/2026-q1.pdf?...&X-Amz-Expires=86400&X-Amz-Signature=...

Pipe it to pbcopy (macOS) or xclip (Linux) to copy directly to clipboard.

Caveats

  • The URL contains an embedded signature. Anyone with the link gets the file. Treat presigned URLs as secrets — don't paste them in public Slack channels or commit them to git.
  • Expiry is enforced server-side. S3 returns 403 the moment the URL expires. There's no warning or grace period.
  • Maximum 7 days for IAM user credentials. For temporary credentials (assumed roles, instance profiles), the URL can never outlive the session token, even if you ask for 7 days. Common caveat when running this from EC2.
  • The URL is signed for the GET method by default. To presign a PUT for uploads, you need the SDK — aws s3 presign only signs downloads.
  • Forward slashes in keys must be unencoded. AWS CLI handles this correctly, but if you're constructing the URL by hand, don't URL-encode the slashes inside the key.

Frequently Asked Questions

What is an S3 presigned URL?

A presigned URL is a temporary URL that grants time-limited access to a private S3 object. The URL contains the request signature, so anyone holding the link can download the object until the URL expires. No bucket policy or IAM change required.

How long can a presigned URL stay valid?

Maximum 7 days (604800 seconds) when generated with IAM user credentials. For credentials from sts:AssumeRole or instance profiles, the URL can only stay valid as long as the underlying session token. The default expiry is 1 hour (3600 seconds).

X (Twitter)LinkedIn