diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,16 @@
 # Revision history for bytesmith
 
+## 0.3.5.0 -- 2020-02-10
+
+* Add big-endian and little-endian `word256` and `word256Array` parsers.
+* Add `hexFixedWord64`.
+
 ## 0.3.4.0 -- 2020-02-03
+
 * Add `hexFixedWord32`.
 
 ## 0.3.3.0 -- 2020-01-22
+
 * Add `hexWord8`, `hexWord16`, and `hexFixedWord8`.
 
 ## 0.3.2.0 -- 2019-12-27
diff --git a/bytesmith.cabal b/bytesmith.cabal
--- a/bytesmith.cabal
+++ b/bytesmith.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.2
 name: bytesmith
-version: 0.3.4.0
+version: 0.3.5.0
 synopsis: Nonresumable byte parser
 description:
   Parse bytes as fast as possible. This is a nonresumable parser
diff --git a/src/Data/Bytes/Parser/BigEndian.hs b/src/Data/Bytes/Parser/BigEndian.hs
--- a/src/Data/Bytes/Parser/BigEndian.hs
+++ b/src/Data/Bytes/Parser/BigEndian.hs
@@ -24,6 +24,7 @@
   , word32
   , word64
   , word128
+  , word256
     -- * Signed
   , int8
   , int16
@@ -35,6 +36,7 @@
   , word32Array
   , word64Array
   , word128Array
+  , word256Array
   ) where
 
 import Prelude hiding (length,any,fail,takeWhile)
@@ -44,12 +46,12 @@
 import Data.Bytes.Types (Bytes(..))
 import Data.Bytes.Parser.Internal (Parser,uneffectful)
 import Data.Bytes.Parser.Internal (InternalResult(..))
-import Data.Bytes.Parser.Internal (swapArray16,swapArray32,swapArray64)
+import Data.Bytes.Parser.Internal (swapArray16,swapArray32,swapArray64,swapArray256)
 import Data.Bytes.Parser.Internal (swapArray128)
 import Data.Word (Word8,Word16,Word32,Word64)
 import Data.Int (Int8,Int16,Int32,Int64)
 import Data.Primitive (ByteArray(..),PrimArray(..))
-import Data.WideWord (Word128(Word128))
+import Data.WideWord (Word128(Word128),Word256(Word256))
 import GHC.ByteOrder (ByteOrder(LittleEndian,BigEndian),targetByteOrder)
 
 import qualified Data.Bytes as Bytes
@@ -99,6 +101,18 @@
     let r = swapArray64 bs
     pure (asWord64s r)
 
+-- | Parse an array of big-endian unsigned 256-bit words.
+word256Array ::
+     e -- ^ Error message if not enough bytes are present
+  -> Int -- ^ Number of big-endian 256-bit words to consume
+  -> Parser e s (PrimArray Word256) -- ^ Native-endian elements
+word256Array e !n = case targetByteOrder of
+  BigEndian -> fmap (asWord256s . Bytes.toByteArrayClone) (P.take e (n * 32))
+  LittleEndian -> do
+    bs <- P.take e (n * 32)
+    let r = swapArray256 bs
+    pure (asWord256s r)
+
 -- | Parse an array of big-endian unsigned 128-bit words.
 word128Array ::
      e -- ^ Error message if not enough bytes are present
@@ -123,6 +137,9 @@
 asWord128s :: ByteArray -> PrimArray Word128
 asWord128s (ByteArray x) = PrimArray x
 
+asWord256s :: ByteArray -> PrimArray Word256
+asWord256s (ByteArray x) = PrimArray x
+
 -- | Unsigned 16-bit word.
 word16 :: e -> Parser e s Word16
 word16 e = uneffectful $ \chunk -> if length chunk >= 2
@@ -181,6 +198,10 @@
 -- | Unsigned 128-bit word.
 word128 :: e -> Parser e s Word128
 word128 e = liftA2 Word128 (word64 e) (word64 e)
+
+-- | Unsigned 256-bit word.
+word256 :: e -> Parser e s Word256
+word256 e = (\a b c d -> Word256 a b c d) <$> word64 e <*> word64 e <*> word64 e <*> word64 e
 
 -- | Signed 8-bit integer.
 int8 :: e -> Parser e s Int8
diff --git a/src/Data/Bytes/Parser/Internal.hs b/src/Data/Bytes/Parser/Internal.hs
--- a/src/Data/Bytes/Parser/Internal.hs
+++ b/src/Data/Bytes/Parser/Internal.hs
@@ -38,6 +38,7 @@
   , swapArray32
   , swapArray64
   , swapArray128
+  , swapArray256
   ) where
 
 import Prelude hiding (length,any,fail,takeWhile)
@@ -262,6 +263,23 @@
           PM.writeByteArray dst (ixDst + 14) v1
           PM.writeByteArray dst (ixDst + 15) v0
           go (ixSrc + 16) (ixDst + 16) (len - 16)
+        else pure ()
+  go offset 0 length
+  PM.unsafeFreezeByteArray dst
+
+swapArray256 :: Bytes -> ByteArray
+swapArray256 (Bytes{array,offset,length}) = runByteArrayST $ do
+  dst <- PM.newByteArray length
+  let go !ixSrc !ixDst !len = if len > 0
+        then do
+          let loop !i
+                | i < 32 = do
+                    let v = PM.indexByteArray array (ixSrc + i) :: Word8
+                    PM.writeByteArray dst (ixDst + (31 - i)) v
+                    loop (i + 1)
+                | otherwise = pure ()
+          loop 0
+          go (ixSrc + 32) (ixDst + 32) (len - 32)
         else pure ()
   go offset 0 length
   PM.unsafeFreezeByteArray dst
diff --git a/src/Data/Bytes/Parser/Latin.hs b/src/Data/Bytes/Parser/Latin.hs
--- a/src/Data/Bytes/Parser/Latin.hs
+++ b/src/Data/Bytes/Parser/Latin.hs
@@ -73,6 +73,7 @@
   , hexFixedWord8
   , hexFixedWord16
   , hexFixedWord32
+  , hexFixedWord64
     -- *** Digit
   , hexNibbleLower
   , tryHexNibbleLower
@@ -895,6 +896,9 @@
     else (# | (# (), unI (offset c + 1), unI (length c - 1) #) #)
 
 
+-- | Parse exactly eight ASCII-encoded characters, interpreting them as the
+-- hexadecimal encoding of a 32-bit number. Note that this rejects a sequence
+-- such as @BC5A9@, requiring @000BC5A9@ instead. This is insensitive to case.
 hexFixedWord32 :: e -> Parser e s Word32
 {-# inline hexFixedWord32 #-}
 hexFixedWord32 e = Parser
@@ -931,7 +935,36 @@
            | otherwise -> (# e | #)
   else (# e | #)
 
--- | Parse exactly four ASCII-encoded characters, interpretting
+-- | Parse exactly 16 ASCII-encoded characters, interpreting them as the
+-- hexadecimal encoding of a 64-bit number. Note that this rejects a sequence
+-- such as @BC5A9@, requiring @00000000000BC5A9@ instead. This is insensitive
+-- to case.
+hexFixedWord64 :: e -> Parser e s Word64
+{-# inline hexFixedWord64 #-}
+hexFixedWord64 e = Parser
+  (\x s0 -> case runParser (hexFixedWord64# e) x s0 of
+    (# s1, r #) -> case r of
+      (# err | #) -> (# s1, (# err | #) #)
+      (# | (# a, b, c #) #) -> (# s1, (# | (# W64# a, b, c #) #) #)
+  )
+
+hexFixedWord64# :: e -> Parser e s Word#
+{-# noinline hexFixedWord64# #-}
+hexFixedWord64# e = uneffectfulWord# $ \chunk -> if length chunk >= 16
+  then
+    let go !off !len !acc = case len of
+          0 -> case acc of
+            W# r -> 
+              (# | (# r
+              ,  unI off
+              ,  unI (length chunk) -# 16# #) #)
+          _ -> case oneHexMaybe (PM.indexByteArray (array chunk) off) of
+            Nothing -> (# e | #)
+            Just w -> go (off + 1) (len - 1) ((acc * 16) + w)
+     in go (offset chunk) (16 :: Int) (0 :: Word)
+  else (# e | #)
+
+-- | Parse exactly four ASCII-encoded characters, interpreting
 -- them as the hexadecimal encoding of a 16-bit number. Note that
 -- this rejects a sequence such as @5A9@, requiring @05A9@ instead.
 -- This is insensitive to case. This is particularly useful when
diff --git a/src/Data/Bytes/Parser/LittleEndian.hs b/src/Data/Bytes/Parser/LittleEndian.hs
--- a/src/Data/Bytes/Parser/LittleEndian.hs
+++ b/src/Data/Bytes/Parser/LittleEndian.hs
@@ -25,6 +25,7 @@
   , word32
   , word64
   , word128
+  , word256
     -- ** Signed
   , int8
   , int16
@@ -36,6 +37,7 @@
   , word32Array
   , word64Array
   , word128Array
+  , word256Array
     -- ** Unsigned
   , int64Array
   ) where
@@ -49,10 +51,10 @@
 import Data.Bytes.Parser.Internal (Parser,uneffectful)
 import Data.Bytes.Parser.Internal (InternalResult(..))
 import Data.Bytes.Parser.Internal (swapArray16,swapArray32)
-import Data.Bytes.Parser.Internal (swapArray64,swapArray128)
+import Data.Bytes.Parser.Internal (swapArray64,swapArray128,swapArray256)
 import Data.Word (Word8,Word16,Word32,Word64)
 import Data.Int (Int8,Int16,Int32,Int64)
-import Data.WideWord (Word128(Word128))
+import Data.WideWord (Word128(Word128),Word256(Word256))
 import GHC.ByteOrder (ByteOrder(LittleEndian,BigEndian),targetByteOrder)
 
 import qualified Data.Bytes as Bytes
@@ -114,6 +116,18 @@
     let r = swapArray128 bs
     pure (asWord128s r)
 
+-- | Parse an array of little-endian unsigned 256-bit words.
+word256Array ::
+     e -- ^ Error message if not enough bytes are present
+  -> Int -- ^ Number of little-endian 256-bit words to consume
+  -> Parser e s (PrimArray Word256) -- ^ Native-endian elements
+word256Array e !n = case targetByteOrder of
+  LittleEndian -> fmap (asWord256s . Bytes.toByteArrayClone) (P.take e (n * 32))
+  BigEndian -> do
+    bs <- P.take e (n * 32)
+    let r = swapArray256 bs
+    pure (asWord256s r)
+
 -- | Parse an array of little-endian signed 64-bit words.
 int64Array ::
      e -- ^ Error message if not enough bytes are present
@@ -135,6 +149,9 @@
 asWord128s :: ByteArray -> PrimArray Word128
 asWord128s (ByteArray x) = PrimArray x
 
+asWord256s :: ByteArray -> PrimArray Word256
+asWord256s (ByteArray x) = PrimArray x
+
 -- | Unsigned 16-bit word.
 word16 :: e -> Parser e s Word16
 word16 e = uneffectful $ \chunk -> if length chunk >= 2
@@ -189,6 +206,10 @@
           )
           (offset chunk + 8) (length chunk - 8)
   else InternalFailure e
+
+-- | Unsigned 256-bit word.
+word256 :: e -> Parser e s Word256
+word256 e = (\d c b a -> Word256 a b c d) <$> word64 e <*> word64 e <*> word64 e <*> word64 e
 
 -- | Unsigned 128-bit word.
 word128 :: e -> Parser e s Word128
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -105,6 +105,19 @@
       P.parseBytes (replicateM (length xs) (BigEndian.word128 ())) bs
       ===
       P.parseBytes (fmap Exts.toList (BigEndian.word128Array () (length xs))) bs
+  , testCase "big-endian-word256" $
+      P.parseBytesMaybe (BigEndian.word256Array () 1) (Exts.fromList [
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12,
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12, 0x34, 0x56, 0x78, 0x90,
+        0x12
+      ])
+      @=?
+      Just (Exts.fromList [0x1234567890123456789012345678901212345678901234567890123456789012])
   , testProperty "big-endian-word64" bigEndianWord64
   , testProperty "big-endian-word32" bigEndianWord32
   , testProperty "little-endian-word32" littleEndianWord32
@@ -338,6 +351,12 @@
         P.parseBytes (Latin.hexFixedWord32 ()) (bytes "") @=? P.Failure ()
     , testCase "D" $
         P.parseBytes (Latin.hexFixedWord32 ()) (bytes "A!A0A0A0") @=? P.Failure ()
+    ]
+  , testGroup "hexFixedWord64"
+    [ testCase "A" $
+        P.parseBytes (Latin.hexFixedWord64 ()) (bytes "ABCD01235678BCDE")
+        @=? P.Success
+        (Slice 17 0 0xABCD01235678BCDE)
     ]
   ]
 
