What is a Presigned URL?

A presigned URL grants time-limited authorization for one specific storage operation, such as downloading or uploading a single object, without giving the recipient the signer’s secret credentials. Its signature fixes the operation, the object, and the expiry.

Application back end signs one request with its storage credentials
Storage service checks the signature and expiry, then serves or accepts the object
The application signs the request; the client then talks to the storage service directly.

How Presigned URLs work

A presigning service computes a signature over a storage request, using credentials it holds, and places the resulting authorization material in the URL’s query string. The storage service calculates the signature again when the URL is used and checks the method, the object, the signed headers, and the expiry, so the secret never has to reach the browser or downloader. The request runs with the authority of whoever signed it: Amazon S3 states that a presigned URL uses the credentials of the principal that generated it and is limited by that principal’s permissions. Amazon S3 calls these presigned URLs, Google Cloud Storage calls them signed URLs, and the Azure Storage counterpart is the shared access signature (SAS). The storage-specific details in this entry come from those three services’ documentation; for an S3-compatible service from another provider, check that provider’s own documentation. A CDN signed URL is a different mechanism: the CDN checks it against keys configured on the CDN, and the storage service is not involved in that check. In a delivery architecture, a presigned URL creates a direct, temporary path between a client and object storage while the application decides who receives one.

Key facts

  1. Who can use a presigned URL? Anyone who holds the complete URL, until it stops being valid. AWS describes presigned URLs as bearer tokens, and Google states that anyone in possession of a signed URL can use it while it is active, with or without an account. An S3 presigned URL can be used repeatedly up to its expiration. One way to end access earlier is to invalidate what signed the URL, which ends every URL signed with it: an S3 URL stops working when the signing credential is revoked, deleted, or deactivated, and a Google signed URL when the signing key is rotated. Other controls depend on the service. An S3 presigned URL is limited by its signer’s permissions, and AWS lists a bucket policy that explicitly denies access to the object among the causes of a 403 Forbidden response to a presigned URL, so such a deny stops requests within the policy’s scope without invalidating the credential. Azure recommends attaching a service SAS to a stored access policy so that it can be revoked without regenerating the account keys.
  2. Why would a presigned URL stop working before its stated expiry? Because it is valid only while the credentials that signed it are. AWS documents that an S3 URL signed with temporary credentials, such as an assumed role or an instance or container role, expires when those credentials do, even if a later expiration was requested, and requests then fail with ExpiredToken. Check the lifetime of the signing credentials before promising a link lifetime: AWS lets the maximum session duration of an IAM role assumed through its console, CLI, or API be set between 1 and 12 hours (1 hour unless a value is set) and describes instance and container role credentials as typically lasting up to about 6 hours, whereas an IAM user’s credentials can sign an S3 URL valid for up to 7 days with Signature Version 4. AWS’s remedies are to refresh the credentials and generate a new URL or, where appropriate, to sign with longer-lived credentials. S3 checks expiry when a request begins: a download that started before the deadline continues, but a request that restarts after the deadline fails.
  3. Why does an unexpired URL fail with a signature error? The request no longer matches what was signed. For S3, the HTTP method, the signed headers, and the query string must match exactly between generating the URL and using it. An S3 URL signed with Signature Version 4 lists its signed headers in X-Amz-SignedHeaders, and AWS requires the host header and any x-amz-* headers sent with the request to be among them. AWS lists a content type that differs from the one given at signing among the causes of SignatureDoesNotMatch, together with a modified URL, the wrong region, clock drift on the signing machine, and proxies that change headers or query strings. Google’s signed URLs name the headers a request must include in X-Goog-SignedHeaders.
  4. Why does a valid presigned URL fail from browser JavaScript? Storage authorization and CORS are separate checks. The bucket’s CORS configuration must allow the page’s origin, the HTTP method, and the request headers; Amazon S3 notes that ACLs and policies continue to apply when CORS is enabled. When the configuration does not allow a request, the browser stops at a failed preflight before sending the actual request or, for a request that needs no preflight (which can be the case for a POST with a form content type), sends it and withholds the response from the script, so a CORS error alone does not show that nothing was uploaded. Because CORS restricts cross-origin requests made by scripts in a browser, the same URL can succeed from a server-side client and fail from a web page.
  5. Does a presigned upload URL limit what gets uploaded? Only what was signed. An S3 presigned URL for an upload is created from a bucket, an object key, an HTTP method, and an expiration, and uploading to a key that already exists replaces the object. Azure warns that a client with write access may upload a very large blob (its example is 200 GB) and recommends validating data after it is written and before it is used. When the storage service must enforce a size limit, form-based POST uploads are the documented tool: the signed policy document accepts a content-length-range condition in Google Cloud Storage and in Amazon S3, and the AWS SDK for Python creates such a signed form with generate_presigned_post. The storage service’s own ceiling for one request still applies: an upload through an S3 presigned URL is a PUT, Amazon S3 documents a maximum of 5 GB for a single PUT, and larger objects go through multipart upload, in which the object is sent in parts. Amazon S3’s POST Object reference states no size ceiling for a single POST, so test a form-based upload with your largest expected file before relying on it.

When Presigned URLs matter

Issue one for direct browser uploads or private downloads when traffic should bypass the application server. Excessive validity, permissive operations, or URL leakage can expose the referenced object until expiration.

How Transloadit helps with Presigned URLs

Transloadit can return presigned download URLs for files it exports to Amazon S3. Setting sign_urls_for on the /s3/store Robot adds signed_url and signed_ssl_url to the result, with the parameter’s value as the expiry time in seconds. The URLs are signed with the AWS credentials you give the Robot, so the documentation requires that identity to hold read permission for the objects in addition to the write permission used for the upload.

A URL returned by /s3/store does not make a private object public, but the Robot’s acl parameter defaults to public-read. For a private bucket, the documentation says to set acl to bucket-default, supply no ACL or grant headers, and keep S3 Block Public Access enabled. With temporary AWS credentials, the Robot does not refresh them, and AWS documents that a presigned URL expires with the credentials that signed it, so compare their lifetime with the value of sign_urls_for. Transloadit’s Signature Authentication and signed Smart CDN URLs are separate mechanisms that use your Transloadit Auth Secret, not your storage credentials.

Explore Transloadit’s delivery capabilities

Sources

Turn media knowledge into a working pipeline

Connect uploads, processing, AI, storage, and delivery through one declarative API — with the encoding stack, scaling, and format churn handled for you.

Try Transloadit for free