I would like to check if a key exists in a given bucket using Java. I looked at the API but there aren't any methods that are useful. I tried to use getObject
but it threw an exception.

- 5,045
- 3
- 28
- 41

- 3,075
- 6
- 30
- 38
-
2In the future, please provide more information like what was the exception you got.. I have provided an answer based on an assumption.. – sethu Nov 29 '11 at 01:36
-
4FYI: For this question, the accepted answer is not the best answer. – malana Jun 26 '16 at 21:05
16 Answers
There's now a doesObjectExist method in the official Java API.
Enjoy!

- 5,045
- 3
- 28
- 41
-
13
-
5
-
2The right thing to do would be to make this the accepted answer but only the OP can do that. http://meta.stackexchange.com/questions/120568/is-it-possible-to-change-the-chosen-answer – malana May 27 '16 at 13:39
-
1
-
4This must do a network call, which is expensive if you have lots of objects... Too bad it can't just return null on the metadata request. – Joel Sep 07 '16 at 15:04
-
-
@JesusAlmaral It seems `AsyncTask` has to do with Android development. I'm not familiar with it but I'd be surprised if there was a connection between it and S3's `doesObjectExist`. – malana Jan 31 '17 at 14:22
-
-
This will work in PHP too, this is the [link](http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.S3ClientInterface.html#_doesObjectExist) to the SDK function, but I think that the HTTP operation that is executed is the one found in [this link](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html). An example would be like `$s3 = new S3Client( [...] ); $exist = $s3->doesObjectExist($bucket, $pathOnS3);` – UselesssCat Jul 26 '17 at 20:13
-
-
22Looks like Amazon removed `doesObjectExist` from the 2.x SDK (currently v2.3.9). – Bampfer Jan 31 '19 at 18:11
-
6
-
1The underlying implementation of doesObjectExist is almost identical to @paul-draper's answer below: https://stackoverflow.com/a/31815968/37416, so you could use this method explicitly in v2.x – Kothar Oct 12 '20 at 15:48
Update:
It seems there's a new API to check just that. See another answer in this page: https://stackoverflow.com/a/36653034/435605
Original post:
Use errorCode.equals("NoSuchKey")
try {
AmazonS3 s3 = new AmazonS3Client(new ClasspathPropertiesFileCredentialsProvider());
String bucketName = getBucketName();
s3.createBucket(bucketName);
S3Object object = s3.getObject(bucketName, getKey());
} catch (AmazonServiceException e) {
String errorCode = e.getErrorCode();
if (!errorCode.equals("NoSuchKey")) {
throw e;
}
Logger.getLogger(getClass()).debug("No such key!!!", e);
}
Note about the exception: I know exceptions should not be used for flow control. The problem is that Amazon didn't provide any api to check this flow - just documentation about the exception.

- 34,335
- 35
- 194
- 277
-
18
-
41@SimonPeck: you are right. The problem is the Amazon didn't provide any api to check this flow - just documentation about the exception. Please remove your down-vote if not up-voting it. – AlikElzin-kilaka Apr 18 '13 at 10:48
-
1This doesn't appear to be true anymore for the Java SDK. I see that my `errorMessage` is set to "Not Found", but the `errorCode` is null. – bstempi May 22 '14 at 16:18
-
4I would go for looking for the status code 404. Seems more robust than looking at a string – Oskar Kjellin Jun 23 '14 at 09:51
-
1This is so not well documented. 404 is a very generic status code. Perhaps it's returned in other cases as well? – AlikElzin-kilaka Jun 23 '14 at 10:26
-
Just a note that the error code returned by S3 is "NotFound" and not "NoSuchKey" as shown above. – rboarman Apr 17 '15 at 16:57
-
2The comment by @rboarman is incorrect - it is `NoSuchKey`. For a definitive listing of S3 error codes, see the documentation: http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html – Allen George Jul 22 '15 at 19:27
-
I just reverified that it is returning NotFound. Something else must be going on here. – rboarman Jul 22 '15 at 21:48
-
1@AllenGeorge, I just tested with the latest Java client and got StatusCode=404 and ErrorMessage="Not Found" on the AmazonServiceException. Perhaps the results differ per SDK or API version being referenced. – Brett Dec 07 '15 at 23:39
-
1s3.getObject will open a stream and the object will be downloaded from S3 bucket itself. I will not recommend this if the purpose is to only check the existence of the object. – Ashish Goel Apr 21 '16 at 10:28
-
To avoid the problem, @ashish-goel, it could be called just a s3.getObjectAcl or s3.getObjectMetadata – Wagner Tsuchiya May 09 '16 at 09:18
-
1Can the original poster of this comment please add a modification. This implementation caused a stream/http connection leak in my code. Other posters here recommend other methods, which I agree with, but if using this one, then you need to put a try with resources around s3.getObject(): ```` // the object needs closing otherwise it will leak an http connection try (S3Object object = s3.getObject(objectId.getBucket(), objectId.getKey())) { return true; } – Ashley Frieze Jul 13 '16 at 08:55
-
It seems there's a new API to check just that. See another answer in this page: http://stackoverflow.com/a/36653034/435605 – AlikElzin-kilaka Sep 11 '16 at 07:00
The right way to do it in SDK V2, without the overload of actually getting the object, is to use S3Client.headObject. Officially backed by AWS Change Log.
Example code:
public boolean exists(String bucket, String key) {
try {
HeadObjectResponse headResponse = client
.headObject(HeadObjectRequest.builder().bucket(bucket).key(key).build());
return true;
} catch (NoSuchKeyException e) {
return false;
}
}
Using the AWS SDK use the getObjectMetadata method. The method will throw an AmazonServiceException if the key doesn't exist.
private AmazonS3 s3;
...
public boolean exists(String path, String name) {
try {
s3.getObjectMetadata(bucket, getS3Path(path) + name);
} catch(AmazonServiceException e) {
return false;
}
return true;
}

- 1,257
- 2
- 19
- 35
-
3getObject throws AmazonServiceException as well, so why do two calls? Also, how do I know that the object doesn't exists from this excpetion? Perhaps it was because of another S3 error and the object is indeed found. – AlikElzin-kilaka Apr 04 '13 at 08:56
-
6
-
This method started spewing log messages whenever it doesn't find the key in recent SDK builds. – Aleksandr Dubinsky May 16 '14 at 14:22
-
1We tested 3 different methods, getObject, getObjectMetadata and listObjects, and getObjMetadata is the fastest. Makes sense as getObject includes the metadata in the response. You should still check for 404 error code. @kilaka - you obviously use this only if you want to check if a file is existent, but don't plan to download it. – Bernhard Jun 27 '14 at 14:11
-
4@AlikElzin-kilaka, because getObject() means you have to download the contents of the object, which could potentially be huge. – Jason Nichols Aug 26 '14 at 18:20
-
21@SimonPeck, it's not ideal, but when Amazon offers an appropriate exists() method, then your point is valid. – Jason Nichols Aug 26 '14 at 18:34
-
5@SimonPeck do you have an alternative in this case? This isn't blatant abuse of exceptions as program control flow... this is simple, accurate at what it does, and safe. If you take your idea to the extreme (as apparently you are if you think this code snippet is abusing exceptions), then why have exceptions at all in a language? Rather than throw an exception **to alert the program and change the program's flow**, the runtime should just terminate I suppose. – Don Cheadle Mar 06 '15 at 20:04
-
If your s3 object is not having any meta data attached to it, then getObjectMetadata will throw a 404 error even if the s3 object exists. I will not recommend this if the objective is to check the existence of the s3 object. – Ashish Goel Apr 21 '16 at 10:30
-
In Amazon Java SDK 1.10+, you can use getStatusCode()
to get the status code of the HTTP response, which will be 404 if the object does not exist.
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import org.apache.http.HttpStatus;
try {
AmazonS3 s3 = new AmazonS3Client();
ObjectMetadata object = s3.getObjectMetadata("my-bucket", "my-client");
} catch (AmazonS3Exception e) {
if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
// bucket/key does not exist
} else {
throw e;
}
}
getObjectMetadata()
consumes fewer resources, and the response doesn't need to be closed like getObject()
.
In previous versions, you can use getErrorCode()
and check for the appropriate string (depends on the version).

- 5,556
- 3
- 23
- 38

- 78,542
- 46
- 206
- 285
-
If your s3 object is not having any meta data attached to it, then getObjectMetadata will throw a 404 error even if the s3 object exists. I will not recommend this if the objective is to check the existence of the s3 object. – Ashish Goel Apr 21 '16 at 10:34
-
1@AshishGoel, there will always be metadata, if the object exists. In fact, the underlying HTTP request is simply a HEAD to the object's URL. – Paul Draper Jun 21 '16 at 19:31
Use ListObjectsRequest setting Prefix as your key.
.NET code:
public bool Exists(string key)
{
using (Amazon.S3.AmazonS3Client client = (Amazon.S3.AmazonS3Client)Amazon.AWSClientFactory.CreateAmazonS3Client(m_accessKey, m_accessSecret))
{
ListObjectsRequest request = new ListObjectsRequest();
request.BucketName = m_bucketName;
request.Prefix = key;
using (ListObjectsResponse response = client.ListObjects(request))
{
foreach (S3Object o in response.S3Objects)
{
if( o.Key == key )
return true;
}
return false;
}
}
}.

- 147
- 3
- 10
-
8WARNING! Amazon charges extra for each LIST call! This method is ok, but don't use it to check if file exists before downloading it. – user34402 Aug 05 '13 at 09:07
-
This is not a good way to get if a file exists as it gets all objects that matches the prefix. If you have multiple files that starts with the key, it will download all the objects, including the one you specified. – Crypth Sep 09 '13 at 08:02
-
Regarding cost of LIST vs GET: note that you also get charged for any data transferred out. So if it is _extremely_ unlikely that the file exists (for example, you generated a random UUID as a key and want to make sure it isn't in use already) then GET is much cheaper. But if the files are 0.5 MB and have an 11% chance of existing already, then LIST looks a little cheaper. Same if the files are 0.1 MB and have a 52% chance of existing... The larger the files, the sooner LIST becomes cheaper. But again, a common scenario is testing a newly generated UUID key, and GET is cheaper for that. – Bampfer Jan 31 '19 at 21:19
For PHP (I know the question is Java, but Google brought me here), you can use stream wrappers and file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");

- 2,123
- 1
- 21
- 22
This java code checks if the key (file) exists in s3 bucket.
public static boolean isExistS3(String accessKey, String secretKey, String bucketName, String file) {
// Amazon-s3 credentials
AWSCredentials myCredentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3Client s3Client = new AmazonS3Client(myCredentials);
ObjectListing objects = s3Client.listObjects(new ListObjectsRequest().withBucketName(bucketName).withPrefix(file));
for (S3ObjectSummary objectSummary: objects.getObjectSummaries()) {
if (objectSummary.getKey().equals(file)) {
return true;
}
}
return false;
}

- 1,360
- 3
- 14
- 24
-
2This should work, but should also be slow in cases there are thousands or files, and for each file loop would be needed. – Danijel Feb 13 '14 at 12:13
-
as @Danijel said, this will indeed determine whether or not an object of a given key exists, but to do so it must loop over potentially **tens of thousands** of objects in S3 before determining whether or not it exists – Don Cheadle Mar 06 '15 at 20:28
-
1I disagree with @Danijel and mmcrae about this being slow. The listObjects request specifies .withPrefix(file) so it should return at most the single matching file, unless there are other files whose name starts with the name of the target file. – davidwebster48 Dec 04 '15 at 01:18
-
its not good idea to download whole list to memory and then check every element - its too slow – Алексеев станислав May 06 '21 at 15:11
Break your path into bucket and object.
Testing the bucket using the method doesBucketExist
,
Testing the object using the size of the listing (0 in case not exist).
So this code will do:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();

- 859
- 1
- 7
- 20
The other answers are for AWS SDK v1. Here is a method for AWS SDK v2 (currently 2.3.9).
Note that getObjectMetadata
and doesObjectExist
methods are not currently in the v2 SDK! So those are no longer options. We are forced to use either getObject
or listObjects
.
listObjects
calls are currently 12.5 times more expensive to make than getObject
. But AWS also charges for any data downloaded, which raises the price of getObject
if the file exists. As long as the file is very unlikely to exist (for example, you have generated a new UUID key randomly and just need to double-check that it isn't taken) then calling getObject
is significantly cheaper by my calculation.
Just to be on the safe side though, I added a range()
specification to ask AWS to only send a few bytes of the file. As far as I know the SDK will always respect this and not charge you for downloading the whole file. But I haven't verified that so rely on that behavior at your own risk! (Also, I'm not sure what how range
behaves if the S3 object is 0 bytes long.)
private boolean sanityCheckNewS3Key(String bucket, String key) {
ResponseInputStream<GetObjectResponse> resp = null;
try {
resp = s3client.getObject(GetObjectRequest.builder()
.bucket(bucket)
.key(key)
.range("bytes=0-3")
.build());
}
catch (NoSuchKeyException e) {
return false;
}
catch (AwsServiceException se) {
throw se;
}
finally {
if (resp != null) {
try {
resp.close();
} catch (IOException e) {
log.warn("Exception while attempting to close S3 input stream", e);
}
}
}
return true;
}
}
Note: this code assumes s3Client
and log
are declared and initialized elsewhere. Method returns a boolean, but can throw exceptions.

- 2,120
- 16
- 25
-
Seems like now there's a `s3Client.headObject()` in V2 to do this: https://stackoverflow.com/a/56949742/9814131 , and you will check the `S3Exception`'s status code 404 to check if object exists according to github issue https://github.com/aws/aws-sdk-java-v2/issues/297 . But I guess yours are more progressive since it has as very little overhead as 0-3 bytes. – Shawn Jan 28 '20 at 21:40
As others have mentioned, for the AWS S3 Java SDK 2.10+ you can use the HeadObjectRequest object to check if there is a file in your S3 bucket. This will act like a GET request without actually getting the file.
Example code since others haven't actually added any code above:
public boolean existsOnS3 () throws Exception {
try {
S3Client s3Client = S3Client.builder ().credentialsProvider (...).build ();
HeadObjectRequest headObjectRequest = HeadObjectRequest.builder ().bucket ("my-bucket").key ("key/to/file/house.pdf").build ();
HeadObjectResponse headObjectResponse = s3Client.headObject (headObjectRequest);
return headObjectResponse.sdkHttpResponse ().isSuccessful ();
}
catch (NoSuchKeyException e) {
//Log exception for debugging
return false;
}
}

- 14,427
- 9
- 57
- 85

- 2,065
- 6
- 32
- 61
-
-
That's because the key does not exist. That is exactly what you are looking for. So handle that exception and return false for it. I've updated the code above to include the try/catch. – Navigatron Mar 13 '20 at 15:44
-
Then you don't need `headObjectResponse` at all. `throws Exception` is not needed as well. – Andrii Karaivanskyi Mar 13 '20 at 19:09
-
-
headObjectResponse.sdkHttpResponse ().isSuccessful (); is always successfull whether the file exists or no? – mark Oct 20 '20 at 19:27
-
If the object does not exist, an exception is thrown by the AWS SDK. So it should exist if it returns a value. – Navigatron Nov 02 '20 at 14:25
Using Object isting. Java function to check if specified key exist in AWS S3.
boolean isExist(String key)
{
ObjectListing objects = amazonS3.listObjects(new ListObjectsRequest().withBucketName(bucketName).withPrefix(key));
for (S3ObjectSummary objectSummary : objects.getObjectSummaries())
{
if (objectSummary.getKey().equals(key))
{
return true;
}
}
return false;
}

- 728
- 8
- 13
There is an easy way to do it using jetS3t API's isObjectInBucket() method.
Sample code:
ProviderCredentials awsCredentials = new AWSCredentials(
awsaccessKey,
awsSecretAcessKey);
// REST implementation of S3Service
RestS3Service restService = new RestS3Service(awsCredentials);
// check whether file exists in bucket
if (restService.isObjectInBucket(bucket, objectKey)) {
//your logic
}

- 541
- 5
- 8
-
It does the same get-metadata call under the hood + exception catch: http://grepcode.com/file/repo1.maven.org/maven2/net.java.dev.jets3t/jets3t/0.9.3/org/jets3t/service/StorageService.java#508 – alexandroid Sep 05 '16 at 22:57
I also faced this problem when I used
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
I got error key not found
When I hit and try
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
it worked , this code is working with 1.9 jar otherwise update to 1.11 and use doesObjectExist as said above

- 39
- 9
Alternatively you can use Minio-Java client library, its Open Source and compatible with AWS S3 API.
You can use Minio-Java StatObject.java examples for the same.
import io.minio.MinioClient;
import io.minio.errors.MinioException;
import java.io.InputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import org.xmlpull.v1.XmlPullParserException;
public class GetObject {
public static void main(String[] args)
throws NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.
// Set s3 endpoint, region is calculated automatically
MinioClient s3Client = new MinioClient("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
InputStream stream = s3Client.getObject("my-bucketname", "my-objectname");
byte[] buf = new byte[16384];
int bytesRead;
while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
System.out.println(new String(buf, 0, bytesRead));
}
stream.close();
}
}
I hope it helps.
Disclaimer : I work for Minio

- 644
- 1
- 8
- 24

- 1,944
- 1
- 12
- 20
Use the jets3t library. Its a lot more easier and robust than the AWS sdk. Using this library you can call, s3service.getObjectDetails(). This will check and retrieve only the details of the object (not the contents) of the object. It will throw a 404 if the object is missing. So you can catch that exception and deal with it in your app.
But in order for this to work, you will need to have ListBucket access for the user on that bucket. Just GetObject access will not work. The reason being, Amazon will prevent you from checking for the presence of the key if you dont have ListBucket access. Just knowing whether a key is present or not, will also suffice for malicious users in some cases. Hence unless they have ListBucket access they will not be able to do so.

- 8,181
- 7
- 39
- 65
-
6All - see an updated answer to this question below: http://stackoverflow.com/a/36653034/49678 – alexandroid Sep 05 '16 at 23:00
-
3jets3t is an old deprecated library. Instead use the aws-java-sdk. – the_storyteller Feb 12 '19 at 20:49
-
1