---
title: "Get a link to an object"
sidebar_label: "Get a link to an object"
description: "How to get a link to an object in a public bucket or create a link to an object in a private bucket"
sidebar_position: 2
---

import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import {TabItemLabel} from '@selectel/docux/components'
import Formbricks from '@theme/MDXComponents/Formbricks'
import LinkIcon from '@selectel/docux/icons/link'
import MoreVerticalIcon from '@selectel/docux/icons/more-vertical'
import CopyIcon from '@selectel/docux/icons/copy'

# Get a link to an object

You can:

* [get a link to an object in a public bucket](#obtain-link-to-object-in-public-bucket) — all objects are available through [public domains](/s3/manage/domains.mdx) of the storage;
* [get a link to an object in a private bucket](#obtain-link-to-object-in-private-bucket) — the link can be permanent or temporary.

We do not recommend using Cyrillic characters in object names. If you use Cyrillic, encode the Cyrillic part of the link to work with such objects.

## Get a link to an object in a public bucket \{#obtain-link-to-object-in-public-bucket}

1. In the [control panel](https://my.selectel.ru/storage/), on the top menu, click **Products** and select **S3**.
2. Go to the **Buckets** section.
3. Open the bucket page → **Objects** tab.
4. In the object line, click .<LinkIcon />
5. In the link line, click .<CopyIcon />

## Get a link to an object in a private bucket \{#obtain-link-to-object-in-private-bucket}

You can:

* [create a permanent or temporary link in the control panel](#create-link-in-control-panel). The link will be saved to a special bucket `links` as an object with the same name as the object the link points to. The object can be accessed via the [bucket public domain](/s3/manage/domains.mdx#bucket-public-domain) `links`;
* [obtain a temporary link via a presigned URL](#obtain-temporary-link-via-presigned-url);
* [obtain a permanent link via a script](#obtain-permanent-link-via-script);
* obtain a permanent or temporary link using tools, for example, [Rclone](/s3/tools/rclone.mdx#obtain-link-to-object), [AWS CLI](/s3/tools/aws-cli.mdx#obtain-link-to-object), [Cyberduck](/s3/tools/cyberduck.mdx#obtain-link-to-object) and [S3 Browser](/s3/tools/s3-browser.mdx#obtain-link-to-object).

### Create a link in the control panel \{#create-link-in-control-panel}

You can get a temporary or permanent link to an object in a private bucket.

An object in a private bucket will be available via a link like `https://<bucket_public_domain>/<object_name>`, where:

* `<bucket_public_domain>` — [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
* `<object_name>` — the object name.

When you create a link to an object in a private bucket for the first time, a public bucket named `links` is automatically created in the project. The created link is added to it as an object with the same name as the main object. Objects in the `links` bucket have zero size and do not consume [storage volume](/s3/about/payment.mdx#storage-volume). If you set up the link as temporary, the object with the link will be automatically removed from the `links` bucket when the link expires.

To create a link:

1. In the [control panel](https://my.selectel.ru/storage/), on the top menu, click **Products** and select **S3**.
2. Go to the **Buckets** section.
3. Open the bucket page → **Objects** tab.
4. In the  object menu, select **Open Access**.<MoreVerticalIcon />
5. Optional: in the **Link address** field, change the object name that will be displayed in the link, or leave it as is.
6. Optional: to ensure the link can only be used once, select the **One-time link** checkbox.
7. Optional: to restrict the link lifetime, select the **Time restrictions** checkbox and choose one of the following:

   * **Delete after** — the link will expire after the specified period of time after creation;
   * **Delete at a specific time** — the link will expire at the selected date and time.
8. Click **Create link**.
9. To copy the link, click . You will be able to [copy it](#obtain-link-to-object-in-public-bucket) later in the `links`.<CopyIcon />

### Get a temporary link via a presigned URL \{#obtain-temporary-link-via-presigned-url}

Use AWS SDK presigned URLs (Presigned URLs) to obtain a temporary link to an object. For more information, see the [Sharing objects with presigned URLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html) article in the AWS documentation.

<Tabs queryString="presigned-url">
  <TabItem value="python">
    <TabItemLabel>
      Python
    </TabItemLabel>

    Script example:

    ```python
    import boto3

    ACCESS_KEY = "<access_key>"      
    SECRET_KEY = "<secret_key>"      
    ENDPOINT_URL = "<s3_domain>" 
    BUCKET_NAME = "<bucket_name>"       
    OBJECT_KEY = "<path_to_object>"      
    EXPIRES_IN = "<time>"

    s3 = boto3.client(
        "s3",
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        endpoint_url=ENDPOINT_URL,
    )

    url = s3.generate_presigned_url(
        ClientMethod="get_object",
        Params={"Bucket": BUCKET_NAME, "Key": OBJECT_KEY},
        ExpiresIn=EXPIRES_IN
    )

    print("\PresignedUrl
    :")
    print(url)
    ```

    Specify:

    * `<access_key>` — the value of the **Access key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<secret_key>` — the value of the **Secret key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<s3_domain>` — [the S3 API domain](/s3/manage/domains.mdx#s3-api-domains) depending on the pool where the bucket is located;
    * `<bucket_name>` — the bucket name;
    * `<path_to_object>` — the path to the object in the bucket;
    * `<time>` — the link lifetime in seconds.
  </TabItem>

  <TabItem value="php">
    <TabItemLabel>
      PHP
    </TabItemLabel>

    Script example:

    ```php
    <?php
    require 'vendor/autoload.php';

    use Aws\S3\S3Client;
    use Aws\Exception\AwsException;

    $selectelS3 = new S3Client([
        'version' => 'latest',
        'region'  => '<pool>',
        'endpoint' => '<s3_domain>':,
        'use_path_style_endpoint' => true,
        'credentials' => [
            'key'    => '<access_key>',
            'secret' => '<secret_key>',
        ],
    ]);

    $bucket = '<bucket_name>';
    $key = '<path_to_object>';

    try {
        $cmd = $selectelS3->getCommand('GetObject', [
            'Bucket' => $bucket,
            'Key'    => $key
        ]);

        $request = $selectelS3->createPresignedRequest($cmd, '<time>');
        $presignedUrl = (string)$request->getUri();

        echo "Public link: $presignedUrl\n";
    } catch (AwsException $e) {
        echo "Error generating link: " . $e->getMessage() . "\n";
    }
    ```

    Specify:

    * `<pool>` — [the pool](/infrastructure/locations.mdx#pool) where the bucket is located;
    * `<s3_domain>` — [the S3 API domain](/s3/manage/domains.mdx#s3-api-domains) depending on the pool where the bucket is located;
    * `<access_key>` — the value of the **Access key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<secret_key>` — the value of the **Secret key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<bucket_name>` — the bucket name;
    * `<path_to_object>` — the path to the object in the bucket;
    * `<time>` — link lifetime, for example `+1 hour`.
  </TabItem>

  <TabItem value="javascript">
    <TabItemLabel>
      JavaScript
    </TabItemLabel>

    Script example:

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

    const client = new S3Client({
    region: "<pool>",
    endpoint: "<s3_domain>",
    forcePathStyle: true,
    credentials: {
        accessKeyId: "<access_key>",
        secretAccessKey: "<secret_key>",
    },
    });

    async function generatePresignedUrl() {
    const bucket = "<bucket_name>";   
    const key = "<path_to_object>";          

    const command = new GetObjectCommand({ Bucket: bucket, Key: key });

    const url = await getSignedUrl(client, command, { expiresIn: <time> });
    console.log("Presigned URL:", url);
    }

    generatePresignedUrl().catch(console.error);
    ```

    Specify:

    * `<pool>` — [the pool](/infrastructure/locations.mdx#pool) where the bucket is located;
    * `<s3_domain>` — [the S3 API domain](/s3/manage/domains.mdx#s3-api-domains) depending on the pool where the bucket is located;
    * `<access_key>` — the value of the **Access key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<secret_key>` — the value of the **Secret key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<bucket_name>` — the bucket name;
    * `<path_to_object>` — the path to the object in the bucket;
    * `<time>` — the link lifetime in seconds.
  </TabItem>

  <TabItem value="java">
    <TabItemLabel>
      Java
    </TabItemLabel>

    Script example:

    ```js
    package com.example;

    import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
    import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
    import software.amazon.awssdk.regions.Region;
    import software.amazon.awssdk.services.s3.S3Client;
    import software.amazon.awssdk.services.s3.model.GetObjectRequest;
    import software.amazon.awssdk.services.s3.model.S3Exception;
    import software.amazon.awssdk.services.s3.presigner.S3Presigner;
    import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
    import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;

    import java.net.URI;
    import java.time.Duration;

    public class SelectelS3PresignedUrlGenerator {
        public static void main(String[] args) {

            String endpoint = "<s3_domain>"; 
            String region = "<pool>";
            String accessKey = "<access_key>";
            String secretKey = "<secret_key>";
            String bucketName = "<bucket_name>";
            String objectKey = "<path_to_object>";

            StaticCredentialsProvider credentials = StaticCredentialsProvider.create(
                    AwsBasicCredentials.create(accessKey, secretKey)
            );

            S3Client s3Client = S3Client.builder()
                    .endpointOverride(URI.create(endpoint))
                    .region(Region.of(region))
                    .credentialsProvider(credentials)
                    .build();

            S3Presigner presigner = S3Presigner.builder()
                    .endpointOverride(URI.create(endpoint))
                    .region(Region.of(region))
                    .credentialsProvider(credentials)
                    .build();

            try {
                GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                        .bucket(bucketName)
                        .key(objectKey)
                        .build();

                GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
                        .signatureDuration(Duration.ofMinutes(<time>))
                        .getObjectRequest(getObjectRequest)
                        .build();

                PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest);

                System.out.println("Presigned URL: " + presignedRequest.url());
                System.out.println("Expires at: " + presignedRequest.expiration());

            } catch (S3Exception e) {
                System.err.println("Error generating presigned URL: " + e.awsErrorDetails().errorMessage());
            } finally {
                s3Client.close();
                presigner.close();
            }
        }
    }
    ```

    Specify:

    * `<s3_domain>` — [the S3 API domain](/s3/manage/domains.mdx#s3-api-domains) depending on the pool where the bucket is located;
    * `<pool>` — [the pool](/infrastructure/locations.mdx#pool) where the bucket is located;
    * `<access_key>` — the value of the **Access key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<secret_key>` — the value of the **Secret key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<bucket_name>` — the bucket name;
    * `<path_to_object>` — the path to the object in the bucket;
    * `<time>` — the link lifetime in minutes.
  </TabItem>

  <TabItem value="go">
    <TabItemLabel>
      Go
    </TabItemLabel>

    Script example:

    ```go
    package main 
    import (
        "context"
        "fmt"
        "log"
        "time"
        "github.com/aws/aws-sdk-go-v2/aws"
        "github.com/aws/aws-sdk-go-v2/config"
        "github.com/aws/aws-sdk-go-v2/credentials"
        "github.com/aws/aws-sdk-go-v2/service/s3"
    )
    func main() {
        cfg, err := config.LoadDefaultConfig(context.TODO(),
            config.WithCredentialsProvider(
                credentials.NewStaticCredentialsProvider("<access_key>", "<secret_key>", ""),
            ),
        )
        if err != nil {
            log.Fatal(err.Error())
        }
        client := s3.NewFromConfig(cfg, func(o *s3.Options) {
            o.BaseEndpoint = aws.String("<s3_domain>")
            o.Region = "<pool>"
        })
        presignClient := s3.NewPresignClient(client)
        req, err := presignClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{
            Bucket: aws.String("<bucket_name>"),
            Key:    aws.String("<path_to_object>"),
        }, s3.WithPresignExpires(<time>))
        if err != nil {
            log.Fatal(err.Error())
        }
        fmt.Println("Public link:", req.URL)
    }
    ```

    Specify:

    * `<access_key>` — the value of the **Access key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<secret_key>` — the value of the **Secret key** field from the [S3 key](/access-control/manage/edit-user-data-or-role.mdx#issue-s3-key);
    * `<s3_domain>` — [the S3 API domain](/s3/manage/domains.mdx#s3-api-domains) depending on the pool where the bucket is located;
    * `<pool>` — [the pool](/infrastructure/locations.mdx#pool) where the bucket is located;
    * `<bucket_name>` — the bucket name;
    * `<path_to_object>` — the path to the object in the bucket;
    * `<time>` — the link lifetime, for example `24*time.Hour`.
  </TabItem>
</Tabs>

### Get a permanent link via script \{#obtain-permanent-link-via-script}

<Tabs queryString="scripts">
  <TabItem value="python">
    <TabItemLabel>
      Python
    </TabItemLabel>

    Script example:

    ```python
    import boto3

    def get_public_url(bucket_uuid: str, object_key: str) -> str:
        
        return f"https://{bucket_uuid}.selstorage.ru/{object_key}"

    if __name__ == "<file_name>":
        bucket_uuid = "<uuid>"
        object_key = "<path_to_object>"
        url = get_public_url(bucket_uuid, object_key)
        print("Public URL:", url)
    ```

    Specify:

    * `<file_name>` — the Python file name;
    * `<uuid>` — the unique bucket identifier, can be viewed in [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
    * `<path_to_object>` — the path to the object in the bucket.
  </TabItem>

  <TabItem value="php">
    <TabItemLabel>
      PHP
    </TabItemLabel>

    Script example:

    ```php
    <?php
    function get_public_url(string $bucket_uuid, string $object_key): string {
        return "https://{$bucket_uuid}.selstorage.ru/{$object_key}";
    }

    $bucket_uuid = "<uuid>";
    $object_key = "<path_to_object>";

    $public_url = get_public_url($bucket_uuid, $object_key);
    echo "Public URL: " . $public_url . PHP_EOL;
    ```

    Specify:

    * `<uuid>` — the unique bucket identifier, can be viewed in [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
    * `<path_to_object>` — path to the object in the bucket.
  </TabItem>

  <TabItem value="javascript">
    <TabItemLabel>
      JavaScript
    </TabItemLabel>

    Script example:

    ```js
    function getPublicUrl(bucketUuid, objectKey) {
        return `https://${bucketUuid}.selstorage.ru/${objectKey}`;
    }

    const bucketUuid = "<uuid>";
    const objectKey = "<path_to_object>";

    const publicUrl = getPublicUrl(bucketUuid, objectKey);
    console.log("Public URL:", publicUrl);
    ```

    Specify:

    * `<uuid>` — the unique bucket identifier, can be viewed in [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
    * `<path_to_object>` — path to the object in the bucket.
  </TabItem>

  <TabItem value="java">
    <TabItemLabel>
      Java
    </TabItemLabel>

    Script example:

    ```js
    public class SelectelPublicLink {

        public static String getPublicUrl(String bucketUuid, String objectKey) {
            return "https://" + bucketUuid + ".selstorage.ru/" + objectKey;
        }

        public static void main(String[] args) {

            String bucketUuid = "<uuid>";
            String objectKey = "<path_to_object>";

            String publicUrl = getPublicUrl(bucketUuid, objectKey);
            System.out.println("Public URL: " + publicUrl);
        }
    }
    ```

    Specify:

    * `<uuid>` — the unique bucket identifier, can be viewed in [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
    * `<path_to_object>` — path to the object in the bucket.
  </TabItem>

  <TabItem value="go">
    <TabItemLabel>
      Go
    </TabItemLabel>

    Script example:

    ```go
    package main

    import (
        "fmt"
    )

    func getPublicURL(bucketUUID, objectKey string) string {
        return fmt.Sprintf("https://%s.selstorage.ru/%s", bucketUUID, objectKey)
    }

    func main() {

        bucketUUID := "<uuid>"
        objectKey := "<path_to_object>"

        publicURL := getPublicURL(bucketUUID, objectKey)
        fmt.Println("Public URL:", publicURL)
    }
    ```

    Specify:

    * `<uuid>` — the unique bucket identifier, can be viewed in [the bucket public domain](/s3/manage/domains.mdx#bucket-public-domain);
    * `<path_to_object>` — path to the object in the bucket.
  </TabItem>
</Tabs>

<Formbricks />
