Yandex Cloud
Search
Contact UsGet started
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • AI for business
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Center for Technologies and Society
    • Yandex Cloud Partner program
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
© 2025 Direct Cursus Technology L.L.C.
Yandex Object Storage
    • Overview
    • Bucket
    • Object
    • Bucket versioning
    • Object lock
    • Partial object updates
    • Encryption
    • Object lifecycles
    • CORS
    • Hosting static websites
    • Pre-signed URLs
    • Multipart upload
    • Access control list (ACL)
    • Bucket policy
    • Uploading files via an HTML form
    • Storage class
    • Bucket actions logging mechanism
    • Backups
    • TLS protocol
    • Labels
    • S3 Select query language
    • Quotas and limits
  • Pricing policy
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Bucket logs
  • Release notes
  • FAQ

In this article:

  • General pre-signed URL format
  • Creating pre-signed URLs
  • Canonical request
  • String to sign
  • Signing key
  • Sign a string with a key
  • Pre-signed URLs
  • Examples of getting a pre-signed link in the Object Storage tools
  • Downloading objects
  • Uploading objects
  • Use cases
  1. Concepts
  2. Pre-signed URLs

Pre-signed URLs

Written by
Yandex Cloud
Improved by
Maksim S.
Updated at September 26, 2025
  • General pre-signed URL format
  • Creating pre-signed URLs
    • Canonical request
    • String to sign
    • Signing key
    • Sign a string with a key
    • Pre-signed URLs
  • Examples of getting a pre-signed link in the Object Storage tools
    • Downloading objects
    • Uploading objects
  • Use cases

Object Storage incorporates several access management mechanisms. To learn how these mechanisms interact, see Access management methods in Object Storage: Overview.

With pre-signed URLs, any web user can perform various operations in Object Storage, such as:

  • Download an object.
  • Upload an object.
  • Create a bucket.

A pre-signed URL is a URL containing request authorization data in its parameters. Pre-signed URLs can be created by users with static access keys.

This section outlines the general principles for generating pre-signed URLs using AWS Signature V4.

Note

SDKs for various programming languages and other tools for AWS S3 feature out-of-the-box methods for generating pre-signed URLs that you can also use for Object Storage.

General pre-signed URL formatGeneral pre-signed URL format

https://<bucket_name>.storage.yandexcloud.net/<object_key>?
     X-Amz-Algorithm=AWS4-HMAC-SHA256
    &X-Amz-Credential=<access_key-id>%2F<YYYYMMDD>%2Fru-central1%2Fs3%2Faws4_request
    &X-Amz-Date=<time_in_ISO_8601_format>
    &X-Amz-Expires=<link_lifetime>
    &X-Amz-SignedHeaders=<list_of_signed_headers>
    &X-Amz-Signature=<signature>

Pre-signed URL parameters:

Parameter Description
X-Amz-Algorithm Identifies the signature version and algorithm for its calculation. Value: AWS4-HMAC-SHA256.
X-Amz-Credential Signature ID.

This is a string in <access-key-id>/<YYYYMMDD>/ru-central1/s3/aws4_request format, where <YYYYMMDD> must match the date set in the X-Amz-Date header.
X-Amz-Date Time in ISO8601 format, e.g., 20180719T000000Z. The specified date value (not the format) must match the date in the X-Amz-Credential parameter.
X-Amz-Expires Link validity time in seconds. The starting point is the time specified in X-Amz-Date. The maximum value is 2,592,000 seconds (30 days).
X-Amz-SignedHeaders Headers of the request you want to sign, delimited by a semicolon (;).

Make sure to sign the Host header and all X-Amz-* headers used in the request. You do not have to sign other headers; however, the more headers you sign, the safer your request is going to be.
X-Amz-Signature Request signature.

Creating pre-signed URLsCreating pre-signed URLs

Note

Generating pre-signed URLs is optional for public buckets. You can get files from a publicly available bucket either via HTTP or HTTPS, even if the bucket has no website hosting configured.

To get a pre-signed URL:

  1. Create a canonical request.
  2. Compose a string to sign.
  3. Generate a signing key.
  4. Calculate the signature using the key.
  5. Generate a pre-signed URL.

To create a pre-signed URL, you must have static access keys.

Canonical requestCanonical request

The general canonical request format is as follows:

<HTTPVerb>\n
<CanonicalURL>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
UNSIGNED-PAYLOAD

HTTPVerbHTTPVerb

HTTP method to use to send the request: GET, PUT, HEAD, or DELETE.

CanonicalURLCanonicalURL

URL-encoded object key, e.g., /folder/object.ext.

Note

Do not normalize the path. For example, if an object has the some//strange//key//example key, normalizing the path to /<bucket-name>/some/strange/key/example will invalidate the key.

CanonicalQueryStringCanonicalQueryString

The canonical query string must include all query parameters of the final URL, except X-Amz-Signature. The parameters in the string must be URL-encoded and sorted alphabetically.

Example:

X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JK38EXAMPLEAKDID8%2F20190801%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20190801T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host

CanonicalHeadersCanonicalHeaders

This section includes the list of the request headers with their values.

The requirements are as follows:

  • Each header is separated by the line break character (\n).
  • Header names must be lowercase.
  • Headers must appear in alphabetical order.
  • There may not be any extra spaces.
  • The list must contain the host header and all x-amz-* headers used in the request.

You can also add any request header to the list. The more headers you sign, the safer your request is going to be.

Example:

host:sample-bucket.storage.yandexcloud.net
x-amz-date:20190801T000000Z

SignedHeadersSignedHeaders

This is a list of lowercase request header names, sorted alphabetically and separated by semicolons.

Here is an example:

host;x-amz-date

Canonical request endingCanonical request ending

A canonical request must always end with the UNSIGNED-PAYLOAD string.

String to signString to sign

General format of a string to sign:

"AWS4-HMAC-SHA256" + "\n" +
<timestamp> + "\n" +
<scope> + "\n" +
Hex(Hash-SHA256(<CanonicalRequest>))

Where:

  • AWS4-HMAC-SHA256: Hash algorithm.
  • timestamp: Current time in ISO 8601 format, e.g., 20190801T000000Z. The specified date value (not the format) must match the date in the scope parameter.
  • scope: <YYYYMMDD>/ru-central1/s3/aws4_request.
  • CanonicalRequest: Canonical request generated earlier. The signature string contains the SHA256 hash of the canonical request in hexadecimal representation.

Signing keySigning key

To generate a signing key:

  1. Use the secret key to encode the date:

    DateKey = sign("AWS4" + "SecretKey", "yyyymmdd")
    
  2. Encode the region using DateKey you got in the previous step:

    RegionKey = sign(DateKey, "ru-central1")
    
  3. Encode the service using RegionKey you got in the previous step:

    ServiceKey = sign(RegionKey, "s3")
    
  4. Get the signing key:

    SigningKey = sign(ServiceKey, "aws4_request")
    

Sign a string with a keySign a string with a key

To get a string signature, use HMAC with the SHA256 hash function and convert the result to hexadecimal format.

signature = Hex(sign(SigningKey, StringToSign))

Pre-signed URLsPre-signed URLs

To create a pre-signed URL, add the parameters required to authorize the request to the Object Storage resource URL, including the X-Amz-Signature parameter containing the calculated signature.

The other parameter values must match their respective values specified earlier in the canonical request and the signature string.

Example of creating a pre-signed URL for downloading an objectExample of creating a pre-signed URL for downloading an object

Let's put together a pre-signed URL to download the object-for-share.txt object from the bucket for an hour:

  • Static key:

    access_key_id = 'JK38EXAMP********'
    secret_access_key = 'ExamP1eSecReTKeykdo********'
    
  • Canonical request:

    GET
    /object-for-share.txt
    X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEK0Iv6x********eLTAdg%2F20231208%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20231208T184504Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host 
    host:<bucket_name>.storage.yandexcloud.net
    
    host
    UNSIGNED-PAYLOAD
    
  • String to sign:

    AWS4-HMAC-SHA256
    20231208T184504Z
    20231208/ru-central1/s3/aws4_request
    e823d75aad02c1317589bd5373fe9e20d5ef44499237703ff23e5600********
    
  • Signing key:

    sign(sign(sign(sign("AWS4" + "ExamP1eSecReTKeykdokKK38800","20190801"),"ru-central1"),"s3"),"aws4_request")
    

    Here, we introduce the sign function to indicate the HMAC algorithm with SHA256 as the key calculation method.

  • Signature:

    b10c16a1997bb524bf59974512f1a6561cf2953c29dc3efbdb920790********
    
  • Pre-signed URL:

    https://<bucket_name>.storage.yandexcloud.net/object-for-share.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEK0Iv6xqy-pEQcueLTAdg%2F20231208%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20231208T195434Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=b10c16a1997bb524bf59974512f1a6561cf2953c29dc3efbdb920790********
    

You can test the request and signature generation using the AWS CLI in debug mode.

To send a signed request to the S3 API, you can use curl.

Code examples for generating pre-signed URLsCode examples for generating pre-signed URLs

The subsection provides code examples for generating pre-signed URLs.

To show the principle of generating and signing requests to Object Storage, the examples do not use AWS SDKs. For examples of using the AWS SDK and other tools, see Examples of getting a pre-signed link in the Object Storage tools.

Python
PHP
import datetime
import hashlib
import hmac

access_key = '<static_key_ID>'
secret_key = '<static_key_contents>'
object_key = '<object_key>'
bucket = '<bucket_name>'
host = 'storage.yandexcloud.net'
now = datetime.datetime.now(datetime.UTC)
datestamp = now.strftime('%Y%m%d')
timestamp = now.strftime('%Y%m%dT%H%M%SZ')

def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

canonical_request = """GET
/{bucket}/{object_key}
X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={access_key}%2F{datestamp}%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date={timestamp}&X-Amz-Expires=3600&X-Amz-SignedHeaders=host
host:{host}

host
UNSIGNED-PAYLOAD""".format(
    bucket=bucket,
    object_key=object_key,
    access_key=access_key,
    datestamp=datestamp,
    timestamp=timestamp,
    host=host)

print()
print("Canonical request:\n" + canonical_request)
print()

string_to_sign = """AWS4-HMAC-SHA256
{timestamp}
{datestamp}/ru-central1/s3/aws4_request
{request_hash}""".format(
    timestamp=timestamp,
    datestamp=datestamp,
    request_hash=hashlib.sha256(canonical_request.encode('utf-8')).hexdigest())

print()
print("String to be signed:\n" + string_to_sign)
print()

signing_key = sign(sign(sign(sign(('AWS4' + secret_key).encode('utf-8'), datestamp), 'ru-central1'), 's3'), 'aws4_request')
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()

print()
print("Signature: " + signature)
print()

signed_link = "https://" + host + '/' + bucket + '/' + object_key + "?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=" + access_key + "%2F" + datestamp + "%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=" + timestamp + "&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=" + signature + "\n"

print()
print("Signed Link:\n" + signed_link)
<?php

  date_default_timezone_set('UTC');
  $keyid = "<static_key_ID>";
  $secretkey = "<static_key_contents>";
  $path = "<object_key>";
  $objectname = "/".implode("/", array_map("rawurlencode", explode("/", $path)));
  $host = "<bucket_name>.storage.yandexcloud.net";
  $region = "ru-central1";
  $timestamp = time();
  $dater = strval(date('Ymd', $timestamp));
  $dateValue = strval(date('Ymd', $timestamp))."T".strval(date('His', $timestamp))."Z";

  // Generate the canonical request
  $canonical_request = "GET\n".$objectname."\nX-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=".$keyid."%2F".$dater."%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=".$dateValue."&X-Amz-Expires=3600&X-Amz-SignedHeaders=host\nhost:".$host."\n\nhost\nUNSIGNED-PAYLOAD";

  echo "<b>Canonical request: </b><br>".$canonical_request."<br><br>";

  // Generate the string to be signed
  $string_to_sign = "AWS4-HMAC-SHA256\n".$dateValue."\n".$dater."/".$region."/s3/aws4_request\n".openssl_digest($canonical_request, "sha256", $binary = false);

  echo "<b>String to be signed: </b><br>".$string_to_sign."<br><br>";

  // Generate the signing key
  $signing_key = hash_hmac('sha256', 'aws4_request', hash_hmac('sha256', 's3', hash_hmac('sha256', 'ru-central1', hash_hmac('sha256', $dater, 'AWS4'.$secretkey, true), true), true), true);

  echo "<b>Signing key: </b><br>".$signing_key."<br><br>";

  // Generate the signature
  $signature = hash_hmac('sha256', $string_to_sign, $signing_key);

  echo "<b>Signature: </b><br>".$signature."<br><br>";

  // Generate the pre-signed link
  $signed_link = "https://".$host.$objectname."?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=".$keyid."%2F".$dater."%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=".$dateValue."&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=".$signature."\n";

  echo '<b>Signed link: </b><br>'.'<a href = "'.$signed_link.'" target = "_blank">'.$signed_link.'</a>';

?>

Examples of getting a pre-signed link in the Object Storage toolsExamples of getting a pre-signed link in the Object Storage tools

This subsection provides examples of generating pre-signed URLs with the help of various Object Storage tools.

Downloading objectsDownloading objects

Management console
Yandex Cloud CLI
AWS CLI
SDK for Python (boto3)
SDK for JavaScript
  1. In the management console, select the folder.
  2. Select Object Storage.
  3. Click the name of the bucket you need.
  4. Click the object name.
  5. Click Get link in the top-right corner.
  6. For a bucket with restricted access, specify the link Lifetime in hours or days (the maximum time is 30 days).
  7. Click Get link.
  8. Copy the link.

If you do not have the Yandex Cloud CLI installed yet, install and initialize it.

By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID> command. You can also set a different folder for any specific command using the --folder-name or --folder-id parameter.

  1. View the description of the CLI command to get an object pre-signed URL:

    yc storage s3 presign --help
    
  2. Get a list of buckets in the default folder:

    yc storage bucket list
    

    Result:

    +------------------+----------------------+-------------+-----------------------+---------------------+
    |       NAME       |      FOLDER ID       |  MAX SIZE   | DEFAULT STORAGE CLASS |     CREATED AT      |
    +------------------+----------------------+-------------+-----------------------+---------------------+
    | first-bucket     | b1gmit33ngp6******** | 53687091200 | STANDARD              | 2022-12-16 13:58:18 |
    +------------------+----------------------+-------------+-----------------------+---------------------+
    
  3. View a list of objects in the bucket by specifying its name:

    yc storage s3api list-objects \
      --bucket <bucket_name>
    

    Result:

    contents:
      - key: sample.txt
        last_modified: "2025-09-04T06:02:16.884Z"
        etag: '"7bd56d2f6096d582420e8a01********"'
        size: "17"
        owner:
          id: ajeol2afu1js********
          display_name: ajeol2afu1js********
        storage_class: STANDARD
    name: first-bucket
    max_keys: "1000"
    key_count: "1"
    request_id: 338862e1********
    
  4. Generate a pre-signed URL. You can do this either via the Yandex Cloud API on behalf of the account currently authenticated in the Yandex Cloud CLI profile, or locally on behalf of the service account, providing its static access key in the command.

    Using the Yandex Cloud API
    Locally

    To generate a pre-signed URL to download an object on behalf of the account currently authenticated in the Yandex Cloud CLI profile, run this command:

    yc storage s3 presign \
      s3://<bucket_name>/<object_key> \
      --expires-in <link_validity> \
      --as-attachment
    

    Where:

    • <bucket_name>: Name of the bucket containing the object you need, e.g., first-bucket.
    • <object_key>: Object key in the bucket to generate a pre-signed URL for, e.g., sample.txt.
    • --expires-in: URL validity period in seconds.
    • --as-attachment: For a forced download of an object when opening the URL you got in a browser. This is an optional parameter. If the option is not set, when opening a URL, the browser may try to display the contents of the text object instead of downloading it.

    Result:

    https://storage.yandexcloud.net/first-bucket/sample.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEIUp_5V5nBFDgIgh-NLc2%2F20250904%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20250904T063033Z&X-Amz-Expires=36000&X-Amz-Signature=d661b64566753dba1ef66b467e56db0e7f7c69581b0ddd2c8a0a7b505bc3ff61&X-Amz-SignedHeaders=host&response-content-disposition=attachment
    

    To generate a pre-signed URL to download an object locally on behalf of a service account, run this command:

    yc storage s3 presign \
      s3://<bucket_name>/<object_key> \
      --expires-in <link_validity> \
      --as-attachment \
      --local \
      --access-key <key_ID> \
      --secret-key <secret_key>
    

    Where:

    • <bucket_name>: Name of the bucket containing the object you need, e.g., first-bucket.
    • <object_key>: Object key in the bucket to generate a pre-signed URL for, e.g., sample.txt.
    • --expires-in: URL validity period in seconds.
    • --as-attachment: For a forced download of an object when opening the URL you got in a browser. This is an optional parameter. If the option is not set, when opening a URL, the browser may try to display the contents of the text object instead of downloading it.
    • --access-key: Static access key ID of the service account.
    • --secret-key: Secret key of the service account static access key.

    Result:

    https://storage.yandexcloud.net:443/first-bucket/sample.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJE98uTrKJwAtqwrHJXNh5L%2F20250904%2Fdefault%2Fs3%2Faws4_request&X-Amz-Date=20250904T072650Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=host&response-content-disposition=attachment&x-id=GetObject&X-Amz-Signature=e60562ef242588eec44916ad9e97d2864b250a73f4e5a70e29bb2bd8926249b0
    

You can use the AWS CLI to generate a pre-signed URL for downloading an object. To do this, run this command:

aws s3 presign s3://<bucket_name>/<object_key> \
  --expires-in <link_lifetime> \
  --endpoint-url "https://storage.yandexcloud.net/"

To generate the link properly, make sure to provide the --endpoint-url parameter pointing to the Object Storage hostname. For detailed information, see this section covering the AWS CLI specifics.

The example generates a pre-signed URL for downloading object-for-share from bucket-with-objects. The URL is valid for 100 seconds.

# coding=utf-8

import boto3
from botocore.client import Config


ENDPOINT = "https://storage.yandexcloud.net"

ACCESS_KEY = "JK38EXAMP********"
SECRET_KEY = "ExamP1eSecReTKeykdo********"

session = boto3.Session(
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY,
    region_name="ru-central1",
)
s3 = session.client(
    "s3", endpoint_url=ENDPOINT, config=Config(signature_version="s3v4")
)

presigned_url = s3.generate_presigned_url(
    "get_object",
    Params={"Bucket": "bucket-with-objects", "Key": "object-for-share"},
    ExpiresIn=100,
)

print(presigned_url)

The example generates a pre-signed URL for downloading object-for-share from bucket-with-objects. The URL is valid for 100 seconds.

This example uses the @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner libraries.

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

const S3_ENDPOINT = "https://storage.yandexcloud.net";

const ACCESS_KEY_ID = "JK38EXAMP********";
const SECRET_ACCESS_KEY = "ExamP1eSecReTKeykdo********";

const s3Client = new S3Client({
  region: "ru-central1",
  endpoint: S3_ENDPOINT,
  credentials: {
    accessKeyId: ACCESS_KEY_ID,
    secretAccessKey: SECRET_ACCESS_KEY,
  },
});

const command = new GetObjectCommand({
  Bucket: "bucket-with-objects",
  Key: "object-for-share",
});
const objectPresignedUrl = await getSignedUrl(s3Client, command, {
  expiresIn: 100,
});

console.log(objectPresignedUrl);

Uploading objectsUploading objects

Before using the examples, save the required authentication data to environment variables:

export AWS_ACCESS_KEY_ID="<static_key_ID>"
export AWS_SECRET_ACCESS_KEY="<secret_key>"
export AWS_DEFAULT_REGION="ru-central1"
export AWS_REGION="ru-central1"
export AWS_ENDPOINT_URL="https://storage.yandexcloud.net"

Where:

  • AWS_ACCESS_KEY_ID: Static access key ID.
  • AWS_SECRET_ACCESS_KEY: Secret key.

The code in the examples generates a signed URL to upload an object with a specified key into a specified bucket. The URL you get is valid for one hour.

In this example, the size of the uploaded object is limited and cannot exceed the 5 MB value set in the code.

SDK for Python (boto3)
SDK for JavaScript
SDK for Go

Install boto3 and run this code:

import logging
import boto3
from botocore.exceptions import ClientError
import json


def create_presigned_post(bucket_name, object_name, max_size, expiration, fields=None):

    conditions = [["content-length-range", 1, max_size]]

    s3_client = boto3.client("s3")
    try:
        response = s3_client.generate_presigned_post(
            bucket_name,
            object_name,
            Fields=fields,
            Conditions=conditions,
            ExpiresIn=expiration,
        )
    except ClientError as e:
        logging.error(e)
        return None

    return response


def main():

    bucket_name = "<bucket_name>"
    object_name = "<uploaded_object_key>"
    max_size = 5 * 1024 * 1024  # Maximum size of uploaded object in bytes
    lifespan = 3600 # Link validity period in seconds

    response = create_presigned_post(bucket_name, object_name, max_size, lifespan)

    print("Signed link and data to upload created successfully:")
    print(json.dumps(response, indent=4))


if __name__ == "__main__":
    main()

Where:

  • bucket_name: Name of the bucket to upload the file to.
  • object_name: Key to assign to the object in the bucket. For example, new-prefix/sample-object.txt.
  • max_size: Maximum allowed size of the uploaded file in bytes.

Result:

Signed link and data to upload created successfully:
{
    "url": "https://storage.yandexcloud.net/my-sample-bucket",
    "fields": {
        "key": "new-prefix/sample-object.txt",
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-credential": "YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request",
        "x-amz-date": "20250516T145901Z",
        "policy": "eyJleHBpcmF0aW9uIjogIjIwMjUtMDUtMTZUMTU6NTk6MDFaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDUyNDI4ODBdLCB7ImJ1Y2tldCI6ICJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSwgeyJrZXkiOiAiZmlsZS50eHQifSwgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LCB7IngtYW16LWNyZWRlbnRpYWwiOiAiWUNBSkU5OHVUcktKd0F0cXdySEpYTmg1TC8yMDI1MDUxNi9ydS1jZW50cmFsMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwNTE2VDE0NTkw********",
        "x-amz-signature": "c2e1783095d20d89a7683fc582527740541de16156569d9950cfb1b7********"
    }
}

This example uses the @aws-sdk/client-s3 and @aws-sdk/@aws-sdk/s3-presigned-post libraries.

Run the following code:

import { S3Client } from "@aws-sdk/client-s3";
import { createPresignedPost } from "@aws-sdk/s3-presigned-post";

const client = new S3Client();
const Bucket = "<bucket_name>";
const Key = "<uploaded_object_key>";
const max_size = 5 * 1,024 * 1,024;  // Maximum size of uploaded object in bytes

const Conditions = [["content-length-range", 1, max_size]];

const url = await createPresignedPost(client, {
  Bucket,
  Key,
  Conditions,
  Expires: 3600, // Link validity period in seconds
});

console.log(url)

Where:

  • Bucket: Name of the bucket to upload the file to.
  • Key: Key to assign to the object in the bucket, e.g., new-prefix/sample-object.txt.
  • max_size: Maximum allowed size of the uploaded file in bytes.

Result:

{
  url: 'https://my-sample-bucket.storage.yandexcloud.net/',
  fields: {
    bucket: 'my-sample-bucket',
    'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
    'X-Amz-Credential': 'YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request',
    'X-Amz-Date': '20250516T210215Z',
    key: 'new-prefix/sample-object.txt',
    Policy: 'eyJleHBpcmF0aW9uIjoiMjAyNS0wNS0xNlQyMjowMjoxNVoiLCJjb25kaXRpb25zIjpbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMSw1MjQyODgwXSx7ImJ1Y2tldCI6ImFsdGFyYXNraW4tdGVzdGVyLWJ1Y2tldCJ9LHsiWC1BbXotQWxnb3JpdGhtIjoiQVdTNC1ITUFDLVNIQTI1NiJ9LHsiWC1BbXotQ3JlZGVudGlhbCI6IllDQUpFOTh1VHJLSndBdHF3ckhKWE5oNUwvMjAyNTA1MTYvcnUtY2VudHJhbDEvczMvYXdzNF9yZXF1ZXN0In0seyJYLUFtei1EYXRlIjoiMjAyNTA1MTZUMjEwMjE1WiJ9LHsia2V5IjoiZmlsZS50********',
    'X-Amz-Signature': '2a8be28a4e2a72de98bd258a8362dd895dd0fdb1886a1764e7085282********'
  }
}

Install AWS SDK for Go and run this code:

package main

import (
  "context"
  "fmt"
  "log"
  "time"

  "github.com/aws/aws-sdk-go-v2/config"
  "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
  cfg, err := config.LoadDefaultConfig(context.TODO())
  if err != nil {
    log.Fatal(err)
  }

  client := s3.NewFromConfig(cfg)

  psClient := s3.NewPresignClient(client)

  bucket := "<bucket_name>"
  key := "<uploaded_object_key>"
  max_size = 5 * 1,024 * 1,024;  // Maximum size of uploaded object in bytes

  req, err := psClient.PresignPostObject(
    context.TODO(),
    &s3.PutObjectInput{
      Bucket: &bucket,
      Key:    &key,
    },
    func(opts *s3.PresignPostOptions) {
      opts.Expires = time.Hour // Link validity period
      opts.Conditions = []interface{}{
        []interface{}{"content-length-range", 1, max_size},
      }
    },
  )
  if err != nil {
    log.Fatal(err)
  }

  fmt.Printf("url: %v\n", req.URL)
  fmt.Println("values:")
  for k, v := range req.Values {
    fmt.Printf("%v=%v\n", k, v)
  }
}

Where:

  • bucket: Name of the bucket to upload the file to.
  • key: Key to assign to the object in the bucket, e.g., new-prefix/sample-object.txt.
  • max_size: Maximum allowed size of the uploaded file in bytes.

Result:

url: https://my-sample-bucket.storage.yandexcloud.net
values:
X-Amz-Algorithm=AWS4-HMAC-SHA256
X-Amz-Date=20250516T152552Z
X-Amz-Credential=YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request
X-Amz-Signature=9371b1924dd468a9be6b57868565ad5f99cdc7edc3b56589bea3dbfa********
key=new-prefix/sample-object.txt
policy=eyJjb25kaXRpb25zIjpbeyJYLUFtei1BbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJidWNrZXQiOiJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSx7IlgtQW16LUNyZWRlbnRpYWwiOiJZQ0FKRTk4dVRyS0p3QXRxd3JISlhOaDVMLzIwMjUwNTE2L3J1LWNlbnRyYWwxL3MzL2F3czRfcmVxdWVzdCJ9LHsiWC1BbXotRGF0ZSI6IjIwMjUwNTE2VDE1MjU1MloifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwxLDUyNDI4ODBdLHsia2V5IjoiZmlsZS50eHQifV0sImV4cGlyYXRpb24iOiIyMDI1LTA1LTE2VDE2OjI1********

Use the signed link components you got to send an HTTP request to upload a file to the Yandex Object Storage bucket:

curl \
  --request POST \
  --form "X-Amz-Date=20250516T152552Z" \
  --form "X-Amz-Credential=YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request" \
  --form "X-Amz-Signature=9371b1924dd468a9be6b57868565ad5f99cdc7edc3b56589bea3dbfa********" \
  --form "key=new-prefix/sample-object.txt" \
  --form "policy=eyJjb25kaXRpb25zIjpbeyJYLUFtei1BbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJidWNrZXQiOiJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSx7IlgtQW16LUNyZWRlbnRpYWwiOiJZQ0FKRTk4dVRyS0p3QXRxd3JISlhOaDVMLzIwMjUwNTE2L3J1LWNlbnRyYWwxL3MzL2F3czRfcmVxdWVzdCJ9LHsiWC1BbXotRGF0ZSI6IjIwMjUwNTE2VDE1MjU1MloifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwxLDUyNDI4ODBdLHsia2V5IjoiZmlsZS50eHQifV0sImV4cGlyYXRpb24iOiIyMDI1LTA1LTE2VDE2OjI1********" \
  --form "X-Amz-Algorithm=AWS4-HMAC-SHA256" \
  --form "file=./sample-object.txt" \
  https://my-sample-bucket.storage.yandexcloud.net

As a result, the file will be uploaded to the bucket if not exceeding in size the value specified in the code. If the file is larger than the set maximum, an error will be returned:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>EntityTooLarge</Code>
    <Message>Your proposed upload exceeds the maximum allowed object size.</Message>
    <Resource>/</Resource>
    <RequestId>5575e8faa94e02b2</RequestId>
    <MaxSizeAllowed>5242880</MaxSizeAllowed>
    <ProposedSize>15728640</ProposedSize>
</Error>

Use casesUse cases

  • Providing secure access to content in Cloud CDN

Was the article helpful?

Previous
Hosting static websites
Next
Multipart upload
© 2025 Direct Cursus Technology L.L.C.