Library / SDK
minio/minio-java avatar
minio/minio-java

minio-java: an S3 client for MinIO and compatible stores

MinIO Client SDK for Java

1,311 stars522 forksJavaApache-2.0

At a glance

What is it?
The MinIO Java SDK is a client for Simple Storage Service, that is S3, bucket and object operations against any Amazon S3 compatible object storage service, built around one builder style Args class per operation. The examples directory in the repository is the real API documentation, and the 9.0.x line is where the recent security and bug fix releases have landed.
Who is it for?
Adopt minio-java if you are writing Java against MinIO or another S3 compatible store and you want one small dependency and a builder shaped API for every operation. Do not adopt it if you need features that only a cloud provider's own SDK exposes, or if your application is not in Java.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 26 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One client for S3 compatible object storage

The README describes the project as the MinIO Java SDK for Amazon S3 Compatible Cloud Storage, and the package description is more precise: it is a Simple Storage Service, that is S3, client to perform bucket and object operations to any Amazon S3 compatible object storage service.

The word that carries the weight is any. This is not a client that only works against a MinIO server, it is a client for the S3 API as it is implemented by MinIO, which means the same code can talk to a MinIO deployment, to a serverless bucket service, or to another implementation of the same interface. For a team that runs its own storage and wants to be able to move, that portability is the point of the library rather than a side effect.

The minimum requirement is Java 1.8 or above, which is a deliberately low floor and means the SDK drops into an older service without a language upgrade.

The scope is bucket and object operations, and the repository shows how wide that is in practice. There are adminapi/ and api/ directories for the two client surfaces, a functional/ directory for the functional tests, a docs/ directory, and an examples/ directory that contains one small program per operation, among them BucketExists, ComposeObject, CopyObject, DownloadObject, GetObject, and the whole family of bucket configuration calls such as DeleteBucketCors, DeleteBucketEncryption, DeleteBucketLifecycle, DeleteBucketNotification, DeleteBucketPolicy, DeleteBucketReplication, DeleteBucketTags, plus GetBucketVersioning, GetObjectAcl, EnableObjectLegalHold and DisableObjectLegalHold.

The licence is Apache-2.0, the last push was on 2026-09-27, and the recent releases are 9.0.1 on 2026-05-19, 9.0.2 on 2026-06-10 and 9.0.3 on 2026-06-12.

Maven, Gradle or a plain JAR, all on one version

The installation section gives three ways in, and the numbers are the same in all of them.

For Maven:

xml
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>9.0.3</version>
</dependency>

For Gradle:

text
dependencies {
    implementation("io.minio:minio:9.0.3")
}

And the latest JAR can be downloaded directly from the Maven Central repository, with the README linking the 9.0.3 directory.

The fact that all three paths agree on 9.0.3 is a small quality signal, because the third path is the one most likely to drift, and the compile and run commands in the quick start use the same version in the file name, minio-9.0.3-all.jar.

The all jar is worth understanding. It is a bundle with the dependencies included, which is what makes the two command line steps work without a classpath listing every transitive dependency. It is convenient for a quick test and for a container image, and it is larger than the plain artifact, so a build that uses a dependency manager would use the Maven or Gradle coordinates instead.

The README also points to a Java Client API Reference, to Javadoc at minio-java.min.io, and to the examples on a release branch rather than on master, which is a detail worth noticing when you are reading the source.

One Args class per operation, built with a builder

The API shape is visible in the quick start, and it is the same for every call.

Every operation takes an Args object, and every Args object is created with a builder. bucketExists takes a BucketExistsArgs, makeBucket takes a MakeBucketArgs, uploadObject takes an UploadObjectArgs, and each of those is built with a fluent call and a trailing build(). The repository documents the convention in a file named arg-class-structure.md, and there is a separate spotbugs-filter.xml for the static analysis of the result.

java
boolean found =
    minioClient.bucketExists(BucketExistsArgs.builder().bucket("asiatrip").build());
if (!found) {
  minioClient.makeBucket(MakeBucketArgs.builder().bucket("asiatrip").build());
}

The reason for the pattern is that the operation surface is wide. A call like uploadObject needs a bucket, an object name, a file name, and a set of optional behaviours such as part size, content type and metadata, and a builder with named setters makes each of those explicit at the call site instead of a positional argument list that changes meaning as the API grows.

The client itself is created the same way, with a builder:

java
MinioClient minioClient =
    MinioClient.builder()
        .endpoint("https://play.min.io")
        .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
        .build();

The endpoint, the access key and the secret key are the three things the README says you need in order to connect, and the endpoint is the URL to the S3 service, the access key is the user ID of an account in the S3 service and the secret key is its password.

The FileUploader example, end to end

The quick start example is a complete program, and it is the best short introduction to the library because it shows the whole shape: connect, check, create, upload, report.

java
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import io.minio.errors.MinioException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class FileUploader {
  public static void main(String[] args)
      throws IOException, NoSuchAlgorithmException, InvalidKeyException {
    try {
      MinioClient minioClient =
          MinioClient.builder()
              .endpoint("https://play.min.io")
              .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")
              .build();

      boolean found =
          minioClient.bucketExists(BucketExistsArgs.builder().bucket("asiatrip").build());
      if (!found) {
        minioClient.makeBucket(MakeBucketArgs.builder().bucket("asiatrip").build());
      } else {
        System.out.println("Bucket 'asiatrip' already exists.");
      }

      minioClient.uploadObject(
          UploadObjectArgs.builder()
              .bucket("asiatrip")
              .object("asiaphotos-2015.zip")
              .filename("/home/user/Photos/asiaphotos.zip")
              .build());
    } catch (MinioException e) {
      System.out.println("Error occurred: " + e);
      System.out.println("HTTP trace: " + e.httpTrace());
    }
  }
}

Three things are worth drawing out. The idempotency check comes first, because a bucket that already exists is not an error. The upload names a local file with filename and a destination object with object, which are different things, and the two are easy to confuse. And the catch is on MinioException, and it prints e.httpTrace(), which is the request and response trace for the failed call, and for an object store that is often the only way to see what the server actually said.

The example runs against the MinIO server playground at play.min.io, which the README says is free to use for test and development, and it compiles and runs with two commands:

sh
$ javac -cp minio-9.0.3-all.jar FileUploader.java
$ java -cp minio-9.0.3-all.jar:. FileUploader

The last line of the example output is the confirmation, and the README then verifies the result with the mc client, listing the bucket contents.

The examples directory is the practical API reference

The Javadoc and the API Reference on the MinIO documentation site are the formal documentation, but the repository's own examples directory is the more useful thing for a new user, and the README points at it in more than one place.

The structure of that directory is the point. There is one file per operation, with a descriptive name, and the names cover both sides of the API. The reads and writes are there, GetObject, DownloadObject, CopyObject, ComposeObject, DeleteObject and the uploads, and alongside them sit the configuration calls that a storage service exposes, DeleteBucketCors, GetBucketCors, DeleteBucketReplication, GetBucketReplication, DeleteBucketNotification, GetBucketNotification, DeleteBucketEncryption, GetBucketEncryption, DeleteBucketPolicy, GetBucketPolicy, DeleteBucketLifecycle, GetBucketLifecycle, DeleteBucketTags, GetBucketTags, GetBucketVersioning and GetObjectAcl, along with the object lock and legal hold operations.

Reading one file per operation is a better way to learn the API than reading a class hierarchy, because the file shows the Args class, the builder calls and the error handling for exactly one thing.

The repository also has a build.gradle with a gradlew wrapper, a settings.gradle, a functional/ directory, a MAINTAINERS.md, a README_zh_CN.md and a CLAUDE.md, so the project is set up for both automated checks and contributions. The contributor guide is linked at the release branch rather than master, which is worth noting if you are comparing what the README says with what is in the tree on the default branch.

Where minio-java is the wrong tool

The limits are ordinary and mostly about fit.

The first is that it is a client for one API family. It performs bucket and object operations against S3 compatible storage, and it does not implement anything above that layer, so a file transfer workflow, a lifecycle policy engine or a data pipeline is not something this library provides. If the requirement is to move petabytes between storage accounts, that is a different tool and a different design.

The second is the version coupling to the server. The library tracks the behaviour of the S3 implementation it is written against, and the release history shows how that works in practice. The three most recent releases are 9.0.1 on 2026-05-19, 9.0.2 on 2026-06-10 and 9.0.3 on 2026-06-12, and the last is described as a security and bug fix release. Two patch releases in two days with a security fix in the second of them is a normal pattern for a client that has to match a server, and it means you should track the releases rather than pinning an old version and hoping.

The third is the credential handling, and the example shows the shape of the risk. The access key and the secret key are in the source of the example program, against the public playground. In a real application they belong in the environment or in a secret store, and the example is not a place to copy from on that point.

The fourth is the language. This is a Java SDK, and if the rest of your platform is not Java then it is the wrong artefact for the job, whatever the API looks like.

And the fifth is the obvious one. If you are talking to object storage from a language with a first party S3 client that already does signing, retries and multipart uploads for you, the case for a second client has to be made on something else, such as one API across several storage backends.

Editorial conclusion

Adopt minio-java if you are writing Java against MinIO or another S3 compatible store and you want one small dependency and a builder shaped API for every operation. Do not adopt it if you need features that only a cloud provider's own SDK exposes, or if your application is not in Java. Verify first that the version you depend on matches the server you talk to, that the credential handling suits your deployment, since the example embeds an access key and secret key in the source, and that the operation you need actually has an example in the examples/ directory, because that directory is where the API is effectively documented.

Frequently asked questions

How do I add the minio-java SDK to my project?

With Maven, add the io.minio:minio:9.0.3 dependency, with Gradle, use implementation("io.minio:minio:9.0.3"), or download the JAR from the Maven Central repository. The minimum requirement is Java 1.8 or above.

What do I need to connect minio-java to a server?

Three things, according to the README: the endpoint, which is the URL to the S3 service, the access key, which is the user ID of an account in the S3 service, and the secret key, which is the password of that account. The quick start example uses the MinIO server playground at play.min.io.

How are minio-java operations called?

Each operation takes an Args object built with a builder, so bucketExists takes a BucketExistsArgs, makeBucket takes a MakeBucketArgs and uploadObject takes an UploadObjectArgs, each created with the matching builder and a trailing build() call. The repository documents the convention in arg-class-structure.md.

Where can I find examples for specific minio-java operations?

The examples/ directory of the repository holds one small program per operation, such as BucketExists, ComposeObject, CopyObject, DownloadObject, GetObject and the bucket configuration calls. The README also links the Java Client API Reference, the Javadoc and the minio-java-rest-example application.

Official sources

  1. License: Apache-2.0
  2. minio/minio-java on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/minio-minio-java.svg)](https://hysenlabs.com/projects/minio-minio-java)

Was this useful?