diff --git a/Aws.hs b/Aws.hs
--- a/Aws.hs
+++ b/Aws.hs
@@ -58,6 +58,7 @@
 , loadCredentialsFromEnvOrFile
 , loadCredentialsFromEnvOrFileOrInstanceMetadata
 , loadCredentialsDefault
+, anonymousCredentials
 )
 where
 
diff --git a/Aws/Core.hs b/Aws/Core.hs
--- a/Aws/Core.hs
+++ b/Aws/Core.hs
@@ -84,6 +84,7 @@
 , loadCredentialsFromEnvOrFile
 , loadCredentialsFromEnvOrFileOrInstanceMetadata
 , loadCredentialsDefault
+, anonymousCredentials
   -- * Service configuration
 , DefaultServiceConfiguration(..)
   -- * HTTP types
@@ -262,9 +263,11 @@
       , v4SigningKeys :: IORef [V4Key]
         -- | Signed IAM token
       , iamToken :: Maybe B.ByteString
+        -- | Set when the credentials are intended for anonymous access.
+      , isAnonymousCredentials :: Bool
       }
 instance Show Credentials where
-    show c = "Credentials{accessKeyID=" ++ show (accessKeyID c) ++ ",secretAccessKey=" ++ show (secretAccessKey c) ++ ",iamToken=" ++ show (iamToken c) ++ "}"
+    show c@(Credentials {}) = "Credentials{accessKeyID=" ++ show (accessKeyID c) ++ ",secretAccessKey=" ++ show (secretAccessKey c) ++ ",iamToken=" ++ show (iamToken c) ++ "}"
 
 makeCredentials :: MonadIO io
                 => B.ByteString -- ^ AWS Access Key ID
@@ -273,6 +276,7 @@
 makeCredentials accessKeyID secretAccessKey = liftIO $ do
     v4SigningKeys <- newIORef []
     let iamToken = Nothing
+    let isAnonymousCredentials = False
     return Credentials { .. }
 
 -- | The file where access credentials are loaded, when using 'loadCredentialsDefault'.
@@ -350,7 +354,8 @@
               return (Credentials <$> (T.encodeUtf8 . T.pack <$> keyID)
                                   <*> (T.encodeUtf8 . T.pack <$> secret)
                                   <*> return ref
-                                  <*> (Just . T.encodeUtf8 . T.pack <$> token))
+                                  <*> (Just . T.encodeUtf8 . T.pack <$> token)
+                                  <*> return False)
           Nothing -> return Nothing
 
 -- | Load credentials from environment variables if possible, or alternatively from a file with a given key name.
@@ -393,6 +398,13 @@
   case mfile of
       Just file -> loadCredentialsFromEnvOrFileOrInstanceMetadata file credentialsDefaultKey
       Nothing   -> loadCredentialsFromEnv
+
+-- | Make a dummy Credentials that can be used to access some AWS services
+-- anonymously.
+anonymousCredentials :: MonadIO io => io Credentials
+anonymousCredentials = do
+  cr <- makeCredentials mempty mempty
+  return (cr { isAnonymousCredentials = True })
 
 -- | Protocols supported by AWS. Currently, all AWS services use the HTTP or HTTPS protocols.
 data Protocol
diff --git a/Aws/Iam/Internal.hs b/Aws/Iam/Internal.hs
--- a/Aws/Iam/Internal.hs
+++ b/Aws/Iam/Internal.hs
@@ -19,7 +19,7 @@
 import           Control.Monad.Trans.Resource (MonadThrow)
 import           Data.ByteString     (ByteString)
 import           Data.Maybe
-import           Data.Monoid         ((<>))
+import           Data.Monoid
 import           Prelude
 import           Data.Text           (Text)
 import qualified Data.Text           as Text
diff --git a/Aws/S3/Commands/DeleteObjects.hs b/Aws/S3/Commands/DeleteObjects.hs
--- a/Aws/S3/Commands/DeleteObjects.hs
+++ b/Aws/S3/Commands/DeleteObjects.hs
@@ -14,7 +14,8 @@
 import           Text.XML.Cursor      (($/), (&|))
 import qualified Data.ByteString.Char8 as B
 import           Data.ByteString.Char8 ({- IsString -})
-import           Control.Applicative     ((<$>))
+import           Control.Applicative
+import           Prelude
 
 data DeleteObjects
     = DeleteObjects {
diff --git a/Aws/S3/Commands/GetObject.hs b/Aws/S3/Commands/GetObject.hs
--- a/Aws/S3/Commands/GetObject.hs
+++ b/Aws/S3/Commands/GetObject.hs
@@ -83,7 +83,7 @@
 
 instance ResponseConsumer GetObject GetObjectResponse where
     type ResponseMetadata GetObjectResponse = S3Metadata
-    responseConsumer httpReq GetObject{..} metadata resp
+    responseConsumer httpReq GetObject{} metadata resp
         | status == HTTP.status200 = do
             rsp <- s3BinaryResponseConsumer return metadata resp
             om <- parseObjectMetadata (HTTP.responseHeaders resp)
diff --git a/Aws/S3/Commands/HeadObject.hs b/Aws/S3/Commands/HeadObject.hs
--- a/Aws/S3/Commands/HeadObject.hs
+++ b/Aws/S3/Commands/HeadObject.hs
@@ -60,7 +60,7 @@
 
 instance ResponseConsumer HeadObject HeadObjectResponse where
     type ResponseMetadata HeadObjectResponse = S3Metadata
-    responseConsumer httpReq HeadObject{..} _ resp
+    responseConsumer httpReq HeadObject{} _ resp
         | status == HTTP.status200 = HeadObjectResponse . Just <$> parseObjectMetadata headers
         | status == HTTP.status404 = return $ HeadObjectResponse Nothing
         | otherwise = throwStatusCodeException httpReq resp
diff --git a/Aws/S3/Core.hs b/Aws/S3/Core.hs
--- a/Aws/S3/Core.hs
+++ b/Aws/S3/Core.hs
@@ -9,7 +9,7 @@
 import           Data.Char                      (isAscii, isAlphaNum, toUpper, ord)
 import           Data.Conduit                   ((.|))
 import           Data.Function
-import           Data.Functor                   ((<$>))
+import           Data.Functor
 import           Data.IORef
 import           Data.List
 import           Data.Maybe
@@ -230,7 +230,12 @@
       , sqStringToSign = stringToSign
       }
     where
-      amzHeaders = merge $ sortBy (compare `on` fst) (s3QAmzHeaders ++ (fmap (\(k, v) -> (CI.mk k, v)) iamTok))
+      -- This also implements anonymous queries.
+      isanon = isAnonymousCredentials signatureCredentials 
+      amzHeaders = merge $ sortBy (compare `on` fst) $ s3QAmzHeaders ++ 
+        if isanon 
+          then []
+          else fmap (\(k, v) -> (CI.mk k, v)) iamTok
           where merge (x1@(k1,v1):x2@(k2,v2):xs) | k1 == k2  = merge ((k1, B8.intercalate "," [v1, v2]) : xs)
                                                  | otherwise = x1 : merge (x2 : xs)
                 merge xs = xs
@@ -278,30 +283,36 @@
                        ]
           where amzHeader (k, v) = Blaze.copyByteString (CI.foldedCase k) `mappend` Blaze8.fromChar ':' `mappend` Blaze.copyByteString v
       (authorization, authQuery) = case ti of
-                                 AbsoluteTimestamp _ -> (Just $ return $ B.concat ["AWS ", accessKeyID signatureCredentials, ":", sig], [])
+                                 AbsoluteTimestamp _
+                                        | isanon -> (Nothing, [])
+                                        | otherwise -> (Just $ return $ B.concat ["AWS ", accessKeyID signatureCredentials, ":", sig], [])
                                  AbsoluteExpires time -> (Nothing, HTTP.toQuery $ makeAuthQuery time)
       makeAuthQuery time
-          = [("Expires" :: B8.ByteString, fmtTimeEpochSeconds time)
-            , ("AWSAccessKeyId", accessKeyID signatureCredentials)
-            , ("SignatureMethod", "HmacSHA256")
-            , ("Signature", sig)] ++ iamTok
-s3SignQuery S3Query{..} S3Configuration{ s3SignVersion = S3SignV4 signpayload, .. } sd@SignatureData{..}
-    = SignedQuery
-    { sqMethod = s3QMethod
-    , sqProtocol = s3Protocol
-    , sqHost = B.intercalate "." $ catMaybes host
-    , sqPort = s3Port
-    , sqPath = mconcat $ catMaybes path
-    , sqQuery = queryString ++ signatureQuery :: HTTP.Query
-    , sqDate = Just signatureTime
-    , sqAuthorization = authorization
-    , sqContentType = s3QContentType
-    , sqContentMd5 = s3QContentMd5
-    , sqAmzHeaders = Map.toList amzHeaders
-    , sqOtherHeaders = s3QOtherHeaders
-    , sqBody = s3QRequestBody
-    , sqStringToSign = stringToSign
-    }
+        | isanon = []
+        | otherwise = 
+                [ ("Expires" :: B8.ByteString, fmtTimeEpochSeconds time)
+                , ("AWSAccessKeyId", accessKeyID signatureCredentials)
+                , ("SignatureMethod", "HmacSHA256")
+                , ("Signature", sig)] ++ iamTok
+s3SignQuery sq@S3Query{..} sc@S3Configuration{ s3SignVersion = S3SignV4 signpayload, .. } sd@SignatureData{..}
+    | isAnonymousCredentials signatureCredentials =
+      s3SignQuery sq (sc { s3SignVersion = S3SignV2 }) sd
+    | otherwise = SignedQuery
+      { sqMethod = s3QMethod
+      , sqProtocol = s3Protocol
+      , sqHost = B.intercalate "." $ catMaybes host
+      , sqPort = s3Port
+      , sqPath = mconcat $ catMaybes path
+      , sqQuery = queryString ++ signatureQuery :: HTTP.Query
+      , sqDate = Just signatureTime
+      , sqAuthorization = authorization
+      , sqContentType = s3QContentType
+      , sqContentMd5 = s3QContentMd5
+      , sqAmzHeaders = Map.toList amzHeaders
+      , sqOtherHeaders = s3QOtherHeaders
+      , sqBody = s3QRequestBody
+      , sqStringToSign = stringToSign
+      }
     where
         -- V4 signing
         -- * <http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html>
diff --git a/Aws/Ses/Commands/GetIdentityDkimAttributes.hs b/Aws/Ses/Commands/GetIdentityDkimAttributes.hs
--- a/Aws/Ses/Commands/GetIdentityDkimAttributes.hs
+++ b/Aws/Ses/Commands/GetIdentityDkimAttributes.hs
@@ -4,13 +4,14 @@
     , IdentityDkimAttributes(..)
     ) where
 
-import           Control.Applicative   ((<$>))
 import qualified Data.ByteString.Char8 as BS
 import           Data.Text             (Text)
 import           Data.Text             as T (toCaseFold)
 import           Data.Text.Encoding    as T (encodeUtf8)
 import           Data.Typeable
 import           Text.XML.Cursor       (laxElement, ($/), ($//), (&/), (&|))
+import           Control.Applicative
+import           Prelude
 
 import           Aws.Core
 import           Aws.Ses.Core
diff --git a/Aws/Ses/Commands/GetIdentityNotificationAttributes.hs b/Aws/Ses/Commands/GetIdentityNotificationAttributes.hs
--- a/Aws/Ses/Commands/GetIdentityNotificationAttributes.hs
+++ b/Aws/Ses/Commands/GetIdentityNotificationAttributes.hs
@@ -6,11 +6,12 @@
 
 import Data.Text (Text)
 import qualified Data.ByteString.Char8 as BS
-import Control.Applicative ((<$>))
+import Control.Applicative
 import Data.Text.Encoding as T (encodeUtf8)
 import Data.Text as T (toCaseFold)
 import Data.Typeable
 import Text.XML.Cursor (($//), ($/), (&|), laxElement)
+import Prelude
 
 import Aws.Core
 import Aws.Ses.Core
diff --git a/Aws/Ses/Commands/GetIdentityVerificationAttributes.hs b/Aws/Ses/Commands/GetIdentityVerificationAttributes.hs
--- a/Aws/Ses/Commands/GetIdentityVerificationAttributes.hs
+++ b/Aws/Ses/Commands/GetIdentityVerificationAttributes.hs
@@ -7,10 +7,11 @@
 import Data.Text (Text)
 import qualified Data.ByteString.Char8 as BS
 import Data.Maybe (listToMaybe)
-import Control.Applicative ((<$>))
+import Control.Applicative
 import Data.Text.Encoding as T (encodeUtf8)
 import Data.Typeable
 import Text.XML.Cursor (($//), ($/), (&|), laxElement)
+import Prelude
 
 import Aws.Core
 import Aws.Ses.Core
diff --git a/Aws/Ses/Commands/ListIdentities.hs b/Aws/Ses/Commands/ListIdentities.hs
--- a/Aws/Ses/Commands/ListIdentities.hs
+++ b/Aws/Ses/Commands/ListIdentities.hs
@@ -7,10 +7,11 @@
 import Data.Text (Text)
 import  qualified Data.ByteString.Char8 as BS
 import Data.Maybe (catMaybes)
-import Control.Applicative ((<$>))
+import Control.Applicative
 import Data.Text.Encoding as T (encodeUtf8)
 import Data.Typeable
 import Text.XML.Cursor (($//), (&/), laxElement)
+import Prelude
 
 import Aws.Core
 import Aws.Ses.Core
diff --git a/Aws/Ses/Commands/SendRawEmail.hs b/Aws/Ses/Commands/SendRawEmail.hs
--- a/Aws/Ses/Commands/SendRawEmail.hs
+++ b/Aws/Ses/Commands/SendRawEmail.hs
@@ -5,10 +5,11 @@
 
 import Data.Text (Text)
 import Data.Typeable
-import Control.Applicative ((<$>))
+import Control.Applicative
 import qualified Data.ByteString.Char8 as BS
 import Text.XML.Cursor (($//))
 import qualified Data.Text.Encoding as T
+import Prelude
 
 import Aws.Core
 import Aws.Ses.Core
diff --git a/Aws/Ses/Commands/SetIdentityNotificationTopic.hs b/Aws/Ses/Commands/SetIdentityNotificationTopic.hs
--- a/Aws/Ses/Commands/SetIdentityNotificationTopic.hs
+++ b/Aws/Ses/Commands/SetIdentityNotificationTopic.hs
@@ -5,10 +5,11 @@
     ) where
 
 import Data.Text (Text)
-import Control.Applicative ((<$>))
+import Control.Applicative
 import Data.Maybe (maybeToList)
 import Data.Text.Encoding as T (encodeUtf8)
 import Data.Typeable
+import Prelude
 import Aws.Core
 import Aws.Ses.Core
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+0.23 series
+-----------
+
+NOTES: 0.23 brings technically breaking changes, which should not affect
+most users. I recommend using smart constructors and {} matching syntax
+whenever possible when interacting with aws types.
+
+-   0.23
+    - Support anonymous access of S3 buckets.a
+    - [breaking change] added isAnonymousCredentials to Credentials.
+    - Support bytestring 0.11
+
 0.22 series
 -----------
 
diff --git a/aws.cabal b/aws.cabal
--- a/aws.cabal
+++ b/aws.cabal
@@ -1,5 +1,5 @@
 Name:                aws
-Version:             0.22.1
+Version:             0.23
 Synopsis:            Amazon Web Services (AWS) for Haskell
 Description:         Bindings for Amazon Web Services (AWS), with the aim of supporting all AWS services. To see a high level overview of the library, see the README at <https://github.com/aristidb/aws/blob/master/README.md>.
 Homepage:            http://github.com/aristidb/aws
@@ -19,7 +19,7 @@
 Source-repository this
   type: git
   location: https://github.com/aristidb/aws.git
-  tag: 0.22.1
+  tag: 0.23
 
 Source-repository head
   type: git
@@ -135,7 +135,7 @@
                        base64-bytestring    >= 1.0     && < 1.3,
                        blaze-builder        >= 0.2.1.4 && < 0.5,
                        byteable             == 0.1.*,
-                       bytestring           >= 0.9     && < 0.11,
+                       bytestring           >= 0.9     && < 0.12,
                        case-insensitive     >= 0.2     && < 1.3,
                        cereal               >= 0.3     && < 0.6,
                        conduit              >= 1.3     && < 1.4,
