Getting a pre-signed URL to upload an object
If your bucket is public, you can upload objects without restrictions even if the bucket has no website hosting configured. You can get a link by following this guide or generate one yourself. Learn more about the link format here.
If you have a bucket with restricted access, Object Storage enables you to generate a pre-signed URL to upload an object. Anyone with this link can upload the object, even to a bucket with restricted access. You can read more about pre-signed URLs, their generation, and their use here.
Note
If the bucket has an access policy in place which bans creating pre-signed URLs, you will not be able to create a 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 options.
-
View the description of the CLI command to get an object pre-signed URL:
yc storage s3 presign --help -
Get a list of buckets in the default folder:
yc storage bucket listResult:
+------------------+----------------------+-------------+-----------------------+---------------------+ | NAME | FOLDER ID | MAX SIZE | DEFAULT STORAGE CLASS | CREATED AT | +------------------+----------------------+-------------+-----------------------+---------------------+ | first-bucket | b1gmit33ngp6******** | 53687091200 | STANDARD | 2022-12-16 13:58:18 | +------------------+----------------------+-------------+-----------------------+---------------------+ -
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 APILocalTo generate a pre-signed URL to upload 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> \ --http-method PUTWhere:
<bucket_name>: Name of the bucket to upload the object to, e.g.,first-bucket.<object_key>: Object (file) name to use in the bucket, e.g.,sample.txt.--expires-in: URL validity period in seconds.--http-method PUT: HTTP method for uploading the object to the bucket. This is a required parameter for generating an upload URL.
Result:
https://storage.yandexcloud.net/first-bucket/sample.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEwkbVN5BKvE2wqYiZCzlQ%2F20260205%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20260205T131200Z&X-Amz-Expires=3600&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&X-Amz-SignedHeaders=hostTo generate a pre-signed URL to upload 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> \ --http-method PUT \ --local \ --access-key <key_ID> \ --secret-key <secret_key>Where:
<bucket_name>: Name of the bucket to upload the object to, e.g.,first-bucket.<object_key>: Object (file) name to use in the bucket, e.g.,sample.txt.--expires-in: URL validity period in seconds.--http-method PUT: HTTP method for uploading the object to the bucket. This is a required parameter for generating an upload URL.
--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/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&x-id=PutObject&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -
To upload the file using the pre-signed URL, run this command:
curl --request PUT \ --upload-file <file_path> \ "<obtained_pre-signed_URL>"Where:
<file_path>: Path to the local file to upload to the bucket, e.g.,~/sample.txtor./sample.txt.<obtained_pre-signed_URL>: URL you got in the previous step.
Here is an example:
curl --request PUT \ --upload-file ~/sample.txt \ "https://storage.yandexcloud.net/first-bucket/sample.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEwkbVN5BKvE2wqYiZCzlQ%2F20260205%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20260205T131200Z&X-Amz-Expires=3600&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&X-Amz-SignedHeaders=host"If the file is uploaded successfully, the command will not return any message. To view the request details, add the
--verboseflag.
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.
Install
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, e.g.,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********"
}
}
Use the components you obtained to send an HTTP POST request to upload the file:
curl \
--request POST \
--form "key=new-prefix/sample-object.txt" \
--form "x-amz-algorithm=AWS4-HMAC-SHA256" \
--form "x-amz-credential=YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request" \
--form "x-amz-date=20250516T145901Z" \
--form "policy=eyJleHBpcmF0aW9uIjogIjIwMjUtMDUtMTZUMTU6NTk6MDFaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDUyNDI4ODBdLCB7ImJ1Y2tldCI6ICJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSwgeyJrZXkiOiAiZmlsZS50eHQifSwgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LCB7IngtYW16LWNyZWRlbnRpYWwiOiAiWUNBSkU5OHVUcktKd0F0cXdySEpYTmg1TC8yMDI1MDUxNi9ydS1jZW50cmFsMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwNTE2VDE0NTkw********" \
--form "x-amz-signature=c2e1783095d20d89a7683fc582527740541de16156569d9950cfb1b7********" \
--form "file=@sample-object.txt" \
https://storage.yandexcloud.net/my-sample-bucket
Where @sample-object.txt is the path to the file you need to upload.
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>
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.
This example uses the @aws-sdk/client-s3
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 * 1024 * 1024; // 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********'
}
}
Use the components you obtained to send an HTTP POST request to upload the file:
curl \
--request POST \
--form "key=new-prefix/sample-object.txt" \
--form "x-amz-algorithm=AWS4-HMAC-SHA256" \
--form "x-amz-credential=YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request" \
--form "x-amz-date=20250516T145901Z" \
--form "policy=eyJleHBpcmF0aW9uIjogIjIwMjUtMDUtMTZUMTU6NTk6MDFaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDUyNDI4ODBdLCB7ImJ1Y2tldCI6ICJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSwgeyJrZXkiOiAiZmlsZS50eHQifSwgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LCB7IngtYW16LWNyZWRlbnRpYWwiOiAiWUNBSkU5OHVUcktKd0F0cXdySEpYTmg1TC8yMDI1MDUxNi9ydS1jZW50cmFsMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwNTE2VDE0NTkw********" \
--form "x-amz-signature=c2e1783095d20d89a7683fc582527740541de16156569d9950cfb1b7********" \
--form "file=@sample-object.txt" \
https://storage.yandexcloud.net/my-sample-bucket
Where @sample-object.txt is the path to the file you need to upload.
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>
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.
Install
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 * 1024 * 1024; // 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 components you obtained to send an HTTP POST request to upload the file:
curl \
--request POST \
--form "key=new-prefix/sample-object.txt" \
--form "x-amz-algorithm=AWS4-HMAC-SHA256" \
--form "x-amz-credential=YCAJE98uTrKJwAtqw********/20250516/ru-central1/s3/aws4_request" \
--form "x-amz-date=20250516T145901Z" \
--form "policy=eyJleHBpcmF0aW9uIjogIjIwMjUtMDUtMTZUMTU6NTk6MDFaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDUyNDI4ODBdLCB7ImJ1Y2tldCI6ICJhbHRhcmFza2luLXRlc3Rlci1idWNrZXQifSwgeyJrZXkiOiAiZmlsZS50eHQifSwgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LCB7IngtYW16LWNyZWRlbnRpYWwiOiAiWUNBSkU5OHVUcktKd0F0cXdySEpYTmg1TC8yMDI1MDUxNi9ydS1jZW50cmFsMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwNTE2VDE0NTkw********" \
--form "x-amz-signature=c2e1783095d20d89a7683fc582527740541de16156569d9950cfb1b7********" \
--form "file=@sample-object.txt" \
https://storage.yandexcloud.net/my-sample-bucket
Where @sample-object.txt is the path to the file you need to upload.
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>
Note
You cannot extend the validity period of a pre-signed URL to an object in a bucket with restricted access. If the URL has expired, generate a new one.