diff --git a/lib/src/minio.dart b/lib/src/minio.dart
index 1545b58f1de6b0d27d9bab13be548b164800205a..b203ff359985ddce671eebd4c233130619feab81 100644
--- a/lib/src/minio.dart
+++ b/lib/src/minio.dart
@@ -67,14 +67,29 @@ class Minio {
   final _regionMap = <String, String>{};
 
   /// Checks if a bucket exists.
+  ///
+  /// Returns `true` if the [bucket] exists or you don't have permission to access
+  /// it (which implies that it exists). Returns `false` only if the [bucket] does
+  /// not exist.
   Future<bool> bucketExists(String bucket) async {
     MinioInvalidBucketNameError.check(bucket);
     try {
-      await _client.request(method: 'HEAD', bucket: bucket);
+      final response = await _client.request(method: 'HEAD', bucket: bucket);
+      return (response.statusCode == 200 || response.statusCode == 403);
     } on MinioS3Error catch (e) {
       final code = e.error.code;
       if (code == 'NoSuchBucket' || code == 'NotFound') return false;
       rethrow;
+    } on StateError catch (e) {
+      // Insight from testing: in most cases, AWS S3 returns the HTTP status code
+      // 404 when a bucket does not exist. Whereas in other cases, when the bucket
+      // does not exist, S3 returns the HTTP status code 301 Redirect instead of
+      // status code 404 as officially documented. Then, this redirect response
+      // lacks the HTTP header `location` which causes this exception in Dart's
+      // HTTP library (`http_impl.dart`).
+      if (e.message == 'Response has no Location header for redirect')
+        return false;
+      rethrow;
     }
     return true;
   }