Yandex Cloud
Search
Contact UsTry it for free
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
  • Marketplace
    • Featured
    • Infrastructure & Network
    • Data Platform
    • AI for business
    • Security
    • DevOps tools
    • Serverless
    • Monitoring & Resources
  • 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
    • Price calculator
    • Pricing plans
  • Customer Stories
  • Documentation
  • Blog
© 2026 Direct Cursus Technology L.L.C.
Yandex Object Storage
    • All guides
      • Uploading an object
      • Multipart upload of an object
      • Get a list of bucket objects
      • Getting information about an object
      • Downloading an object
      • Restoring an object's version
      • Renaming and moving objects
      • Copying objects
      • Downloading an object using a pre-signed URL
      • Uploading an object using a pre-signed URL
      • Configuring an object lock
      • Deleting an object
      • Deleting all objects
      • Deleting a partially uploaded object
      • Editing an object's ACL
      • Managing object labels
      • Managing object custom metadata
  • Pricing policy
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Bucket logs
  • Release notes
  • FAQ
  1. Step-by-step guides
  2. Objects
  3. Uploading an object using a pre-signed URL

Getting a pre-signed URL to upload an object

Written by
Yandex Cloud
Updated at March 6, 2026

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.

Yandex Cloud CLI
SDK for Python (boto3)
SDK for JavaScript
SDK for Go

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.

  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. 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
    Local

    To 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 PUT
    

    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.

    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=host
    

    To 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
    
  4. 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.txt or ./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 --verbose flag.

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 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, 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 and @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 * 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 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 * 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.

See alsoSee also

  • Getting a pre-signed URL to download an object

Was the article helpful?

Previous
Downloading an object using a pre-signed URL
Next
Configuring an object lock
© 2026 Direct Cursus Technology L.L.C.