On this page

S3 Presigned URLs

Introduction

A presigned URL is a time-limited link that grants temporary access to a specific object in an S3-compatible storage bucket - credentials or bucket permissions required on the recipient's side.

Presigned URLs are useful when you need to:

  • Share a file for download without making your bucket public.
  • Allow someone to upload a file directly to your bucket without giving them permanent access.
  • Save a Qencode transcoding output directly to a specific storage object without including storage credentials in the transcoding task.
  • Grant access that automatically expires after a set period.

There are two main types of presigned URLs:

  • GET presigned URL - provides temporary access to download an object.
  • PUT presigned URL - provides temporary access to upload or replace an object.

Generating a GET Presigned URL (for downloading)

A GET presigned URL lets anyone with the link download a specific object from your bucket.

Option 1 — Using the s3cmd CLI

s3cmd \
  --access_key=<access_key> \
  --secret_key=<secret_key> \
  --host=https://<endpoint_host> \
  --host-bucket=https://<bucket_name>.<endpoint_host> \
  signurl s3://<bucket_name>/<object_key> <expiration_seconds>

Replace the placeholders with your actual values:

PlaceholderDescription
<access_key>Your S3 access key
<secret_key>Your S3 secret key
<endpoint_host>Your S3 endpoint hostname (us-west.s3.qencode.com or eu-central.s3.qencode.com)
<bucket_name>Name of your bucket
<object_key>Path to the object inside the bucket
<expiration_seconds>How long the URL should remain valid (in seconds)

Option 2 — Using Python (Boto3)

Prerequisite: Install the boto3 module before running the scripts:

pip install boto3

Create a settings.py file with your credentials:

S3_ACCESS_KEY = "<access_key>"
S3_SECRET_KEY = "<secret_key>"
REGION_NAME = "<region>"   # e.g. "us-west" or "eu-central"
ENDPOINT_URL = "<endpoint>"  # e.g. "https://us-west.s3.qencode.com"

Then create gen_get_url.py:

import boto3
from botocore.exceptions import ClientError
import settings

def create_presigned_url(bucket_name, object_name, expiration, url_type='get_object'):
    s3_client = boto3.client(
        's3',
        aws_access_key_id=settings.AWS_SERVER_PUBLIC_KEY,
        aws_secret_access_key=settings.AWS_SERVER_SECRET_KEY,
        region_name=settings.REGION_NAME,
        endpoint_url=settings.ENDPOINT_URL
    )
    try:
        response = s3_client.generate_presigned_url(
            url_type,
            Params={'Bucket': bucket_name, 'Key': object_name},
            ExpiresIn=expiration,
        )
    except ClientError as e:
        print(e)
        return None
    return response

create_presigned_url(
    bucket_name='<bucket_name>',
    object_name='<object_key>',
    expiration=<expiration_seconds>,
    url_type='get_object'
)

Run it with:

python gen_get_url.py

Generating a PUT Presigned URL (for uploading)

A PUT presigned URL lets someone upload a file to a specific location in your bucket — without needing your credentials.

note
Note
If an object already exists at the specified key, it will be replaced by the uploaded file.

Create gen_put_url.py (requires boto3 python module installed as a dependency):

import boto3
from botocore.exceptions import ClientError
import settings

def create_presigned_url(bucket_name, object_name, expiration, url_type='put_object'):
    s3_client = boto3.client(
        's3',
        aws_access_key_id=settings.AWS_SERVER_PUBLIC_KEY,
        aws_secret_access_key=settings.AWS_SERVER_SECRET_KEY,
        region_name=settings.REGION_NAME,
        endpoint_url=settings.ENDPOINT_URL
    )
    try:
        response = s3_client.generate_presigned_url(
            url_type,
            Params={'Bucket': bucket_name, 'Key': object_name},
            ExpiresIn=expiration,
        )
    except ClientError as e:
        print(e)
        return None
    return response

create_presigned_url(
    bucket_name='<bucket_name>',
    object_name='<object_key>',
    expiration=<expiration_seconds>,
    url_type='put_object'
)

Run it with:

python gen_put_url.py

Use the same settings.py from the GET example above.

Downloading with a GET Presigned URL

Once you have a GET presigned URL, you can use it to download the object in several ways:

  • In a browser — simply paste the URL into the address bar.
  • Using curl:
curl -X GET "<presigned_url>"

Uploading with a PUT Presigned URL

To upload a local file using a PUT presigned URL:

curl -X PUT -T "/path/to/local/file" "<presigned_url>"

Replace /path/to/local/file with the full path to the file on your device.

Saving Qencode transcoding output to a presigned S3 URL

Qencode can save a transcoding output directly to a presigned S3 PUT URL. This allows Qencode to upload the result without including the storage access key or secret key in the transcoding task.

Add the complete presigned HTTPS PUT URL to destination:

{ 
    "destination": 
    { 
        "url": "https://nyc3.digitaloceanspaces.com/yourspace/output.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=..." 
    }   
}

The storage destination type is detected automatically when:

  • The URL uses the http:// or https:// scheme.
  • The URL contains the X-Amz-Signature query parameter.

No additional storage type or destination field is required.

The key and secret are no longer required for pre-signed S3 upload. They can now be omitted entirely, and they are ignored either way (whether provided or not) — they do not affect the upload. No dummy values are needed anymore.

Destination parameters

destination - object or array of objects

NameTypeRequirementDescription
urlstringRequiredThe URL (including the protocol) of the output to be created
keystringnot Required*S3 storage Access Key ID
secretstringnot Required*S3 storage Secret Access Key
permissionsstringOptionalS3 object access permissions
aclstringOptionalDefine the Access Control List (ACL) for an object when saving transcoding results to Amazon S3
storage_classstringOptionalS3 storage class (AWS)
cache_controlstringOptionalSets the Cache-Control metadata for S3 storage
is_passiveinteger (1 or 0)OptionalEnables FTP passive mode
use_tlsinteger (1 or 0)OptionalEnables FTP over SSL (TLS)
tcp_portintegerOptionalTCP port for Aspera
udp_portintegerOptionalUDP port for Aspera
  • key and secret are required for regular S3 destinations (s3://), but are optional and ignored for pre-signed S3 PUT URLs.

Key things to know

  • A presigned URL can be used multiple times until it expires.
  • The expiration time is set when the URL is generated and cannot be changed afterward.
  • Anyone who has the URL can use it within the expiration window — treat it like a temporary password and share it only with intended recipients.

For additional information, tutorials, or support, visit the Qencode Documentation pageLink or contact Qencode Support at support@qencode.com.