How it works

BestHTTP implements HTTP/2 over TLS. Using the TLS negotiation and its ALPN extension the plugin let the server know that it’s ready to upgrade to the HTTP/2 protocol. If the server has support for HTTP/2 and sends back the proper answer the plugin upgrades the connection and will communicate with the server using the HTTP/2 protocol. Using the TLS’ ALPN extension upgrading to HTTP/2 is faster.

However, when multiple requests are made to the same server and the plugin don’t know whether the server capable to upgrade to HTTP/2, it will create only one connection to test against http/2. If the server reports no HTTP/2/2 support, the plugin will open new connections depending on the value of HTTPManager.MaxConnectionPerServer. if the server supports HTTP/2, the plugin will use that connection only. This mechanism prevents the plugin to open multiple connections that will be used only for one request. The plugin also stores what servers are supporting HTTP/2, so next time it can decide whether it should open multiple connections or not.

Using HTTP/2 is seemless and requires no prior knowledge whether any target servers has support for it or not. The plugin hides differencies HTTP1.1 and HTTP/2 from the user, but will take advantage of the new protocol every time it has a chance.


Using HTTP/2 Ping frames the client can measure the latency between the server and the client. Setting a lower PingFrequency rate will help get a more accurate view of the latency with the price of more overhead.

Here’s a small example how the Latency property can be acquired from the plugin.

using System;

using BestHTTP;
using BestHTTP.Connections;
using BestHTTP.Connections.HTTP2;
using BestHTTP.Core;

using UnityEngine;

public sealed class PrintHTTP2Latency : MonoBehaviour
    public string ServerURL;

    private Uri serverUri;
    private string key = null;
    private double lastPrintedLatency = 0;

    private void Start()
        serverUri = new Uri(ServerURL);

    private void Update()
        // Cache they Server+Proxy unique key. It expects that the global Proxy isn't changing.
        if (string.IsNullOrEmpty(key))
            key = HostDefinition.GetKeyFor(serverUri, HTTPManager.Proxy);

        // For the given Server+Proxy combination Find a HTTPConnection that has a HTTP2Handler
        var httpConnection = HostManager.GetHost(serverUri.Host)
            .Find(con => con is HTTPConnection http && http.requestHandler is HTTP2Handler) as HTTPConnection;

        // No connection yet
        if (httpConnection == null)

        // Get the HTTP2Handler and print latency. If Latency is zero, no ping ack received from the server yet.
        if (httpConnection.requestHandler is HTTP2Handler http2handler &&
            http2handler.Latency > 0 &&
            lastPrintedLatency != http2handler.Latency)
            lastPrintedLatency = http2handler.Latency;

You can add this component to a GameObject and set its ServerURL field in the Unity3D Editor:


WebSocket Over HTTP/2 Settings

Through these options the WebSocket Over HTTP/2 implementation can be customized.


Set it to false to disable Websocket Over HTTP/2 (RFC 8441). It’s true by default.

HTTPManager.HTTP2Settings.WebSocketOverHTTP2Settings.EnableWebSocketOverHTTP2 = false;


Set it to disable fallback logic from the Websocket Over HTTP/2 implementation to the ‘old’ HTTP/1 implementation when it fails to connect.

HTTPManager.HTTP2Settings.WebSocketOverHTTP2Settings.EnableImplementationFallback = false;


As most of the global settings, HTTP/2 settings can be accessed through the HTTPManager class:

using BestHTTP;

HTTPManager.HTTP2Settings.InitialStreamWindowSize = 5 * 1024 * 1024;


Maximum concurrent http2 stream on http2 connection will allow. Its default value is 128;

HTTPManager.HTTP2Settings.MaxConcurrentStreams = 256;


Initial window size of a http2 stream. Its default value is 10 MiB (10 * 1024 * 1024).

HTTPManager.HTTP2Settings.InitialStreamWindowSize = 1 * 1024 * 1024;


Global window size of a http/2 connection. Its default value is the maximum possible value on 31 bits.

HTTPManager.HTTP2Settings.InitialConnectionWindowSize = HTTPManager.HTTP2Settings.MaxConcurrentStreams * 1024 * 1024;


Maximum payload size of a http2 frame. Its default value is 16384. It must be between 16_384 and 16_777_215.

HTTPManager.HTTP2Settings.MaxFrameSize = 1 * 1024 * 1024;


With HTTP/2 only one connection will be open so we can can keep it open longer as we hope it will be resued more. Its default value is 120 seconds.

HTTPManager.HTTP2Settings.MaxIdleTime = TimeSpan.FromSeconds(30);


Minimum time between two ping messages.

HTTPManager.HTTP2Settings.PingFrequency = TimeSpan.FromSeconds(3);


Timeout to receive a ping acknowledgement from the server. If no ack reveived in this time the connection will be treated as broken.

HTTPManager.HTTP2Settings.Timeout = TimeSpan.FromSeconds(5);