---
title: "MinIO SDK"
sidebar_label: "MinIO SDK"
sidebar_position: 15
description: "How to set up MinIO SDK and work with S3"
---

import Formbricks from '@theme/MDXComponents/Formbricks'
import GrantAccess from '@site/i18n/en/docusaurus-plugin-content-docs/current/_partials/s3/grant-access.mdx'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import {TabItemLabel} from '@selectel/docux/components'
import {CustomTable} from '@selectel/docux/components'

# MinIO SDK

[MinIO Go Client SDK](https://pkg.go.dev/github.com/minio/minio-go/v7#section-readme) is the official Go language library that allows you to work with S3-compatible storage via the Amazon S3 API ([S3 API](/api/object-storage-s3/)).

## Setting up MinIO SDK \{#configure-minio-sdk}

1. [Configure S3 access](#configure-s3-access).
2. [Install the library in your project](#install-library).
3. [Set environment variables](#set-variables).
4. [Configure the client](#configure-client).

### 1. Configure S3 access \{#configure-s3-access}

<GrantAccess />

### 2. Install the library \{#install-library}

1. Open the CLI.
2. Add the library to your project:

   ```go
   go get github.com/minio/minio-go/v7
   ```

### 3. Set environment variables \{#set-variables}

There are different ways to specify S3 keys. We recommend specifying S3 keys through environment variables rather than in the code. Learn more about other methods in the [MinIO SDK documentation](https://pkg.go.dev/github.com/minio/minio-go/v7/pkg/credentials).

<Tabs queryString="set-variables">
  <TabItem value="linux-macos" default>
    <TabItemLabel>
      Linux/macOS
    </TabItemLabel>

    1. Open the CLI.
    2. Set the variables:

       ```bash
       export AWS_ACCESS_KEY_ID=<access_key>
       export AWS_SECRET_ACCESS_KEY=<secret_key>
       ```

       Specify:

       * `<access_key>` — value of the **Access key** field from the S3 key you [received in step 1](#configure-s3-access);
       * `<secret_key>` — value of the **Secret key** field from the S3 key you [received in step 1](#configure-s3-access).
  </TabItem>

  <TabItem value="windows">
    <TabItemLabel>
      Windows
    </TabItemLabel>

    1. Open PowerShell.
    2. Set the variables:

       ```PowerShell
       $env:AWS_ACCESS_KEY_ID="<access_key>"
       $env:AWS_SECRET_ACCESS_KEY="<secret_key>"
       ```

       Specify:

       * `<access_key>` — value of the **Access key** field from the S3 key you [received in step 1](#configure-s3-access);
       * `<secret_key>` — value of the **Secret key** field from the S3 key you [received in step 1](#configure-s3-access).
  </TabItem>
</Tabs>

### 4. Configure the client \{#configure-client}

1. In your local project, open the `main.go` file.
2. Add the client initialization script:

   ```go
   package main

   import (
       "context"
       "log"
       "github.com/minio/minio-go/v7"
       "github.com/minio/minio-go/v7/pkg/credentials"
   )

   func main() {

       creds := credentials.NewEnvAWS()

       endpoint := "<s3_domain>"

       minioClient, err := minio.New(endpoint, &minio.Options{
           Creds:  creds,
           Secure: true,
       })
       if err != nil {
           log.Fatal(err)
       }

   }
   ```

   Specify `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.

## Working with MinIO SDK \{#minio-sdk-usage}

If you encounter errors when working with MinIO SDK, check the [list of possible errors](#errors).

### Get a list of buckets \{#get-bucket-list}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to get the list of buckets to the `func main()` block:

   ```go
     info, err := minioClient.ListBuckets(context.Background())
     if err != nil {
         log.Fatalf("cannot get ListBuckets: %s", err)
     }

     log.Printf("%#v\n", info)
   ```

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log" 
         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         info, err := minioClient.ListBuckets(context.Background())
         if err != nil {
             log.Fatalf("cannot get ListBuckets: %s", err)
         }

         log.Printf("%#v\n", info)

     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Create a bucket \{#create-bucket}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to create a bucket to the `func main()` block:

   ```go
   bucketName := "<bucket_name>"

   err = minioClient.MakeBucket(
       context.Background(),
       bucketName,
       minio.MakeBucketOptions{Region: "<pool>"},
   )
   if err != nil {
       exists, errBucketExists := minioClient.BucketExists(context.Background(), bucketName)
       if errBucketExists == nil && exists {
       log.Printf("Bucket %s already exists", bucketName)
       } else {
       log.Fatalf("cannot create bucket: %s", err)
       }
   } else {
       log.Printf("Bucket %s created", bucketName)
   } 
   ```

   Specify:

   * optional: `<pool>` — [pool](/infrastructure/locations.mdx#pool) in which the bucket will be created;
   * `<bucket_name>` — bucket name.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"

         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         bucketName := "bucketName"

         err = minioClient.MakeBucket(
             context.Background(),
             bucketName,
             minio.MakeBucketOptions{Region: "ru-7"},
         )
         if err != nil {
             exists, errBucketExists := minioClient.BucketExists(context.Background(), bucketName)
             if errBucketExists == nil && exists {
                 log.Printf("Bucket %s already exists", bucketName)
             } else {
                 log.Fatalf("cannot create bucket: %s", err)
             }
         } else {
             log.Printf("Bucket %s created", bucketName)
         }
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Upload an object to a bucket \{#upload-object}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to upload an object to a bucket to the `func main()` block:

   ```go
   objectName := "<object_name>"
   filePath := "<path>"
   contentType := "application/octet-stream"

   info, err := minioClient.FPutObject(
       context.Background(),
       "<bucket_name>",
       objectName,
       filePath,
       minio.PutObjectOptions{ContentType: contentType},
   )
   if err != nil {
       log.Fatalf("Error: %s", err)
   }

   log.Printf("File uploaded. Size: %d bytes", info.Size)
   ```

   Specify:

   * `<object_name>` — name the object will have in S3;
   * `<path>` — path to the file on the local device;
   * `<bucket_name>` — bucket name.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"
         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         objectName := "object-name.csv"
         filePath := "/path/file.csv"
         contentType := "application/octet-stream"

         info, err := minioClient.FPutObject(
             context.Background(),
             "bucketName",
             objectName,
             filePath,
             minio.PutObjectOptions{ContentType: contentType},
         )
         if err != nil {
             log.Fatalf("Error: %s", err)
         }

         log.Printf("File uploaded. Size: %d bytes", info.Size)
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Get a list of objects in a bucket \{#get-object-list}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to get a list of objects in a bucket to the `func main()` block:

   ```go
   objectsChan := minioClient.ListObjects(context.TODO(), "<bucket_name>", minio.ListObjectsOptions{
       Recursive: true,
   })
   for object := range objectsChan {
       log.Printf("%#v\n", object)
   }
   ```

   Specify `<bucket_name>` — bucket name.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log" 
         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         objectsChan := minioClient.ListObjects(context.TODO(), "bucketName", minio.ListObjectsOptions{
             Recursive: true,
         })
         for object := range objectsChan {
             log.Printf("%#v\n", object)
         }
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Change bucket versioning status \{#change-versioning-status}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.

2. Add the script to change the versioning status to the `func main()` block:

   ```go
   err = minioClient.SetBucketVersioning(
       context.Background(),
       "<bucket_name>",
       minio.BucketVersioningConfiguration{Status: "<status>"},
   )
   if err != nil {
       log.Fatalf("cannot enable versioning: %s", err)
   }
   log.Printf("Versioning enabled for bucket %s", "<bucket_name>") 
   ```

   Specify:

   * `<bucket_name>` — bucket name;
   * `<status>` — versioning status to set for the bucket. Possible values:

     * `Enabled` — enable versioning;
     * `Suspended` — suspend versioning.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"

         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         bucketName := "bucketName"

         err = minioClient.SetBucketVersioning(
             context.Background(),
             bucketName,
             minio.BucketVersioningConfiguration{Status: "Enabled"},
         )
         if err != nil {
             log.Fatalf("cannot enable versioning: %s", err)
         }

         log.Printf("Versioning enabled for bucket %s", bucketName)
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

3. Optionally: add the script to check the versioning status to the `func main()` block:

   ```Go
   bucketName := "<bucket_name>"

   config, err := minioClient.GetBucketVersioning(context.Background(), bucketName)
   if err != nil {
       log.Fatalf("cannot get versioning config: %s", err)
   }

   log.Printf("Versioning status: %s", config.Status)
   ```

   Specify `<bucket_name>` — bucket name.

### Get an object \{#get-object}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.

2. In the `import` block, add the `io` package:

   ```go
   import (
       "context"
       "log"
       "io" 
       "github.com/minio/minio-go/v7"
       "github.com/minio/minio-go/v7/pkg/credentials"
   )
   ```

3. Add the script to get an object to the `func main()` block:

   ```go
     object, err := minioClient.GetObject(context.TODO(), "<bucket_name>", "<object_name>", minio.GetObjectOptions{})
     if err != nil {
         log.Fatalf("cannot get object: %s", err)
     }

     log.Printf("%#v\n", object)

     byteSlice, err := io.ReadAll(object)
     if err != nil {
         log.Fatalf("Error reading from reader: %s\n", err)
     }

     log.Printf("object contains: \"%s\"", byteSlice)
   ```

   Specify:

   * `<object_name>` — object name;
   * `<bucket_name>` — bucket name.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"
         "io" 
         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         object, err := minioClient.GetObject(context.TODO(), "bucketName", "objectName", minio.GetObjectOptions{})
         if err != nil {
             log.Fatalf("cannot get object: %s", err)
         }

         log.Printf("%#v\n", object)

         byteSlice, err := io.ReadAll(object)
         if err != nil {
             log.Fatalf("Error reading from reader: %s\n", err)
         }

         log.Printf("object contains: \"%s\"", byteSlice)
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Create a temporary link to upload or download an object \{#create-temporary-link-to-upload-or-download-object}

You can create a link in a public or private bucket using a presigned URL (Presigned URL). Learn more about Presigned URLs in the [Sharing objects with presigned URLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html) section of the AWS documentation.

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.

2. In the `import` block, add the `time` package.

   ```go
   import (
       "context"
       "log"
       "time"

       "github.com/minio/minio-go/v7"
       "github.com/minio/minio-go/v7/pkg/credentials"
   )
   ```

3. Add the script to create upload and download links to the `func main()` block:

   ```go
   getURL, err := minioClient.PresignedGetObject(
       context.Background(),
       "<bucket_name>",
       "<object_name>",
       <expiry>,
       nil,
   )
   if err != nil {
       log.Fatalf("cannot generate presigned get url: %s", err)
   }
   log.Printf("Presigned GET URL: %s", getURL.String())

   putURL, err := minioClient.PresignedPutObject(
       context.Background(),
       "<bucket_name>",
       "<object_name>",
       <expiry>,
   )
   if err != nil {
       log.Fatalf("cannot generate presigned put url: %s", err)
   }
   log.Printf("Presigned PUT URL: %s", putURL.String())
   ```

   Specify:

   * `<bucket_name>` — bucket name;
   * `<object_name>` — object name;
   * `<expiry>` — link expiration time in the `<amount>*<time>` format, where:

     * `<amount>` — number of hours, minutes, or seconds the link will be valid;
     * `<time>` — time unit, possible values: `time.Hour`, `time.Minute` or `time.Second`.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"
         "time"

         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         getURL, err := minioClient.PresignedGetObject(
             context.Background(),
             "bucketName",
             "objectName",
             30*time.Hour,
             nil,
         )
         if err != nil {
             log.Fatalf("cannot generate presigned get url: %s", err)
         }
         log.Printf("Presigned GET URL: %s", getURL.String())

         putURL, err := minioClient.PresignedPutObject(
             context.Background(),
             "bucketName",
             "objectName",
             time.Hour,
         )
         if err != nil {
             log.Fatalf("cannot generate presigned put url: %s", err)
         }
         log.Printf("Presigned PUT URL: %s", putURL.String())
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Get object metadata \{#get-object-metadata}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to get object metadata to the `func main()` block:

   ```go
   info, err := minioClient.StatObject(
       context.Background(),
       "<bucket_name>",
       "<object_name>",
       minio.StatObjectOptions{},
   )
   if err != nil {
       log.Fatalf("cannot get object info: %s", err)
   }

   log.Printf("Key: %s", info.Key)
   log.Printf("Size: %d bytes", info.Size)
   log.Printf("ContentType: %s", info.ContentType)
   log.Printf("ETag: %s", info.ETag)
   log.Printf("LastModified: %s", info.LastModified)
   ```

   Specify:

   * `<bucket_name>` — bucket name;
   * `<object_name>` — object name.

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"

         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
             Creds:  creds,
             Secure: true,
         })
         if err != nil {
             log.Fatal(err)
         }

         info, err := minioClient.StatObject(
             context.Background(),
             "bucketName",
             "objectName",
             minio.StatObjectOptions{},
         )
         if err != nil {
             log.Fatalf("cannot get object info: %s", err)
         }

         log.Printf("Key: %s", info.Key)
         log.Printf("Size: %d bytes", info.Size)
         log.Printf("ContentType: %s", info.ContentType)
         log.Printf("ETag: %s", info.ETag)
         log.Printf("LastModified: %s", info.LastModified)
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

### Delete an object \{#delete-object}

1. Open the `main.go` file with the client you [configured in step 4](#configure-client), or create a new file and copy the client into it.
2. Add the script to delete an object to the `func main()` block:

   ```go
   err = minioClient.RemoveObject(
       context.Background(),
       "<bucket_name>",
       "<object_name>",
       minio.RemoveObjectOptions{VersionID: "<version_id>"},
   )
   if err != nil {
       log.Fatalf("cannot remove object: %s", err)
   }
   log.Printf("Object %s removed", "<object_name>") 
   ```

   Specify:

   * `<bucket_name>` — bucket name;
   * `<object_name>` — object name;
   * optional: `VersionID: "<version_id>"` — option to delete a specific version of an object if [versioning](/s3/buckets/versioning.mdx) is enabled in the bucket. Specify `<version_id>` — [version identifier](/s3/buckets/versioning.mdx#version-id).

   <details>
     <summary>Full script example</summary>

     ```go
     package main

     import (
         "context"
         "log"

         "github.com/minio/minio-go/v7"
         "github.com/minio/minio-go/v7/pkg/credentials"
     )

     func main() {

         creds := credentials.NewEnvAWS()

         endpoint := "<s3_domain>"

         minioClient, err := minio.New(endpoint, &minio.Options{
         Creds:  creds,
         Secure: true,
         })
         if err != nil {
         log.Fatal(err)
         }

         err = minioClient.RemoveObject(
         context.Background(),
         "bucketName",
         "objectName",
         minio.RemoveObjectOptions{},
         )
         if err != nil {
         log.Fatalf("cannot remove object: %s", err)
         }

         log.Printf("Object %s removed", "objectName")
     }
     ```

     Here `<s3_domain>` — [S3 API domain](/s3/manage/domains.mdx#s3-api-domains). The domain depends on the [pool](/infrastructure/locations.mdx#pool) where S3 is located.
   </details>

## Possible errors \{#errors}

<CustomTable>
  <table>
    <thead>
      <tr>
        <th>Error</th><th>Description</th><th>Solution</th>
      </tr>
    </thead>

    <tbody>
      <tr>
        <th>AccessDenied</th><td>Access denied</td><td>Check your keys, access policies, and user permissions</td>
      </tr>

      <tr>
        <th>NoSuchBucket</th><td>Bucket does not exist</td><td>Check the bucket name and the target [pool](/infrastructure/locations.mdx#pool)</td>
      </tr>

      <tr>
        <th>NoSuchKey</th><td>Object not found</td><td>Check the object name and its path in the bucket</td>
      </tr>

      <tr>
        <th>BucketAlreadyExists</th><td>A bucket with this name already exists</td><td>Specify a different name</td>
      </tr>

      <tr>
        <th>BucketNotEmpty</th><td>Bucket is not empty</td><td>Delete all objects and unfinished uploads before deleting the bucket</td>
      </tr>

      <tr>
        <th>InvalidBucketName</th><td>Invalid bucket name</td><td>Specify a name that contains only lowercase letters, numbers, dots, and hyphens</td>
      </tr>

      <tr>
        <th>connection refused</th><td>Incorrect [S3 API domain](/s3/manage/domains.mdx)</td><td>Ensure that the domain matches the [pool](/infrastructure/locations.mdx#pool) where the bucket is located</td>
      </tr>

      <tr>
        <th>SignatureDoesNotMatch</th><td>Signature does not match: invalid secret key or corrupted request headers</td><td>Use a correct secret key and check the request headers</td>
      </tr>

      <tr>
        <th>MalformedXML</th><td>Incorrect XML</td><td>Check the syntax and structure of the provided XML</td>
      </tr>

      <tr>
        <th>TooManyBuckets</th><td>Bucket limit reached. Delete unused buckets or request a quota increase</td>

        <td />
      </tr>

      <tr>
        <th>RequestTimeout</th><td>Request timeout exceeded. Check your network connection or increase the request timeout</td>

        <td />
      </tr>

      <tr>
        <th>MethodNotAllowed</th><td>An inappropriate HTTP method is used for this operation (GET/PUT/DELETE)</td>

        <td />
      </tr>
    </tbody>
  </table>
</CustomTable>

<Formbricks />
