Skip to main content

Pre-signed URLs

A pre-signed URL embeds a short-lived signature in a URL, granting the bearer permission to perform exactly one S3 operation on exactly one object. Use them when you need to:

  • Let a user download a private object via a normal browser link.
  • Let a browser upload directly to Filebase without your access key ever touching the client.
  • Share a temporary download link with a third party.

The pre-signed URL is generated client-side using your access key — Filebase doesn't see it until the recipient uses it.

How they work

  1. You decide which operation (GET, PUT, etc.) and which object.
  2. You ask the SDK to compute a SigV4 signature for that exact request, with an expiration time.
  3. The SDK encodes the signature, your access key ID, the date, and the expiry into URL query parameters.
  4. The result is a normal HTTPS URL anyone can use until the signature expires.

The recipient doesn't need an access key. They don't need any S3 client. They just need an HTTP client.

Generate a download URL

AWS CLI

aws --endpoint https://s3.filebase.io s3 presign s3://my-bucket/private.pdf

By default the URL is valid for 1 hour. Override with --expires-in <seconds>:

aws --endpoint https://s3.filebase.io s3 presign s3://my-bucket/private.pdf --expires-in 86400

AWS SDK for JavaScript v3

import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
endpoint: 'https://s3.filebase.io',
region: 'auto',
credentials: { accessKeyId: KEY, secretAccessKey: SECRET },
});

const url = await getSignedUrl(
s3,
new GetObjectCommand({ Bucket: 'my-bucket', Key: 'private.pdf' }),
{ expiresIn: 3600 },
);

console.log(url);

AWS SDK for Python (boto3)

url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': 'my-bucket', 'Key': 'private.pdf'},
ExpiresIn=3600,
)

AWS SDK for Go v2

presigner := s3.NewPresignClient(client)

req, err := presigner.PresignGetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("private.pdf"),
}, s3.WithPresignExpires(time.Hour))

fmt.Println(req.URL)

Generate an upload URL

A pre-signed PutObject URL lets a browser upload directly to Filebase, bypassing your application server entirely:

AWS SDK for JavaScript v3

import { PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const url = await getSignedUrl(
s3,
new PutObjectCommand({
Bucket: 'uploads',
Key: `user-${userId}/${filename}`,
ContentType: 'image/jpeg',
}),
{ expiresIn: 600 },
);

return url;

The browser then PUTs the file directly:

await fetch(presignedUrl, {
method: 'PUT',
body: fileBlob,
headers: { 'Content-Type': 'image/jpeg' },
});

See browser uploads for the full pattern, including handling CORS.

AWS SDK for Python (boto3)

url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': 'uploads',
'Key': f'user-{user_id}/{filename}',
'ContentType': 'image/jpeg',
},
ExpiresIn=600,
)

Expiration

Pre-signed URLs expire after the time you specify (ExpiresIn, in seconds). Until then they can be used as many times as the recipient wants — pre-signed URLs are not single-use. After expiry the URL returns 403 SignatureExpired from Filebase.

A reasonable default is 1 hour for downloads and 10 minutes for uploads, but tune for your use case.

Security considerations

  • A pre-signed URL is as powerful as the operation it signs. A pre-signed PutObject URL lets the bearer overwrite that exact key with arbitrary content. Generate URLs only for the specific operations and keys you intend.
  • Never log or persist pre-signed URLs in places where untrusted parties might see them. They effectively contain a short-lived bearer token.
  • For browser uploads, constrain the upload by including ContentType, Content-Length ranges, or a custom condition policy. The SDK enforces these constraints by signing them into the URL — the browser cannot deviate without invalidating the signature.

Pre-signed URLs and the CDN

Pre-signed URL responses are not aggressively cached at the Filebase CDN — the cache key includes the signature, so distinct URLs for the same object are cache misses. For high-traffic public distribution, prefer a public bucket over rotating pre-signed URLs.

What's next