diff --git a/simple-parser.cabal b/simple-parser.cabal
--- a/simple-parser.cabal
+++ b/simple-parser.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 7341b05daadfbc05dcc6e23a6a38993f95e78a160b7942b60b7d39fc93331b6e
+-- hash: f2236fd481ed5014f290a522ef1c9a4df6f488ed8ad58f0ef69aa30acef790d5
 
 name:           simple-parser
-version:        0.7.0
+version:        0.8.0
 synopsis:       Simple parser combinators
 description:    Please see the README on GitHub at <https://github.com/ejconlon/simple-parser#readme>
 category:       Parsing
@@ -29,6 +29,7 @@
 library
   exposed-modules:
       SimpleParser
+      SimpleParser.CharString
       SimpleParser.Chunked
       SimpleParser.Common
       SimpleParser.Errata
@@ -65,6 +66,7 @@
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds
   build-depends:
       base >=4.12 && <5
+    , bytestring ==0.10.*
     , containers ==0.6.*
     , errata ==0.3.*
     , list-t ==1.0.*
@@ -102,6 +104,7 @@
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       base >=4.12 && <5
+    , bytestring ==0.10.*
     , containers ==0.6.*
     , errata ==0.3.*
     , list-t ==1.0.*
diff --git a/src/SimpleParser.hs b/src/SimpleParser.hs
--- a/src/SimpleParser.hs
+++ b/src/SimpleParser.hs
@@ -4,7 +4,8 @@
 -- "SimpleParser.Parser" for the core transformer, "SimpleParser.Stream" for the source abstraction,
 -- or "SimpleParser.Input" for useful combinators.
 module SimpleParser
-  ( module SimpleParser.Chunked
+  ( module SimpleParser.CharString
+  , module SimpleParser.Chunked
   , module SimpleParser.Common
   , module SimpleParser.Explain
   , module SimpleParser.Input
@@ -16,6 +17,7 @@
   , module SimpleParser.Stream
   ) where
 
+import SimpleParser.CharString
 import SimpleParser.Chunked
 import SimpleParser.Common
 import SimpleParser.Explain
diff --git a/src/SimpleParser/CharString.hs b/src/SimpleParser/CharString.hs
new file mode 100644
--- /dev/null
+++ b/src/SimpleParser/CharString.hs
@@ -0,0 +1,84 @@
+module SimpleParser.CharString
+  ( CharString (..)
+  , LazyCharString (..)
+  , toLazyCharString
+  , toStrictCharString
+  ) where
+
+import Data.Bifunctor (second)
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as BSC
+import qualified Data.ByteString.Lazy as BSL
+import qualified Data.ByteString.Lazy.Char8 as BSLC
+import Data.Coerce (coerce)
+import Data.String (IsString)
+import qualified Data.Text.Encoding as TE
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TLE
+import SimpleParser.Chunked (Chunked (..), TextualChunked (..))
+import SimpleParser.Stream (Stream (..))
+import qualified Text.Builder as TB
+
+newtype CharString = CharString
+  { unCharString :: ByteString
+  } deriving newtype (Eq, Ord, Show, Semigroup, Monoid, IsString)
+
+newtype LazyCharString = LazyCharString
+  { unLazyCharString :: BSL.ByteString
+  } deriving newtype (Eq, Ord, Show, Semigroup, Monoid, IsString)
+
+toLazyCharString :: CharString -> LazyCharString
+toLazyCharString = undefined
+
+toStrictCharString :: LazyCharString -> CharString
+toStrictCharString = undefined
+
+instance Chunked CharString Char where
+  consChunk a = CharString . BSC.cons a . unCharString
+  unconsChunk = fmap (second CharString) . BSC.uncons . unCharString
+  tokenToChunk = CharString . BSC.singleton
+  tokensToChunk = CharString . BSC.pack
+  chunkToTokens = BSC.unpack . unCharString
+  chunkLength = BSC.length . unCharString
+  chunkEmpty = BSC.null . unCharString
+
+instance TextualChunked CharString where
+  buildChunk = TB.asciiByteString . unCharString
+  packChunk = TE.decodeLatin1 . unCharString
+  unpackChunk = CharString . TE.encodeUtf8
+
+instance Stream CharString where
+  type Chunk CharString = CharString
+  type Token CharString = Char
+
+  streamTake1 = coerce . BSC.uncons . coerce
+  streamTakeN n (CharString s)
+    | n <= 0 = Just (coerce (BSC.empty, s))
+    | BSC.null s = Nothing
+    | otherwise = Just (coerce (BSC.splitAt n s))
+  streamTakeWhile = coerce . BSC.span
+
+instance Chunked LazyCharString Char where
+  consChunk a = LazyCharString . BSLC.cons a . unLazyCharString
+  unconsChunk = fmap (second LazyCharString) . BSLC.uncons . unLazyCharString
+  tokenToChunk = LazyCharString . BSLC.singleton
+  tokensToChunk = LazyCharString . BSLC.pack
+  chunkToTokens = BSLC.unpack . unLazyCharString
+  chunkLength = fromIntegral . BSLC.length . unLazyCharString
+  chunkEmpty = BSLC.null . unLazyCharString
+
+instance TextualChunked LazyCharString where
+  buildChunk = TB.asciiByteString . BSLC.toStrict . unLazyCharString
+  packChunk = TL.toStrict . TLE.decodeLatin1 . unLazyCharString
+  unpackChunk = LazyCharString . TLE.encodeUtf8 . TL.fromStrict
+
+instance Stream LazyCharString where
+  type Chunk LazyCharString = LazyCharString
+  type Token LazyCharString = Char
+
+  streamTake1 = coerce . BSLC.uncons . coerce
+  streamTakeN n (LazyCharString s)
+    | n <= 0 = Just (coerce (BSLC.empty, s))
+    | BSLC.null s = Nothing
+    | otherwise = Just (coerce (BSLC.splitAt (fromIntegral n) s))
+  streamTakeWhile = coerce . BSLC.span
diff --git a/src/SimpleParser/Chunked.hs b/src/SimpleParser/Chunked.hs
--- a/src/SimpleParser/Chunked.hs
+++ b/src/SimpleParser/Chunked.hs
@@ -3,12 +3,17 @@
   , TextualChunked (..)
   ) where
 
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
 import Data.Foldable (toList)
 import Data.List (uncons)
 import Data.Sequence (Seq (..))
 import qualified Data.Sequence as Seq
 import Data.Text (Text)
 import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import Data.Word (Word8)
 import Text.Builder (Builder)
 import qualified Text.Builder as TB
 
@@ -31,11 +36,11 @@
 -- | Captures textual streams.
 class Chunked chunk Char => TextualChunked chunk where
   buildChunk :: chunk -> Builder
+  buildChunk = TB.text . packChunk
   packChunk :: chunk -> Text
   packChunk = TB.run . buildChunk
   unpackChunk :: Text -> chunk
-
--- TODO(ejconlon) Add instances for Strict BS, Lazy BS, and Lazy Text
+  {-# MINIMAL (buildChunk | packChunk), unpackChunk #-}
 
 instance Chunked [a] a where
   consChunk = (:)
@@ -82,3 +87,35 @@
   buildChunk = TB.text
   packChunk = id
   unpackChunk = id
+
+instance Chunked TL.Text Char where
+  consChunk = TL.cons
+  unconsChunk = TL.uncons
+  tokenToChunk = TL.singleton
+  tokensToChunk = TL.pack
+  chunkToTokens = TL.unpack
+  chunkLength = fromIntegral . TL.length
+  chunkEmpty = TL.null
+
+instance TextualChunked TL.Text where
+  buildChunk = TB.text . TL.toStrict
+  packChunk = TL.toStrict
+  unpackChunk = TL.fromStrict
+
+instance Chunked ByteString Word8 where
+  consChunk = BS.cons
+  unconsChunk = BS.uncons
+  tokenToChunk = BS.singleton
+  tokensToChunk = BS.pack
+  chunkToTokens = BS.unpack
+  chunkLength = BS.length
+  chunkEmpty = BS.null
+
+instance Chunked BSL.ByteString Word8 where
+  consChunk = BSL.cons
+  unconsChunk = BSL.uncons
+  tokenToChunk = BSL.singleton
+  tokensToChunk = BSL.pack
+  chunkToTokens = BSL.unpack
+  chunkLength = fromIntegral . BSL.length
+  chunkEmpty = BSL.null
diff --git a/src/SimpleParser/Stream.hs b/src/SimpleParser/Stream.hs
--- a/src/SimpleParser/Stream.hs
+++ b/src/SimpleParser/Stream.hs
@@ -18,12 +18,17 @@
   ) where
 
 import Data.Bifunctor (first, second)
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
 import Data.Kind (Type)
 import Data.List (foldl')
 import Data.Sequence (Seq (..))
 import qualified Data.Sequence as Seq
 import Data.Text (Text)
 import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import Data.Word (Word8)
 import SimpleParser.Chunked (Chunked (..), TextualChunked (..))
 
 -- | 'Stream' lets us peel off tokens and chunks for parsing with explicit state passing.
@@ -83,6 +88,47 @@
     | T.null s = Nothing
     | otherwise = Just (T.splitAt n s)
   streamTakeWhile = T.span
+
+  -- TODO(ejconlon) Specialize drops
+
+instance Stream TL.Text where
+  type instance Chunk TL.Text = TL.Text
+  type instance Token TL.Text = Char
+
+  streamTake1 = TL.uncons
+  streamTakeN n s
+    | n <= 0 = Just (TL.empty, s)
+    | TL.null s = Nothing
+    | otherwise = Just (TL.splitAt (fromIntegral n) s)
+  streamTakeWhile = TL.span
+
+  -- TODO(ejconlon) Specialize drops
+
+instance Stream ByteString where
+  type instance Chunk ByteString = ByteString
+  type instance Token ByteString = Word8
+
+  streamTake1 = BS.uncons
+  streamTakeN n s
+    | n <= 0 = Just (BS.empty, s)
+    | BS.null s = Nothing
+    | otherwise = Just (BS.splitAt n s)
+  streamTakeWhile = BS.span
+
+  -- TODO(ejconlon) Specialize drops
+
+instance Stream BSL.ByteString where
+  type instance Chunk BSL.ByteString = BSL.ByteString
+  type instance Token BSL.ByteString = Word8
+
+  streamTake1 = BSL.uncons
+  streamTakeN n s
+    | n <= 0 = Just (BSL.empty, s)
+    | BSL.null s = Nothing
+    | otherwise = Just (BSL.splitAt (fromIntegral n) s)
+  streamTakeWhile = BSL.span
+
+  -- TODO(ejconlon) Specialize drops
 
 -- | 'PosStream' adds position tracking to a 'Stream'.
 class Stream s => PosStream s where
