Skip to content
Switch branches/tags
Go to file


Failed to load latest commit information.
Latest commit message
Commit time

Titanium Web Proxy

A lightweight HTTP(S) proxy server written in C#.

Build Status Join the chat at

Report bugs or raise issues here. For programming help use StackOverflow with the tag Titanium-Web-Proxy.


  • Multithreaded and asynchronous proxy employing server connection pooling, certificate cache, and buffer pooling
  • View, modify, redirect and block requests or responses
  • Supports mutual SSL authentication, proxy authentication & automatic upstream proxy detection
  • Supports kerberos, NTLM authentication over HTTP protocols on windows domain controlled networks
  • SOCKS4/5 Proxy support


Install by nuget

For beta releases on beta branch

Install-Package Titanium.Web.Proxy -Pre

For stable releases on stable branch

Install-Package Titanium.Web.Proxy


  • .NET Standard 2.0 or above
  • .NET Framework 4.5 or above

Note to contributors

Road map

  • Fix outstanding bugs
  • Support reading request and response body as stream #823
  • Use Dispose(false) pattern to reduce possibility of memory leaks #740
  • Stop throwing new exceptions #634
  • Support HTTP 2.0


The owner of this project, justcoding121, is considered to be inactive from this project due to his busy work schedule. However, we have a collaborator listed below who time and again shows up to maintain this project. Please create pull requests prioritizing bug fixes for the attention of collaborators.

Development environment


  • Visual Studio Code as IDE for .NET Core
  • Visual Studio 2019 as IDE for .NET Framework/.NET Core

Mac OS

  • Visual Studio Code as IDE for .NET Core
  • Visual Studio 2019 as IDE for Mono


  • Visual Studio Code as IDE for .NET Core
  • Mono develop as IDE for Mono


Refer the HTTP Proxy Server library in your project and look up the test project to learn usage.

Setup HTTP proxy:

var proxyServer = new ProxyServer();

// locally trust root certificate used by this proxy 
proxyServer.CertificateManager.TrustRootCertificate = true;

// optionally set the Certificate Engine
// Under Mono only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;

proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;

var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
    // Use self-issued generic certificate on all https requests
    // Optimizes performance by not creating a certificate for each https-enabled domain
    // Useful when certificate trust is not required by proxy clients
   //GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")

// Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnect += OnBeforeTunnelConnect;

// An explicit endpoint is where the client knows about the existence of a proxy
// So client sends request in a proxy friendly manner

// Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
// A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
// to send data to this endPoint
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
    // Generic Certificate hostname to use
    // when SNI is disabled by client
    GenericCertificateName = ""


//proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

foreach (var endPoint in proxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
    endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);

// Only explicit proxies can be set as system proxy!

// wait here (You can use something else as a wait function, I am using this as a demo)

// Unsubscribe & Quit
explicitEndPoint.BeforeTunnelConnect -= OnBeforeTunnelConnect;
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;


Sample request and response event handlers

private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
    string hostname = e.HttpClient.Request.RequestUri.Host;

    if (hostname.Contains(""))
         // Exclude Https addresses you don't want to proxy
         // Useful for clients that use certificate pinning
         // for example
         e.DecryptSsl = false;

public async Task OnRequest(object sender, SessionEventArgs e)

    // read request headers
    var requestHeaders = e.HttpClient.Request.RequestHeaders;

    var method = e.HttpClient.Request.Method.ToUpper();
    if ((method == "POST" || method == "PUT" || method == "PATCH"))
        // Get/Set request body bytes
        byte[] bodyBytes = await e.GetRequestBody();

        // Get/Set request body as string
        string bodyString = await e.GetRequestBodyAsString();
        // store request 
        // so that you can find it from response handler 
        e.UserData = e.HttpClient.Request;

    // To cancel a request with a custom HTML content
    // Filter URL
    if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains(""))
        e.Ok("<!DOCTYPE html>" +
            "<html><body><h1>" +
            "Website Blocked" +
            "</h1>" +
            "<p>Blocked by titanium web proxy.</p>" +
            "</body>" +

    // Redirect example
    if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains(""))

// Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
    // read response headers
    var responseHeaders = e.HttpClient.Response.ResponseHeaders;

    //if (!e.ProxySession.Request.Host.Equals("")) return;
    if (e.HttpClient.Request.Method == "GET" || e.HttpClient.Request.Method == "POST")
        if (e.HttpClient.Response.ResponseStatusCode == "200")
            if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
                byte[] bodyBytes = await e.GetResponseBody();

                string body = await e.GetResponseBodyAsString();
    if (e.UserData != null)
        // access request from UserData property where we stored it in RequestHandler
        var request = (Request)e.UserData;

// Allows overriding default certificate validation logic
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
    // set IsValid to true/false based on Certificate Errors
    if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
        e.IsValid = true;

    return Task.CompletedTask;

// Allows overriding default client certificate selection logic during mutual authentication
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
    // set e.clientCertificate to override
    return Task.CompletedTask;

Console example application screenshot

alt tag

GUI example application screenshot

alt tag