diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Hoogle
 
+4.2.33
+    Allow WAI-3.0
 4.2.32
     Allow haskell-src-exts-1.15
 4.2.31
diff --git a/hoogle.cabal b/hoogle.cabal
--- a/hoogle.cabal
+++ b/hoogle.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.10
 build-type:         Simple
 name:               hoogle
-version:            4.2.32
+version:            4.2.33
 license:            BSD3
 license-file:       docs/LICENSE
 category:           Development
diff --git a/src/General/Web.hs b/src/General/Web.hs
--- a/src/General/Web.hs
+++ b/src/General/Web.hs
@@ -21,6 +21,9 @@
 import General.Base
 import System.FilePath
 import Network.Wai
+#if MIN_VERSION_wai(3, 0, 0)
+import Data.IORef
+#endif
 #if MIN_VERSION_wai(2, 0, 0)
 import Network.Wai.Internal
 #endif
@@ -46,7 +49,15 @@
 
 responseFlatten :: Response -> IO (Status, ResponseHeaders, LBString)
 responseFlatten r = do
-#if MIN_VERSION_wai(2, 0, 0)
+#if MIN_VERSION_wai(3, 0, 0)
+    let (s,hs,withBody) = responseToStream r
+    ref <- newIORef mempty
+    let addChunk builder = modifyIORef ref (<> builder)
+    withBody $ \body -> body addChunk (return ())
+    builder <- readIORef ref
+    let res = toLazyByteString builder
+    return (s,hs,res)
+#elif MIN_VERSION_wai(2, 0, 0)
     let (s,hs,withSrc) = responseToSource r
     chunks <- withSrc $ \src -> src $$ consume
     let res = toLazyByteString $ mconcat [x | Chunk x <- chunks]
diff --git a/src/Web/Server.hs b/src/Web/Server.hs
--- a/src/Web/Server.hs
+++ b/src/Web/Server.hs
@@ -32,14 +32,23 @@
     resp <- respArgs q
     v <- newMVar ()
     putStrLn $ "Starting Hoogle Server on port " ++ show port
-    runSettings defaultSettings{settingsOnException=exception, settingsPort=port} $ \r -> liftIO $ do
+    runSettings defaultSettings{settingsOnException=exception, settingsPort=port}
+#if MIN_VERSION_wai(3, 0, 0)
+      $ \r sendResponse -> do
+#else
+      $ \r -> liftIO $ do
+#endif
         start <- getCurrentTime
         res <- talk resp q r
         responseEvaluate res
         stop <- getCurrentTime
         let t = floor $ diffUTCTime stop start * 1000
         withMVar v $ const $ putStrLn $ bsUnpack (rawPathInfo r) ++ bsUnpack (rawQueryString r) ++ " ms:" ++ show t
+#if MIN_VERSION_wai(3, 0, 0)
+        sendResponse res
+#else
         return res
+#endif
 
 
 #if MIN_VERSION_wai(2, 0, 0)
