diff --git a/flatparse.cabal b/flatparse.cabal
--- a/flatparse.cabal
+++ b/flatparse.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           flatparse
-version:        0.3.2.0
+version:        0.3.3.0
 synopsis:       High-performance parsing from strict bytestrings
 description:    @Flatparse@ is a high-performance parsing library, focusing on programming languages and
                 human-readable data formats. See the README for more information:
@@ -23,7 +23,8 @@
     GHC == 8.6.5
   , GHC == 8.8.4
   , GHC == 8.10.7
-  , GHC == 9.0.1
+  , GHC == 9.0.2
+  , GHC == 9.2.2
 extra-source-files:
     README.md
 
@@ -47,6 +48,7 @@
       FlatParse.Examples.BasicLambda.Lexer
       FlatParse.Examples.BasicLambda.Parser
       FlatParse.Internal
+      FlatParse.Internal.UnboxedNumerics
       FlatParse.Stateful
   other-modules:
       Paths_flatparse
@@ -98,6 +100,7 @@
   ghc-options: -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-binds -Wno-unused-matches -O2 -Wno-type-defaults
   build-depends:
       HUnit
+    , QuickCheck
     , base >=4.7 && <5
     , bytestring
     , flatparse
diff --git a/src/FlatParse/Basic.hs b/src/FlatParse/Basic.hs
--- a/src/FlatParse/Basic.hs
+++ b/src/FlatParse/Basic.hs
@@ -52,8 +52,15 @@
   , anyWord16_
   , anyWord32
   , anyWord32_
+  , anyWord64
+  , anyWord64_
   , anyWord
   , anyWord_
+  , anyInt8
+  , anyInt16
+  , anyInt32
+  , anyInt64
+  , anyInt
   , anyChar
   , anyChar_
   , anyCharASCII
@@ -64,6 +71,20 @@
   , FlatParse.Basic.readInt
   , FlatParse.Basic.readInteger
 
+  -- ** Explicit-endianness machine integers
+  , anyWord16le
+  , anyWord16be
+  , anyWord32le
+  , anyWord32be
+  , anyWord64le
+  , anyWord64be
+  , anyInt16le
+  , anyInt16be
+  , anyInt32le
+  , anyInt32be
+  , anyInt64le
+  , anyInt64be
+
   -- * Combinators
   , (<|>)
   , branch
@@ -115,6 +136,15 @@
   , scanBytes#
   , setBack#
 
+  , withAnyWord8#
+  , withAnyWord16#
+  , withAnyWord32#
+  , withAnyWord64#
+  , withAnyInt8#
+  , withAnyInt16#
+  , withAnyInt32#
+  , withAnyInt64#
+
   ) where
 
 import Control.Monad
@@ -125,6 +155,7 @@
 import Data.Word
 import GHC.Exts
 import GHC.Word
+import GHC.Int
 import GHC.ForeignPtr
 import Language.Haskell.TH
 import System.IO.Unsafe
@@ -135,6 +166,7 @@
 import qualified Data.Map.Strict as M
 
 import FlatParse.Internal
+import FlatParse.Internal.UnboxedNumerics
 
 --------------------------------------------------------------------------------
 
@@ -334,8 +366,8 @@
 char c = string [c]
 
 -- | Read a `Word8`.
-byte :: Word -> Parser e ()
-byte (W# w) = ensureBytes# 1 >> scan8# (W# w)
+byte :: Word8 -> Parser e ()
+byte w = ensureBytes# 1 >> scan8# w
 {-# inline byte #-}
 
 -- | Read a sequence of bytes. This is a template function, you can use it as @$(bytes [3, 4, 5])@,
@@ -507,58 +539,6 @@
 fusedSatisfy_ f1 f2 f3 f4 = () <$ fusedSatisfy f1 f2 f3 f4
 {-# inline fusedSatisfy_ #-}
 
--- | Parse any `Word8`.
-anyWord8 :: Parser e Word8
-anyWord8 = Parser \fp eob buf -> case eqAddr# eob buf of
-  1# -> Fail#
-  _  -> case indexWord8OffAddr# buf 0# of
-    w -> OK# (W8# w) (plusAddr# buf 1#)
-{-# inline anyWord8 #-}
-
--- | Skip any `Word8`.
-anyWord8_ :: Parser e ()
-anyWord8_ = () <$ anyWord8
-{-# inline anyWord8_ #-}
-
--- | Parse any `Word16`.
-anyWord16 :: Parser e Word
-anyWord16 = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWord16OffAddr buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 2#)
-{-# inline anyWord16 #-}
-
--- | Skip any `Word16`.
-anyWord16_ :: Parser e ()
-anyWord16_ = () <$ anyWord16
-{-# inline anyWord16_ #-}
-
--- | Parse any `Word32`.
-anyWord32 :: Parser e Word
-anyWord32 = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWord32OffAddr buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 4#)
-{-# inline anyWord32 #-}
-
--- | Skip any `Word32`.
-anyWord32_ :: Parser e ()
-anyWord32_ = () <$ anyWord32
-{-# inline anyWord32_ #-}
-
--- | Parse any `Word`.
-anyWord :: Parser e Word
-anyWord = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWordOffAddr# buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 8#)
-{-# inline anyWord #-}
-
--- | Skip any `Word`.
-anyWord_ :: Parser e ()
-anyWord_ = () <$ anyWord
-{-# inline anyWord_ #-}
-
 -- | Parse any UTF-8-encoded `Char`.
 anyChar :: Parser e Char
 anyChar = Parser \fp eob buf -> case eqAddr# eob buf of
@@ -902,30 +882,30 @@
 
 -- | Unsafely read a concrete byte from the input. It's not checked that the input has
 --   enough bytes.
-scan8# :: Word -> Parser e ()
-scan8# (W# c) = Parser \fp eob s ->
-  case indexWord8OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan8# :: Word8 -> Parser e ()
+scan8# (W8# c) = Parser \fp eob s ->
+  case indexWord8OffAddr# s 0# of
+    c' -> case eqWord8'# c c' of
       1# -> OK# () (plusAddr# s 1#)
       _  -> Fail#
 {-# inline scan8# #-}
 
 -- | Unsafely read two concrete bytes from the input. It's not checked that the input has
 --   enough bytes.
-scan16# :: Word -> Parser e ()
-scan16# (W# c) = Parser \fp eob s ->
-  case indexWord16OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan16# :: Word16 -> Parser e ()
+scan16# (W16# c) = Parser \fp eob s ->
+  case indexWord16OffAddr# s 0# of
+    c' -> case eqWord16'# c c' of
       1# -> OK# () (plusAddr# s 2#)
       _  -> Fail#
 {-# inline scan16# #-}
 
 -- | Unsafely read four concrete bytes from the input. It's not checked that the input has
 --   enough bytes.
-scan32# :: Word -> Parser e ()
-scan32# (W# c) = Parser \fp eob s ->
-  case indexWord32OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan32# :: Word32 -> Parser e ()
+scan32# (W32# c) = Parser \fp eob s ->
+  case indexWord32OffAddr# s 0# of
+    c' -> case eqWord32'# c c' of
       1# -> OK# () (plusAddr# s 4#)
       _  -> Fail#
 {-# inline scan32# #-}
@@ -934,15 +914,15 @@
 --   enough bytes.
 scan64# :: Word -> Parser e ()
 scan64# (W# c) = Parser \fp eob s ->
-  case indexWord64OffAddr s 0# of
+  case indexWord64OffAddr# s 0# of
     c' -> case eqWord# c c' of
       1# -> OK# () (plusAddr# s 8#)
       _  -> Fail#
 {-# inline scan64# #-}
 
 -- | Unsafely read and return a byte from the input. It's not checked that the input is non-empty.
-scanAny8# :: Parser e Word
-scanAny8# = Parser \fp eob s -> OK# (W# (indexWord8OffAddr s 0#)) (plusAddr# s 1#)
+scanAny8# :: Parser e Word8
+scanAny8# = Parser \fp eob s -> OK# (W8# (indexWord8OffAddr# s 0#)) (plusAddr# s 1#)
 {-# inline scanAny8# #-}
 
 scanPartial64# :: Int -> Word -> Parser e ()
@@ -1076,3 +1056,204 @@
       !m    = M.fromList ((Nothing, maybe (VarE 'empty) id fallback) : branches)
       !trie = compileTrie strings
   in (m , trie)
+
+--------------------------------------------------------------------------------
+
+withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a
+withAnyWord8# p = Parser \fp eob buf -> case eqAddr# eob buf of
+  1# -> Fail#
+  _  -> case indexWord8OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp eob (plusAddr# buf 1#)
+{-# inline withAnyWord8# #-}
+
+withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a
+withAnyWord16# p = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWord16OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp eob (plusAddr# buf 2#)
+{-# inline withAnyWord16# #-}
+
+withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a
+withAnyWord32# p = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWord32OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp eob (plusAddr# buf 4#)
+{-# inline withAnyWord32# #-}
+
+withAnyWord64# :: (Word# -> Parser e a) -> Parser e a
+withAnyWord64# p = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWordOffAddr# buf 0# of
+    w# -> runParser# (p w#) fp eob (plusAddr# buf 8#)
+{-# inline withAnyWord64# #-}
+
+withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a
+withAnyInt8# p = Parser \fp eob buf -> case eqAddr# eob buf of
+  1# -> Fail#
+  _  -> case indexInt8OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp eob (plusAddr# buf 1#)
+{-# inline withAnyInt8# #-}
+
+withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a
+withAnyInt16# p = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt16OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp eob (plusAddr# buf 2#)
+{-# inline withAnyInt16# #-}
+
+withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a
+withAnyInt32# p = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt32OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp eob (plusAddr# buf 4#)
+{-# inline withAnyInt32# #-}
+
+withAnyInt64# :: (Int# -> Parser e a) -> Parser e a
+withAnyInt64# p = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt64OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp eob (plusAddr# buf 8#)
+{-# inline withAnyInt64# #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Word8' (byte).
+anyWord8 :: Parser e Word8
+anyWord8 = withAnyWord8# (\w# -> pure (W8# w#))
+{-# inline anyWord8 #-}
+
+-- | Skip any 'Word8' (byte).
+anyWord8_ :: Parser e ()
+anyWord8_ = () <$ anyWord8
+{-# inline anyWord8_ #-}
+
+-- | Parse any 'Word16'.
+anyWord16 :: Parser e Word16
+anyWord16 = withAnyWord16# (\w# -> pure (W16# w#))
+{-# inline anyWord16 #-}
+
+-- | Skip any 'Word16'.
+anyWord16_ :: Parser e ()
+anyWord16_ = () <$ anyWord16
+{-# inline anyWord16_ #-}
+
+-- | Parse any 'Word32'.
+anyWord32 :: Parser e Word32
+anyWord32 = withAnyWord32# (\w# -> pure (W32# w#))
+{-# inline anyWord32 #-}
+
+-- | Skip any 'Word32'.
+anyWord32_ :: Parser e ()
+anyWord32_ = () <$ anyWord32
+{-# inline anyWord32_ #-}
+
+-- | Parse any 'Word64'.
+anyWord64 :: Parser e Word64
+anyWord64 = withAnyWord64# (\w# -> pure (W64# w#))
+{-# inline anyWord64 #-}
+
+-- | Skip any 'Word64'.
+anyWord64_ :: Parser e ()
+anyWord64_ = () <$ anyWord64
+{-# inline anyWord64_ #-}
+
+-- | Parse any 'Word'.
+anyWord :: Parser e Word
+anyWord = withAnyWord64# (\w# -> pure (W# w#))
+{-# inline anyWord #-}
+
+-- | Skip any 'Word'.
+anyWord_ :: Parser e ()
+anyWord_ = () <$ anyWord
+{-# inline anyWord_ #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Int8'.
+anyInt8 :: Parser e Int8
+anyInt8 = withAnyInt8# (\i# -> pure (I8# i#))
+{-# inline anyInt8 #-}
+
+-- | Parse any 'Int16'.
+anyInt16 :: Parser e Int16
+anyInt16 = withAnyInt16# (\i# -> pure (I16# i#))
+{-# inline anyInt16 #-}
+
+-- | Parse any 'Int32'.
+anyInt32 :: Parser e Int32
+anyInt32 = withAnyInt32# (\i# -> pure (I32# i#))
+{-# inline anyInt32 #-}
+
+-- | Parse any 'Int64'.
+anyInt64 :: Parser e Int64
+anyInt64 = withAnyInt64# (\i# -> pure (I64# i#))
+{-# inline anyInt64 #-}
+
+-- | Parse any 'Int'.
+anyInt :: Parser e Int
+anyInt = withAnyInt64# (\i# -> pure (I# i#))
+{-# inline anyInt #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Word16' (little-endian).
+anyWord16le :: Parser e Word16
+anyWord16le = anyWord16
+{-# inline anyWord16le #-}
+
+-- | Parse any 'Word16' (big-endian).
+anyWord16be :: Parser e Word16
+anyWord16be = withAnyWord16# (\w# -> pure (W16# (byteSwap16'# w#)))
+{-# inline anyWord16be #-}
+
+-- | Parse any 'Word32' (little-endian).
+anyWord32le :: Parser e Word32
+anyWord32le = anyWord32
+{-# inline anyWord32le #-}
+
+-- | Parse any 'Word32' (big-endian).
+anyWord32be :: Parser e Word32
+anyWord32be = withAnyWord32# (\w# -> pure (W32# (byteSwap32'# w#)))
+{-# inline anyWord32be #-}
+
+-- | Parse any 'Word64' (little-endian).
+anyWord64le :: Parser e Word64
+anyWord64le = anyWord64
+{-# inline anyWord64le #-}
+
+-- | Parse any 'Word64' (big-endian).
+anyWord64be :: Parser e Word64
+anyWord64be = withAnyWord64# (\w# -> pure (W64# (byteSwap# w#)))
+{-# inline anyWord64be #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Int16' (little-endian).
+anyInt16le :: Parser e Int16
+anyInt16le = anyInt16
+{-# inline anyInt16le #-}
+
+-- | Parse any 'Int16' (big-endian).
+anyInt16be :: Parser e Int16
+anyInt16be = withAnyWord16# (\w# -> pure (I16# (word16ToInt16# (byteSwap16'# w#))))
+{-# inline anyInt16be #-}
+
+-- | Parse any 'Int32' (little-endian).
+anyInt32le :: Parser e Int32
+anyInt32le = anyInt32
+{-# inline anyInt32le #-}
+
+-- | Parse any 'Int32' (big-endian).
+anyInt32be :: Parser e Int32
+anyInt32be = withAnyWord32# (\w# -> pure (I32# (word32ToInt32# (byteSwap32'# w#))))
+{-# inline anyInt32be #-}
+
+-- | Parse any 'Int64' (little-endian).
+anyInt64le :: Parser e Int64
+anyInt64le = anyInt64
+{-# inline anyInt64le #-}
+
+-- | Parse any 'Int64' (big-endian).
+anyInt64be :: Parser e Int64
+anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#))))
+{-# inline anyInt64be #-}
diff --git a/src/FlatParse/Internal.hs b/src/FlatParse/Internal.hs
--- a/src/FlatParse/Internal.hs
+++ b/src/FlatParse/Internal.hs
@@ -2,6 +2,8 @@
 
 module FlatParse.Internal where
 
+import FlatParse.Internal.UnboxedNumerics
+
 import Data.Bits
 import Data.Char
 import Data.Foldable (foldl')
@@ -31,23 +33,7 @@
 #endif
 {-# inline shortInteger #-}
 
-#if MIN_VERSION_base(4,16,0)
-indexWord8OffAddr s x = word8ToWord# (indexWord8OffAddr# s x)
-indexWord16OffAddr s x = word16ToWord# (indexWord16OffAddr# s x)
-indexWord32OffAddr s x = word32ToWord# (indexWord32OffAddr# s x)
-indexWord64OffAddr s x = indexWord64OffAddr# s x
-#else
-indexWord8OffAddr  = indexWord8OffAddr#
-indexWord16OffAddr = indexWord16OffAddr#
-indexWord32OffAddr = indexWord32OffAddr#
-indexWord64OffAddr = indexWord64OffAddr#
-#endif
-{-# inline indexWord8OffAddr #-}
-{-# inline indexWord16OffAddr #-}
-{-# inline indexWord32OffAddr #-}
-{-# inline indexWord64OffAddr #-}
 
-
 -- Char predicates
 --------------------------------------------------------------------------------
 
@@ -76,9 +62,9 @@
 readInt' :: Int# -> Addr# -> Addr# -> (# Int#, Addr# #)
 readInt' acc s end = case eqAddr# s end of
   1# -> (# acc, s #)
-  _  -> case indexWord8OffAddr s 0# of
-    w | 1# <- leWord# 48## w, 1# <- leWord# w 57## ->
-      readInt' (mul10 acc +# (word2Int# w -# 48#)) (plusAddr# s 1#) end
+  _  -> case indexWord8OffAddr''# s 0# of
+    w | 1# <- leWord8# (wordToWord8''# 0x30##) w, 1# <- leWord8# w (wordToWord8''# 0x39##) ->
+      readInt' (mul10 acc +# (word2Int# (word8ToWord''# w) -# 0x30#)) (plusAddr# s 1#) end
     _ -> (# acc, s #)
 
 
diff --git a/src/FlatParse/Internal/UnboxedNumerics.hs b/src/FlatParse/Internal/UnboxedNumerics.hs
new file mode 100644
--- /dev/null
+++ b/src/FlatParse/Internal/UnboxedNumerics.hs
@@ -0,0 +1,113 @@
+{- | Compatibility layer for numeric primops.
+
+GHC 9.2 standardized unboxed numeric primops. Prior, it was quite asymmetric.
+Many primop functions used the native unboxed numerics 'Word#' and 'Int#' even
+if a sized unboxed numeric was in the name, e.g. 'indexWord8OffAddr#' returning
+'Word#' pre-9.2. All boxed machine integers only stored 'Word#' internally!
+
+We target GHC 9.2's better handling. In order to maintain compatibility with
+older GHCs, we define missing primops and wrap ones that changed type. Usually,
+we can write a few wrappers so that 9.2 uses sized unboxed numerics everywhere,
+and pre-9.2 uses native unboxed numerics everywhere. Sometimes we really want to
+work with sized unboxed numerics on both, in which case we have to do more
+involved primop wrapping.
+
+The general pattern is as follows:
+
+  * A ticked primop means it's sized on >=9.2, native on <9.2
+  * A double-ticked primop means it's sized on all
+  * An unticked primop should mean the same as a ticked primop (no guarantees)
+
+Also see: https://gitlab.haskell.org/ghc/ghc/-/wikis/Unboxed-Numerics
+-}
+
+module FlatParse.Internal.UnboxedNumerics where
+
+import GHC.Exts
+
+-- "Switch" wrappers: sized on >=9.2, native on <9.2
+byteSwap16'# :: Word16'# -> Word16'#
+byteSwap32'# :: Word32'# -> Word32'#
+eqWord8'# :: Word8'# -> Word8'# -> Int#
+eqWord16'# :: Word16'# -> Word16'# -> Int#
+eqWord32'# :: Word32'# -> Word32'# -> Int#
+{-# inline byteSwap16'# #-}
+{-# inline byteSwap32'# #-}
+{-# inline eqWord8'#    #-}
+{-# inline eqWord16'#   #-}
+{-# inline eqWord32'#   #-}
+
+-- "Sized" wrappers: sized on all
+indexWord8OffAddr''# :: Addr# -> Int# -> Word8#
+wordToWord8''# :: Word# -> Word8#
+word8ToWord''# :: Word8# -> Word#
+{-# inline indexWord8OffAddr''#  #-}
+{-# inline wordToWord8''# #-}
+{-# inline word8ToWord''# #-}
+
+#if MIN_VERSION_base(4,16,0)
+-- GHC >=9.2
+
+type Word8'#  = Word8#
+type Word16'# = Word16#
+type Word32'# = Word32#
+type Int8'#   = Int8#
+type Int16'#  = Int16#
+type Int32'#  = Int32#
+
+-- "Switch" wrappers: sized on >=9.2, native on <9.2
+byteSwap16'# w# = wordToWord16# (byteSwap16# (word16ToWord# w#))
+byteSwap32'# w# = wordToWord32# (byteSwap32# (word32ToWord# w#))
+eqWord8'# = eqWord8#
+eqWord16'# = eqWord16#
+eqWord32'# = eqWord32#
+
+-- "Sized" wrappers: sized on all
+indexWord8OffAddr''# = indexWord8OffAddr#
+wordToWord8''# = wordToWord8#
+word8ToWord''# = word8ToWord#
+
+#else
+-- GHC <9.2
+
+type Word8'#  = Word#
+type Word16'# = Word#
+type Word32'# = Word#
+type Int8'#   = Int#
+type Int16'#  = Int#
+type Int32'#  = Int#
+
+-- "Switch" wrappers: sized on >=9.2, native on <9.2
+byteSwap16'# = byteSwap16#
+byteSwap32'# = byteSwap32#
+eqWord8'# = eqWord#
+eqWord16'# = eqWord#
+eqWord32'# = eqWord#
+
+-- No need to tick wrap these, they didn't exist <9.2
+word16ToInt16# :: Word16'# -> Int#
+word16ToInt16# w = narrow16Int# (word2Int# w)
+word32ToInt32# :: Word32'# -> Int#
+word32ToInt32# w = narrow32Int# (word2Int# w)
+{-# inline word16ToInt16# #-}
+{-# inline word32ToInt32# #-}
+
+-- "Sized" wrappers: sized on all
+indexWord8OffAddr''# a# i# = narrowWord8# (indexWord8OffAddr# a# i#)
+wordToWord8''# = narrowWord8#
+word8ToWord''# = extendWord8#
+
+#endif
+
+#if !MIN_VERSION_base(4,13,0)
+-- GHC <8.8
+
+type Word8# = Word#
+narrowWord8# :: Word# -> Word8#
+narrowWord8# = narrow8Word#
+extendWord8# :: Word# -> Word8#
+extendWord8# w# = w#
+leWord8# :: Word8# -> Word8# -> Int#
+leWord8# w1# w2# = leWord# w1# w2#
+
+#endif
diff --git a/src/FlatParse/Stateful.hs b/src/FlatParse/Stateful.hs
--- a/src/FlatParse/Stateful.hs
+++ b/src/FlatParse/Stateful.hs
@@ -58,8 +58,15 @@
   , anyWord16_
   , anyWord32
   , anyWord32_
+  , anyWord64
+  , anyWord64_
   , anyWord
   , anyWord_
+  , anyInt8
+  , anyInt16
+  , anyInt32
+  , anyInt64
+  , anyInt
   , anyChar
   , anyChar_
   , anyCharASCII
@@ -70,6 +77,20 @@
   , FlatParse.Stateful.readInt
   , FlatParse.Stateful.readInteger
 
+  -- ** Explicit-endianness machine integers
+  , anyWord16le
+  , anyWord16be
+  , anyWord32le
+  , anyWord32be
+  , anyWord64le
+  , anyWord64be
+  , anyInt16le
+  , anyInt16be
+  , anyInt32le
+  , anyInt32be
+  , anyInt64le
+  , anyInt64be
+
   -- * Combinators
   , (<|>)
   , branch
@@ -121,12 +142,23 @@
   , scanBytes#
   , setBack#
 
+  , withAnyWord8#
+  , withAnyWord16#
+  , withAnyWord32#
+  , withAnyWord64#
+  , withAnyInt8#
+  , withAnyInt16#
+  , withAnyInt32#
+  , withAnyInt64#
+
   ) where
 
 import Control.Monad
 import Data.Foldable
 import Data.Map (Map)
 import GHC.Exts
+import GHC.Word
+import GHC.Int
 import Language.Haskell.TH
 import System.IO.Unsafe
 import GHC.ForeignPtr
@@ -137,6 +169,7 @@
 import qualified Data.Map.Strict as M
 
 import FlatParse.Internal
+import FlatParse.Internal.UnboxedNumerics
 
 import qualified FlatParse.Basic as Basic
 
@@ -367,8 +400,8 @@
 char c = string [c]
 
 -- | Read a byte.
-byte :: Word -> Parser e ()
-byte (W# w) = ensureBytes# 1 >> scan8# (W# w)
+byte :: Word8 -> Parser e ()
+byte w = ensureBytes# 1 >> scan8# w
 {-# inline byte #-}
 
 -- | Read a sequence of bytes. This is a template function, you can use it as @$(bytes [3, 4, 5])@,
@@ -536,58 +569,6 @@
 fusedSatisfy_ f1 f2 f3 f4 = () <$ fusedSatisfy f1 f2 f3 f4
 {-# inline fusedSatisfy_ #-}
 
--- | Parse any byte.
-anyWord8 :: Parser e Word
-anyWord8 = Parser \fp !r eob buf n -> case eqAddr# eob buf of
-  1# -> Fail#
-  _  -> case indexWord8OffAddr buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 1#) n
-{-# inline anyWord8 #-}
-
--- | Skip any byte.
-anyWord8_ :: Parser e ()
-anyWord8_ = () <$ anyWord8
-{-# inline anyWord8_ #-}
-
--- | Parse any `Word16`.
-anyWord16 :: Parser e Word
-anyWord16 = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWord16OffAddr buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 2#) n
-{-# inline anyWord16 #-}
-
--- | Skip any `Word16`.
-anyWord16_ :: Parser e ()
-anyWord16_ = () <$ anyWord16
-{-# inline anyWord16_ #-}
-
--- | Parse any `Word32`.
-anyWord32 :: Parser e Word
-anyWord32 = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWord32OffAddr buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 4#) n
-{-# inline anyWord32 #-}
-
--- | Skip any `Word32`.
-anyWord32_ :: Parser e ()
-anyWord32_ = () <$ anyWord32
-{-# inline anyWord32_ #-}
-
--- | Parse any `Word`.
-anyWord :: Parser e Word
-anyWord = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of
-  0# -> Fail#
-  _  -> case indexWordOffAddr# buf 0# of
-    w -> OK# (W# w) (plusAddr# buf 8#) n
-{-# inline anyWord #-}
-
--- | Skip any `Word`.
-anyWord_ :: Parser e ()
-anyWord_ = () <$ anyWord
-{-# inline anyWord_ #-}
-
 -- | Parse any UTF-8-encoded `Char`.
 anyChar :: Parser e Char
 anyChar = Parser \fp !r eob buf n -> case eqAddr# eob buf of
@@ -876,30 +857,30 @@
 
 -- | Unsafely read a concrete byte from the input. It's not checked that the input has
 --   enough bytes.
-scan8# :: Word -> Parser e ()
-scan8# (W# c) = Parser \fp !r eob s n ->
-  case indexWord8OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan8# :: Word8 -> Parser e ()
+scan8# (W8# c) = Parser \fp !r eob s n ->
+  case indexWord8OffAddr# s 0# of
+    c' -> case eqWord8'# c c' of
       1# -> OK# () (plusAddr# s 1#) n
       _  -> Fail#
 {-# inline scan8# #-}
 
 -- | Unsafely read two concrete bytes from the input. It's not checked that the input has
 --   enough bytes.
-scan16# :: Word -> Parser e ()
-scan16# (W# c) = Parser \fp !r eob s n ->
-  case indexWord16OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan16# :: Word16 -> Parser e ()
+scan16# (W16# c) = Parser \fp !r eob s n ->
+  case indexWord16OffAddr# s 0# of
+    c' -> case eqWord16'# c c' of
       1# -> OK# () (plusAddr# s 2#) n
       _  -> Fail#
 {-# inline scan16# #-}
 
 -- | Unsafely read four concrete bytes from the input. It's not checked that the input has
 --   enough bytes.
-scan32# :: Word -> Parser e ()
-scan32# (W# c) = Parser \fp !r eob s n ->
-  case indexWord32OffAddr s 0# of
-    c' -> case eqWord# c c' of
+scan32# :: Word32 -> Parser e ()
+scan32# (W32# c) = Parser \fp !r eob s n ->
+  case indexWord32OffAddr# s 0# of
+    c' -> case eqWord32'# c c' of
       1# -> OK# () (plusAddr# s 4#) n
       _  -> Fail#
 {-# inline scan32# #-}
@@ -908,15 +889,15 @@
 --   enough bytes.
 scan64# :: Word -> Parser e ()
 scan64# (W# c) = Parser \fp !r eob s n ->
-  case indexWord64OffAddr s 0# of
+  case indexWord64OffAddr# s 0# of
     c' -> case eqWord# c c' of
       1# -> OK# () (plusAddr# s 8#) n
       _  -> Fail#
 {-# inline scan64# #-}
 
 -- | Unsafely read and return a byte from the input. It's not checked that the input is non-empty.
-scanAny8# :: Parser e Word
-scanAny8# = Parser \fp !r eob s n -> OK# (W# (indexWord8OffAddr s 0#)) (plusAddr# s 1#) n
+scanAny8# :: Parser e Word8
+scanAny8# = Parser \fp !r eob s n -> OK# (W8# (indexWord8OffAddr# s 0#)) (plusAddr# s 1#) n
 {-# inline scanAny8# #-}
 
 scanPartial64# :: Int -> Word -> Parser e ()
@@ -1050,3 +1031,204 @@
       !m    =  M.fromList ((Nothing, maybe (VarE 'empty) id fallback) : branches)
       !trie = compileTrie strings
   in (m , trie)
+
+--------------------------------------------------------------------------------
+
+withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a
+withAnyWord8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of
+  1# -> Fail#
+  _  -> case indexWord8OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 1#) n
+{-# inline withAnyWord8# #-}
+
+withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a
+withAnyWord16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWord16OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 2#) n
+{-# inline withAnyWord16# #-}
+
+withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a
+withAnyWord32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWord32OffAddr# buf 0# of
+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 4#) n
+{-# inline withAnyWord32# #-}
+
+withAnyWord64# :: (Word# -> Parser e a) -> Parser e a
+withAnyWord64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexWordOffAddr# buf 0# of
+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 8#) n
+{-# inline withAnyWord64# #-}
+
+withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a
+withAnyInt8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of
+  1# -> Fail#
+  _  -> case indexInt8OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 1#) n
+{-# inline withAnyInt8# #-}
+
+withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a
+withAnyInt16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt16OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 2#) n
+{-# inline withAnyInt16# #-}
+
+withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a
+withAnyInt32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt32OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 4#) n
+{-# inline withAnyInt32# #-}
+
+withAnyInt64# :: (Int# -> Parser e a) -> Parser e a
+withAnyInt64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of
+  0# -> Fail#
+  _  -> case indexInt64OffAddr# buf 0# of
+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 8#) n
+{-# inline withAnyInt64# #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Word8' (byte).
+anyWord8 :: Parser e Word8
+anyWord8 = withAnyWord8# (\w# -> pure (W8# w#))
+{-# inline anyWord8 #-}
+
+-- | Skip any 'Word8' (byte).
+anyWord8_ :: Parser e ()
+anyWord8_ = () <$ anyWord8
+{-# inline anyWord8_ #-}
+
+-- | Parse any 'Word16'.
+anyWord16 :: Parser e Word16
+anyWord16 = withAnyWord16# (\w# -> pure (W16# w#))
+{-# inline anyWord16 #-}
+
+-- | Skip any 'Word16'.
+anyWord16_ :: Parser e ()
+anyWord16_ = () <$ anyWord16
+{-# inline anyWord16_ #-}
+
+-- | Parse any 'Word32'.
+anyWord32 :: Parser e Word32
+anyWord32 = withAnyWord32# (\w# -> pure (W32# w#))
+{-# inline anyWord32 #-}
+
+-- | Skip any 'Word32'.
+anyWord32_ :: Parser e ()
+anyWord32_ = () <$ anyWord32
+{-# inline anyWord32_ #-}
+
+-- | Parse any 'Word64'.
+anyWord64 :: Parser e Word64
+anyWord64 = withAnyWord64# (\w# -> pure (W64# w#))
+{-# inline anyWord64 #-}
+
+-- | Skip any 'Word64'.
+anyWord64_ :: Parser e ()
+anyWord64_ = () <$ anyWord64
+{-# inline anyWord64_ #-}
+
+-- | Parse any 'Word'.
+anyWord :: Parser e Word
+anyWord = withAnyWord64# (\w# -> pure (W# w#))
+{-# inline anyWord #-}
+
+-- | Skip any 'Word'.
+anyWord_ :: Parser e ()
+anyWord_ = () <$ anyWord
+{-# inline anyWord_ #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Int8'.
+anyInt8 :: Parser e Int8
+anyInt8 = withAnyInt8# (\i# -> pure (I8# i#))
+{-# inline anyInt8 #-}
+
+-- | Parse any 'Int16'.
+anyInt16 :: Parser e Int16
+anyInt16 = withAnyInt16# (\i# -> pure (I16# i#))
+{-# inline anyInt16 #-}
+
+-- | Parse any 'Int32'.
+anyInt32 :: Parser e Int32
+anyInt32 = withAnyInt32# (\i# -> pure (I32# i#))
+{-# inline anyInt32 #-}
+
+-- | Parse any 'Int64'.
+anyInt64 :: Parser e Int64
+anyInt64 = withAnyInt64# (\i# -> pure (I64# i#))
+{-# inline anyInt64 #-}
+
+-- | Parse any 'Int'.
+anyInt :: Parser e Int
+anyInt = withAnyInt64# (\i# -> pure (I# i#))
+{-# inline anyInt #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Word16' (little-endian).
+anyWord16le :: Parser e Word16
+anyWord16le = anyWord16
+{-# inline anyWord16le #-}
+
+-- | Parse any 'Word16' (big-endian).
+anyWord16be :: Parser e Word16
+anyWord16be = withAnyWord16# (\w# -> pure (W16# (byteSwap16'# w#)))
+{-# inline anyWord16be #-}
+
+-- | Parse any 'Word32' (little-endian).
+anyWord32le :: Parser e Word32
+anyWord32le = anyWord32
+{-# inline anyWord32le #-}
+
+-- | Parse any 'Word32' (big-endian).
+anyWord32be :: Parser e Word32
+anyWord32be = withAnyWord32# (\w# -> pure (W32# (byteSwap32'# w#)))
+{-# inline anyWord32be #-}
+
+-- | Parse any 'Word64' (little-endian).
+anyWord64le :: Parser e Word64
+anyWord64le = anyWord64
+{-# inline anyWord64le #-}
+
+-- | Parse any 'Word64' (big-endian).
+anyWord64be :: Parser e Word64
+anyWord64be = withAnyWord64# (\w# -> pure (W64# (byteSwap# w#)))
+{-# inline anyWord64be #-}
+
+--------------------------------------------------------------------------------
+
+-- | Parse any 'Int16' (little-endian).
+anyInt16le :: Parser e Int16
+anyInt16le = anyInt16
+{-# inline anyInt16le #-}
+
+-- | Parse any 'Int16' (big-endian).
+anyInt16be :: Parser e Int16
+anyInt16be = withAnyWord16# (\w# -> pure (I16# (word16ToInt16# (byteSwap16'# w#))))
+{-# inline anyInt16be #-}
+
+-- | Parse any 'Int32' (little-endian).
+anyInt32le :: Parser e Int32
+anyInt32le = anyInt32
+{-# inline anyInt32le #-}
+
+-- | Parse any 'Int32' (big-endian).
+anyInt32be :: Parser e Int32
+anyInt32be = withAnyWord32# (\w# -> pure (I32# (word32ToInt32# (byteSwap32'# w#))))
+{-# inline anyInt32be #-}
+
+-- | Parse any 'Int64' (little-endian).
+anyInt64le :: Parser e Int64
+anyInt64le = anyInt64
+{-# inline anyInt64le #-}
+
+-- | Parse any 'Int64' (big-endian).
+anyInt64be :: Parser e Int64
+anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#))))
+{-# inline anyInt64be #-}
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,9 +1,16 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
 module Main where
 
 import Data.ByteString (ByteString)
+import qualified Data.ByteString as B
 import FlatParse.Basic
 import Test.HUnit
 import Test.Hspec
+import Test.Hspec.QuickCheck
+import Data.Word
+import Data.Int
+import Data.Bits
 
 main :: IO ()
 main = hspec $ do
@@ -201,6 +208,39 @@
     describe "readInteger" $ do
       pure ()
 
+    describe "Explicit-endianness machine integers" $ do
+      describe "Unsigned" $ do
+        prop "parses Word8s" $ do
+          \(w :: Word8)  -> anyWord8    `shouldParseWith` (w8AsByteString w, w)
+        prop "parses Word16s (LE)" $ do
+          \(w :: Word16) -> anyWord16le `shouldParseWith` (w16leAsByteString w, w)
+        prop "parses Word16s (BE)" $ do
+          \(w :: Word16) -> anyWord16be `shouldParseWith` (B.reverse (w16leAsByteString w), w)
+        prop "parses Word32s (LE)" $ do
+          \(w :: Word32) -> anyWord32le `shouldParseWith` (w32leAsByteString w, w)
+        prop "parses Word32s (BE)" $ do
+          \(w :: Word32) -> anyWord32be `shouldParseWith` (B.reverse (w32leAsByteString w), w)
+        prop "parses Word64s (LE)" $ do
+          \(w :: Word64) -> anyWord64le `shouldParseWith` (w64leAsByteString w, w)
+        prop "parses Word64s (BE)" $ do
+          \(w :: Word64) -> anyWord64be `shouldParseWith` (B.reverse (w64leAsByteString w), w)
+
+      describe "Signed" $ do
+        prop "parses Int8s" $ do
+          \(i :: Int8)   -> anyInt8     `shouldParseWith` (w8AsByteString i, i)
+        prop "parses Int16s (LE)" $ do
+          \(i :: Int16)  -> anyInt16le  `shouldParseWith` (w16leAsByteString i, i)
+        prop "parses Int16s (BE)" $ do
+          \(i :: Int16)  -> anyInt16be  `shouldParseWith` (B.reverse (w16leAsByteString i), i)
+        prop "parses Int32s (LE)" $ do
+          \(i :: Int32)  -> anyInt32le  `shouldParseWith` (w32leAsByteString i, i)
+        prop "parses Int32s (BE)" $ do
+          \(i :: Int32)  -> anyInt32be  `shouldParseWith` (B.reverse (w32leAsByteString i), i)
+        prop "parses Int64s (LE)" $ do
+          \(i :: Int64)  -> anyInt64le  `shouldParseWith` (w64leAsByteString i, i)
+        prop "parses Int64s (BE)" $ do
+          \(i :: Int64)  -> anyInt64be  `shouldParseWith` (B.reverse (w64leAsByteString i), i)
+
   describe "Combinators" $ do
     describe "(<|>)" $ do
       pure ()
@@ -295,3 +335,36 @@
 
     describe "unpackUTF8" $ do
       pure ()
+
+--------------------------------------------------------------------------------
+
+w8AsByteString :: (Bits w, Num w, Integral w) => w -> ByteString
+w8AsByteString w = B.pack [b1]
+  where
+    b1 = fromIntegral $  w .&. 0x00FF
+
+w16leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString
+w16leAsByteString w = B.pack [b1, b2]
+  where
+    b1 = fromIntegral $  w .&. 0x00FF
+    b2 = fromIntegral $ (w .&. 0xFF00) `shiftR` 8
+
+w32leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString
+w32leAsByteString w = B.pack [b1, b2, b3, b4]
+  where
+    b1 = fromIntegral $  w .&. 0x000000FF
+    b2 = fromIntegral $ (w .&. 0x0000FF00) `shiftR` 8
+    b3 = fromIntegral $ (w .&. 0x00FF0000) `shiftR` 16
+    b4 = fromIntegral $ (w .&. 0xFF000000) `shiftR` 24
+
+w64leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString
+w64leAsByteString w = B.pack [b1, b2, b3, b4, b5, b6, b7, b8]
+  where
+    b1 = fromIntegral $  w .&. 0x00000000000000FF
+    b2 = fromIntegral $ (w .&. 0x000000000000FF00) `shiftR` 8
+    b3 = fromIntegral $ (w .&. 0x0000000000FF0000) `shiftR` 16
+    b4 = fromIntegral $ (w .&. 0x00000000FF000000) `shiftR` 24
+    b5 = fromIntegral $ (w .&. 0x000000FF00000000) `shiftR` 32
+    b6 = fromIntegral $ (w .&. 0x0000FF0000000000) `shiftR` 40
+    b7 = fromIntegral $ (w .&. 0x00FF000000000000) `shiftR` 48
+    b8 = fromIntegral $ (w .&. 0xFF00000000000000) `shiftR` 56
