AWS SDK
S3 pre-signed URL
Amazon S3
cloud storage
cost analysis

Does generating a pre-signed URL to an S3 object using the AWS SDK cost anything?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Generating an S3 pre-signed URL is usually just local request signing done by your application. That act by itself does not create an S3 object request and typically does not incur an S3 charge. The costs come later if someone actually uses the URL to perform a GET, PUT, or other S3 operation, because those are real S3 requests and data transfers.

What a Pre-Signed URL Really Is

A pre-signed URL is a normal S3 request URL with authentication information embedded into the query string. The SDK signs a request locally using AWS credentials and an expiration time.

For example, in Python with boto3:

python
1import boto3
2
3s3 = boto3.client("s3")
4
5url = s3.generate_presigned_url(
6    "get_object",
7    Params={"Bucket": "my-bucket", "Key": "reports/daily.csv"},
8    ExpiresIn=3600,
9)
10
11print(url)

The signing step happens in your process. It does not need S3 to "reserve" the URL or create a special server-side resource.

What Does Cost Money

The important distinction is between generating the URL and using the URL.

Generating the URL:

  • usually no direct S3 request is made
  • usually no S3 charge is incurred just for signing

Using the URL:

  • performs the real S3 operation
  • incurs the same kind of charges that operation would normally incur

If the pre-signed URL is for downloading an object, the actual GET request may count toward:

  • S3 request charges
  • data transfer charges
  • any related networking charges for the environment involved

If the pre-signed URL is for uploading, the resulting PUT request is the billable operation, not the signing step.

Why the Confusion Happens

The confusion comes from the word "generate." It sounds like AWS might be creating a special asset on its side. In reality, the SDK is usually just calculating a signature locally and assembling a URL that S3 will later accept until it expires.

That makes the cost model simple:

  • signing is local work
  • S3 charges apply when S3 actually receives and handles a request

A Concrete Example

Suppose your backend generates 10,000 pre-signed download URLs overnight, but nobody clicks them. In that case, you did local signing work and perhaps some compute time on your own server, but you did not trigger 10,000 S3 object downloads.

Now suppose 2,000 users click those links and download a file. Those GET requests are the part that can generate S3-related cost.

The same logic applies to upload URLs:

python
1import boto3
2
3s3 = boto3.client("s3")
4
5url = s3.generate_presigned_url(
6    "put_object",
7    Params={"Bucket": "my-bucket", "Key": "uploads/photo.jpg"},
8    ExpiresIn=900,
9)
10
11print(url)

No upload charge exists until some client actually performs the PUT.

Secondary Costs You Might Still Care About

Even if S3 does not charge for URL generation, your overall system may still have non-S3 costs associated with the surrounding workflow:

  • compute time in Lambda, EC2, or containers
  • API Gateway or load balancer charges if your service creates URLs on demand
  • logging or monitoring costs

Those are infrastructure costs of your application, not S3 charges for the pre-signed URL itself.

There is also one edge consideration: if your code first calls AWS APIs to discover metadata or assume a role before signing, those surrounding actions may have their own cost or quota implications. But again, that is separate from the act of local pre-signing.

The Security Angle Is More Important Than the Cost Angle

In practice, developers should worry more about access scope and expiration than about URL-generation cost.

Good habits include:

  • keep expiration times short
  • scope the URL to one object and one operation
  • avoid over-permissive credentials
  • log who requested the URL if auditing matters

Pre-signed URLs are powerful because they let clients interact with S3 without exposing long-lived AWS credentials. The main engineering decision is security and control, not per-URL billing.

A Useful Mental Model

Think of pre-signing as writing a time-limited permission slip. Writing the slip is local work. S3 charges only when someone uses the slip to ask S3 to do something.

That mental model also helps explain why expired pre-signed URLs are free to ignore. If nobody successfully makes the request, there is no completed S3 operation behind it.

Common Pitfalls

  • Assuming URL generation itself is an S3 object request. It usually is not.
  • Ignoring the fact that the eventual GET or PUT through the pre-signed URL is still a normal billable S3 operation.
  • Mixing S3 cost with application infrastructure cost. Lambda or API Gateway charges may exist even when S3 charges do not.
  • Generating very long-lived URLs because the cost seems trivial. Security is usually the bigger concern.
  • Forgetting that a URL for put_object can still create storage cost if clients actually upload data.

Summary

  • Generating a pre-signed S3 URL is usually local signing and does not by itself incur S3 request charges.
  • The real S3 cost appears when someone uses the URL to perform a GET, PUT, or similar operation.
  • Request, storage, and data transfer costs still apply to the underlying S3 operation.
  • Your application may still incur compute or API costs while generating the URL.
  • The bigger design concern is usually security and expiration, not the act of generating the URL.

Course illustration
Course illustration

All Rights Reserved.