This library lets you implement an HTTP server with handlers for each endpoint of a servant API, handling most of the boilerplate for you.

Getting started

We’ve written a tutorial guide that introduces the core types and features of servant. After this article, you should be able to write your first servant webservices, learning the rest from the haddocks’ examples.


The latest version of this document is on GitHub. Changelog for servant package contains significant entries for all core packages.

Package versions follow the Package Versioning Policy: in A.B.C, bumps to either A or B represent major versions.


  • Add API docs for ServerT #1573
  • Add Functor instance to AuthHandler. #1638
  • Compatibility with GHC 9.6. #1680


Compatibility with GHC 9.4, see PR #1592.



Significant changes

  • Drop support for GHC < 8.6.
  • Support GHC 9.0 (GHC 9.2 should work as well, but isn’t fully tested yet).
  • Support Aeson 2 (#1475), which fixes a DOS vulnerability related to hash collisions.
  • Add NamedRoutes combinator, making support for records first-class in Servant (#1388).
  • Add custom type errors for partially applied combinators (#1289, #1486).


Significant changes

  • Add response header support to UVerb (#1420)

Other changes

  • Support GHC-9.0.1.
  • Bump bytestring, hspec and base64-bytestring dependencies.


Significant changes

  • Support Fragment combinator.


Significant changes

  • Union verbs

Other changes

  • Bump “tested-with” ghc versions
  • Allow newer dependencies


Significant changes

  • Support for ghc8.8 (#1318, #1326, #1327)

  • Configurable error messages for automatic errors thrown by servant, like “no route” or “could not parse json body” (#1312, #1326, #1327)


Significant changes

  • Add NoContentVerb #1028 #1219 #1228

    The NoContent API endpoints should now use NoContentVerb combinator. The API type changes are usually of the kind

    - :<|> PostNoContent '[JSON] NoContent
    + :<|> PostNoContent

    i.e. one doesn’t need to specify the content-type anymore. There is no content.

  • Capture can be Lenient #1155 #1156

    You can specify a lenient capture as

    :<|> "capture-lenient"  :> Capture' '[Lenient] "foo" Int :> GET

    which will make the capture always succeed. Handlers will be of the type Either String CapturedType, where Left err represents the possible parse failure.

  • servant-server use queryString to parse QueryParam, QueryParams and QueryFlag #1249 #1262

    Some APIs need query parameters rewriting, e.g. in order to support for multiple casing (camel, snake, etc) or something to that effect.

    This could be easily achieved by using WAI Middleware and modifying request’s Query. But QueryParam, QueryParams and QueryFlag use rawQueryString. By using queryString rather then rawQueryString we can enable such rewritings.

  • servant servant-server Make packages build-type: Simple #1263

    We used build-type: Custom, but it’s problematic e.g. for cross-compiling. The benefit is small, as the doctests can be run other ways too (though not so conveniently).


  • singleton-bool-0.1.5 (SBool is re-exported)
    • Add discreteBool :: Dec (a :~: b) (GHC-7.8+)
    • Add Show, Eq, Ord SBool b instances.
  • dependencies update


  • Use http-api-data-0.4.1 (a part of its API is re-exported) #1181


  • Rename ServantError to ClientError, ServantErr to ServerError #1131
  • servant-server Reorder HTTP failure code priorities #1103
  • servant-server Re-organise internal modules #1139
  • Allow network-3.0 #1107


  • Streaming refactoring. #991 #1076 #1077

    The streaming functionality (Servant.API.Stream) is refactored to use servant’s own SourceIO type (see Servant.Types.SourceT documentation), which replaces both StreamGenerator and ResultStream types.

    New conversion type-classes are ToSourceIO and FromSourceIO (replacing ToStreamGenerator and BuildFromStream). There are instances for conduit, pipes and machines in new packages: servant-conduit servant-pipes and servant-machines respectively.

    Writing new framing strategies is simpler. Check existing strategies for examples.

    This change shouldn’t affect you, if you don’t use streaming endpoints.

  • Drop support for GHC older than 8.0 #1008 #1009

  • servant NewlineFraming encodes newline after each element (i.e last) #1079 #1011

  • servant Add lookupResponseHeader :: ... => Headers headers r -> ResponseHeader h a #1064

  • servant-server Add MonadMask Handler #1068

  • servant Export GetHeaders' #1052

  • servant Add Bitraversable and other Bi- instances for :<|> #1032

  • servant Add PutCreated method type alias #1024

  • servant Add ToSourceIO (NonEmpty a) instance #988


  • Merge in servant-generic (by Patrick Chilton) into servant (Servant.API.Generic), servant-client-code (Servant.Client.Generic) and servant-server (Servant.Server.Generic).

  • servant-server Deprecate Servant.Utils.StaticUtils, use Servant.Server.StaticUtils.


  • Stream takes a status code argument

    -Stream method        framing ctype a
    +Stream method status framing ctype a

    (#966 #972)

  • ToStreamGenerator definition changed, so it’s possible to write an instance for conduits.

    -class ToStreamGenerator f a where
    -   toStreamGenerator :: f a -> StreamGenerator a
    +class ToStreamGenerator a b | a -> b where
    +   toStreamGenerator :: a -> StreamGenerator b


  • Added NoFraming streaming strategy (#959)

  • servant-server File serving in polymorphic monad. i.e. Generalised types of serveDirectoryFileServer etc functions in Servant.Utils.StaticFiles (#953)

  • servant-server ReqBody content type check is recoverable. This allows writing APIs like:

          ReqBody '[JSON] Int      :> Post '[PlainText] Int
    :<|>  ReqBody '[PlainText] Int :> Post '[PlainText] Int

    which is useful when handlers are subtly different, for example may do less work. (#937)

  • Support base-compat-0.10


  • Streaming endpoint support. (#836)
  • servant Add Servant.API.Modifiers (#873)


Breaking changes

  • Added hoistServer member to the HasServer class, which is HasServer specific enter. (#804)


Breaking changes

  • Changed HasServer instances for Header to throw 400 when parsing fails (#724)
  • Added headersD block to Delayed (#724)

Other changes

  • Add err418, err422 error codes (#739)


Breaking changes

  • Handler is now an abstract datatype. Migration hint: change throwE to throwError. (#641)

  • Changed HasServer instances for QueryParam and QueryParam to throw 400 when parsing fails (#649)

Other changes

  • Added paramsD block to Delayed

  • Add err422 Unprocessable Entity (#646)

  • Deprecate serveDirectory and introduce serveDirectoryFileServer, serveDirectoryWebApp, serveDirectoryWebAppLookup, serveDirectoryEmbedded and serveDirectoryWith which offer 4 default options and a more flexible one for serving static files. (#658)

  • DelayedIO is an instance of MonadResource, allowing safe resource handling. (#622 , #674 , #675)



  • The Router type has been changed. Static router tables should now be properly shared between requests, drastically increasing the number of situations where servers will be able to route requests efficiently. Functions layout and layoutWithContext have been added to visualize the router layout for debugging purposes. Test cases for expected router layouts have been added.
  • If an endpoint is discovered to have a non-matching “accept header”, this is now a recoverable rather than a fatal failure, allowing different endpoints for the same route, but with different content types to be specified modularly.
  • Export throwError from module Servant
  • Add Handler type synonym


  • If servers use the BasicAuth combinator and receive requests with missing or invalid credentials, the resulting error responses (401 and 403) could be overwritten by subsequent alternative routes. Now BasicAuth uses FailFatal and the error responses can’t be overwritten anymore.


  • Query parameters that can’t be parsed result in a 400 (was 404).


  • Add Config machinery ( This is a breaking change, as the signatures of both route, serve and the typeclass HasServer now take an additional parameter.
  • Support for the HttpVersion, IsSecure, RemoteHost and Vault combinators
  • Drop EitherT in favor of ExceptT
  • Use http-api-data instead of Servant.Common.Text
  • Remove matrix params.
  • Remove RouteMismatch.
  • Redefined constructors of RouteResult.
  • Added Delayed and related functions (addMethodCheck, addAcceptCheck, addBodyCheck, runDelayed)
  • Added support for Basic Authentication
  • Add generalized authentication support via the AuthServerData type family and AuthHandler handler


  • Bump attoparsec upper bound to < 0.14
  • Bump wai-app-static upper bound to < 3.2
  • Bump either upper bound to < 4.5