HTTP.sys web server implementation in ASP.NET Core


By Tom Dykstra, Chris Ross, and Luke Latham


This topic applies to ASP.NET Core 2.0 or later. In earlier versions of ASP.NET Core, HTTP.sys is named WebListener.

HTTP.sys is a web server for ASP.NET Core that only runs on Windows. HTTP.sys is an alternative to Kestrel and offers some features that Kestrel doesn’t provide.


HTTP.sys is incompatible with the ASP.NET Core Module and can’t be used with IIS or IIS Express.

HTTP.sys supports the following features:

  • Windows Authentication
  • Port sharing
  • HTTPS with SNI
  • HTTP/2 over TLS (Windows 10 or later)
  • Direct file transmission
  • Response caching
  • WebSockets (Windows 8 or later)

Supported Windows versions:

  • Windows 7 or later
  • Windows Server 2008 R2 or later

View or download sample code (how to download)

When to use HTTP.sys

HTTP.sys is useful for deployments where:

  • There’s a need to expose the server directly to the Internet without using IIS.

    HTTP.sys communicates directly with the Internet

  • An internal deployment requires a feature not available in Kestrel, such as Windows Authentication.

    HTTP.sys communicates directly with the internal network

HTTP.sys is mature technology that protects against many types of attacks and provides the robustness, security, and scalability of a full-featured web server. IIS itself runs as an HTTP listener on top of HTTP.sys.

How to use HTTP.sys

Configure the ASP.NET Core app to use HTTP.sys

  1. A package reference in the project file isn’t required when using the Microsoft.AspNetCore.All metapackage ( (ASP.NET Core 2.0 or later). When not using the Microsoft.AspNetCore.All metapackage, add a package reference to Microsoft.AspNetCore.Server.HttpSys.

  2. Call the UseHttpSys extension method when building the web host, specifying any required HTTP.sys options:

    public static IWebHost BuildWebHost(string[] args) =>
            .UseHttpSys(options =>
                // The following options are set to default values.
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;

    Additional HTTP.sys configuration is handled through registry settings.

    HTTP.sys options

    Property Description Default
    AllowSynchronousIO Control whether synchronous input/output is allowed for the HttpContext.Request.Body and HttpContext.Response.Body. true
    Authentication.AllowAnonymous Allow anonymous requests. true
    Authentication.Schemes Specify the allowed authentication schemes. May be modified at any time prior to disposing the listener. Values are provided by the AuthenticationSchemes enum: Basic, Kerberos, Negotiate, None, and NTLM. None
    EnableResponseCaching Attempt kernel-mode caching for responses with eligible headers. The response may not include Set-Cookie, Vary, or Pragma headers. It must include a Cache-Control header that’s public and either a shared-max-age or max-age value, or an Expires header. true
    MaxAccepts The maximum number of concurrent accepts. ۵ × Environment.
    MaxConnections The maximum number of concurrent connections to accept. Use -1 for infinite. Use null to use the registry’s machine-wide setting. null
    MaxRequestBodySize See the MaxRequestBodySize section. ۳۰۰۰۰۰۰۰ bytes
    (~28.6 MB)
    RequestQueueLimit The maximum number of requests that can be queued. ۱۰۰۰
    ThrowWriteExceptions Indicate if response body writes that fail due to client disconnects should throw exceptions or complete normally. false
    (complete normally)
    Timeouts Expose the HTTP.sys TimeoutManager configuration, which may also be configured in the registry. Follow the API links to learn more about each setting, including default values:
    UrlPrefixes Specify the UrlPrefixCollection to register with HTTP.sys. The most useful is UrlPrefixCollection.Add, which is used to add a prefix to the collection. These may be modified at any time prior to disposing the listener.


    The maximum allowed size of any request body in bytes. When set to null, the maximum request body size is unlimited. This limit has no effect on upgraded connections, which are always unlimited.

    The recommended method to override the limit in an ASP.NET Core MVC app for a single IActionResult is to use the RequestSizeLimitAttribute attribute on an action method:

    public IActionResult MyActionMethod()

    An exception is thrown if the app attempts to configure the limit on a request after the app has started reading the request. An IsReadOnly property can be used to indicate if the MaxRequestBodySize property is in a read-only state, meaning it’s too late to configure the limit.

    If the app should override MaxRequestBodySize per-request, use the IHttpMaxRequestBodySizeFeature:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
        ILogger<Startup> logger)
        app.Use(async (context, next) =>
                .MaxRequestBodySize = 10 * 1024;
            var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
            var addresses = string.Join(", ", serverAddressesFeature?.Addresses);
            logger.LogInformation($"Addresses: addresses");
            await next.Invoke();
        if (env.IsDevelopment())
  3. If using Visual Studio, make sure the app isn’t configured to run IIS or IIS Express.

    In Visual Studio, the default launch profile is for IIS Express. To run the project as a console app, manually change the selected profile, as shown in the following screen shot:

    Select console app profile

Configure Windows Server

  1. If the app is a framework-dependent deployment, install .NET Core, .NET Framework, or both (if the app is a .NET Core app targeting the .NET Framework).

    • .NET Core – If the app requires .NET Core, obtain and run the .NET Core installer from .NET All Downloads.
    • .NET Framework – If the app requires .NET Framework, see .NET Framework: Installation guide to find installation instructions. Install the required .NET Framework. The installer for the latest .NET Framework can be found at .NET All Downloads.
  2. Configure URLs and ports for the app.

    By default, ASP.NET Core binds to http://localhost:5000. To configure URL prefixes and ports, options include using:

    The following code example shows how to use UrlPrefixes:

    public static IWebHost BuildWebHost(string[] args) =>
            .UseHttpSys(options =>
                // The following options are set to default values.
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;

    An advantage of UrlPrefixes is that an error message is generated immediately for improperly formatted prefixes.

    The settings in UrlPrefixes override UseUrls/urls/ASPNETCORE_URLS settings. Therefore, an advantage of UseUrls, urls, and the ASPNETCORE_URLS environment variable is that it’s easier to switch between Kestrel and HTTP.sys. For more information on UseUrls, urls, and ASPNETCORE_URLS, see Hosting.

    HTTP.sys uses the HTTP Server API UrlPrefix string formats.


    Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit host names rather than wildcards. Subdomain wildcard binding (for example, * doesn’t have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). See rfc7230 section-5.4 for more information.

  3. Preregister URL prefixes to bind to HTTP.sys and set up x.509 certificates.

    If URL prefixes aren’t preregistered in Windows, run the app with administrator privileges. The only exception is when binding to localhost using HTTP (not HTTPS) with a port number greater than 1024. In that case, administrator privileges aren’t required.

    1. The built-in tool for configuring HTTP.sys is netsh.exe. netsh.exe is used to reserve URL prefixes and assign X.509 certificates. The tool requires administrator privileges.

      The following example shows the commands to reserve URL prefixes for ports 80 and 443:

      netsh http add urlacl url=http://+:80/ user=Users
      netsh http add urlacl url=https://+:443/ user=Users

      The following example shows how to assign an X.509 certificate:

      netsh http add sslcert ipport= certhash=MyCertHash_Here appid=00000000-0000-0000-0000-000000000000"

      Reference documentation for netsh.exe:

    2. Create self-signed X.509 certificates, if required.

      On Windows, self-signed certificates can be created using the New-SelfSignedCertificate PowerShell cmdlet. For an unsupported example, see UpdateIISExpressSSLForChrome.ps1.

      On macOS, Linux, and Windows, certificates can be created using OpenSSL.

  4. Open firewall ports to allow traffic to reach HTTP.sys. Use netsh.exe or PowerShell cmdlets.

Additional resources