Skip to content
Guides 7 Connection Type: 1 views

C# Proxy Setup

Learn to configure C# HttpClient using WebProxy for effective proxy management. This guide covers setup, authentication, and best practices.

Configuring a proxy for HTTP requests in C# with HttpClient involves instantiating an HttpClientHandler, assigning a WebProxy object with the proxy address and optional credentials to its Proxy property, and then passing this configured handler to the HttpClient constructor. This setup enables applications to route outgoing web traffic through an intermediary server, which is essential for network security, access control, logging, or bypassing geographical restrictions.

Understanding HttpClient, HttpClientHandler, and WebProxy

HttpClient is the primary class in .NET for sending HTTP requests and receiving HTTP responses. It is designed for long-lived instances and concurrent requests.
HttpClientHandler is the underlying message handler that HttpClient uses to send requests. It provides configuration options for network settings, including proxy configuration, credentials, and SSL/TLS settings.
WebProxy is a class that specifies the URI of a proxy server and allows for configuration of proxy bypass lists and credentials.

HttpClient Instance Management

HttpClient instances should generally be reused across multiple requests to avoid socket exhaustion issues. Creating a new HttpClient for each request can lead to performance problems and resource depletion. A common pattern is to use a single HttpClient instance throughout the application's lifetime or to leverage IHttpClientFactory in ASP.NET Core applications.

Basic Proxy Configuration

To configure a basic HTTP or HTTPS proxy, create an instance of HttpClientHandler, set its Proxy property to a new WebProxy object initialized with the proxy's URI, and then pass this handler to the HttpClient constructor.

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class ProxySetup
{
    public static async Task Main(string[] args)
    {
        string proxyAddress = "http://your.proxy.server:8080"; // Replace with your proxy address
        string targetUrl = "http://httpbin.org/get"; // A public endpoint to test

        // Create a WebProxy instance
        var webProxy = new WebProxy(proxyAddress, BypassOnLocal: false);

        // Create an HttpClientHandler and assign the WebProxy
        var handler = new HttpClientHandler
        {
            Proxy = webProxy,
            UseProxy = true // Explicitly enable proxy usage
        };

        // Create an HttpClient with the configured handler
        using (var httpClient = new HttpClient(handler))
        {
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
                response.EnsureSuccessStatusCode(); // Throws an exception if the HTTP status code is an error
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("Request successful. Response snippet:");
                Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500))); // Print first 500 chars
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request error: {e.Message}");
            }
            catch (WebException e)
            {
                Console.WriteLine($"Proxy or network error: {e.Message}");
            }
        }
    }
}

In this example:
* WebProxy(proxyAddress, BypassOnLocal: false) creates a proxy object. BypassOnLocal: false ensures that requests to local addresses (e.g., localhost) also go through the proxy, unless explicitly bypassed later.
* handler.UseProxy = true explicitly instructs the handler to use the configured proxy.

Proxy with Authentication

If the proxy server requires authentication (e.g., username and password), set the Credentials property of the WebProxy object using a NetworkCredential instance.

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class AuthenticatedProxySetup
{
    public static async Task Main(string[] args)
    {
        string proxyAddress = "http://your.authenticated.proxy.server:8080"; // Replace
        string proxyUsername = "your_username"; // Replace
        string proxyPassword = "your_password"; // Replace
        string targetUrl = "http://httpbin.org/get";

        var credentials = new NetworkCredential(proxyUsername, proxyPassword);

        var webProxy = new WebProxy(proxyAddress, BypassOnLocal: false)
        {
            Credentials = credentials
        };

        var handler = new HttpClientHandler
        {
            Proxy = webProxy,
            UseProxy = true
        };

        using (var httpClient = new HttpClient(handler))
        {
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("Request successful with authenticated proxy.");
                Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request error: {e.Message}");
            }
            catch (WebException e)
            {
                Console.WriteLine($"Proxy or network error: {e.Message}");
            }
        }
    }
}

Using System Default Proxy

HttpClientHandler can be configured to use the system's default proxy settings, which are typically configured in the operating system or Internet Explorer settings. This is often the desired behavior in enterprise environments.

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class SystemDefaultProxySetup
{
    public static async Task Main(string[] args)
    {
        string targetUrl = "http://httpbin.org/get";

        var handler = new HttpClientHandler
        {
            UseSystemProxy = true // Use the system's default proxy settings
        };

        using (var httpClient = new HttpClient(handler))
        {
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("Request successful using system default proxy.");
                Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request error: {e.Message}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error: {e.Message}");
            }
        }
    }
}

Setting UseSystemProxy = true automatically configures the HttpClientHandler to discover and use the proxy settings defined at the operating system level. If UseSystemProxy is true, the Proxy property is ignored.

Bypassing Proxy for Specific Addresses

The WebProxy class provides mechanisms to bypass the proxy for certain addresses.

BypassProxyOnLocal

Setting BypassProxyOnLocal = true in the WebProxy constructor or property will instruct the proxy to not be used for local intranet resources. This is often desirable to prevent internal traffic from routing unnecessarily through an external proxy.

var webProxy = new WebProxy("http://your.proxy.server:8080")
{
    BypassProxyOnLocal = true // Do not use proxy for local addresses
};

BypassList

For more granular control, the BypassList property allows specifying an array of regular expressions that define URIs for which the proxy should be bypassed.

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class ProxyBypassListSetup
{
    public static async Task Main(string[] args)
    {
        string proxyAddress = "http://your.proxy.server:8080";
        string targetUrl = "http://internal.api.com/data"; // Example internal URL
        string externalUrl = "http://external.api.com/data"; // Example external URL

        // Define a bypass list using regular expressions
        string[] bypassList = new string[]
        {
            "internal\\.api\\.com", // Bypass for internal.api.com
            "\\.local$" // Bypass for any host ending with .local
        };

        var webProxy = new WebProxy(proxyAddress)
        {
            BypassList = bypassList,
            BypassProxyOnLocal = false // Explicitly handle local bypass via BypassList if needed
        };

        var handler = new HttpClientHandler
        {
            Proxy = webProxy,
            UseProxy = true
        };

        using (var httpClient = new HttpClient(handler))
        {
            Console.WriteLine($"Attempting request to {targetUrl} (should bypass proxy)...");
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
                response.EnsureSuccessStatusCode();
                Console.WriteLine($"Request to {targetUrl} successful. (Check proxy logs if available)");
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request to {targetUrl} error: {e.Message}");
            }

            Console.WriteLine($"\nAttempting request to {externalUrl} (should use proxy)...");
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(externalUrl);
                response.EnsureSuccessStatusCode();
                Console.WriteLine($"Request to {externalUrl} successful. (Check proxy logs if available)");
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request to {externalUrl} error: {e.Message}");
            }
        }
    }
}

HttpClientHandler vs. SocketsHttpHandler

.NET Core 2.1 introduced SocketsHttpHandler as the default handler for HttpClient, offering improved performance and cross-platform consistency. HttpClientHandler still exists and can be explicitly used, but SocketsHttpHandler is generally preferred for new development. When using SocketsHttpHandler, proxy configuration is slightly different.

Feature HttpClientHandler SocketsHttpHandler (Recommended for .NET Core/.NET 5+)
Proxy Type WebProxy IWebProxy (often WebProxy or custom implementation)
Configuration Set Proxy property with WebProxy instance. Set Proxy property with IWebProxy instance.
System Proxy UseSystemProxy = true UseProxy = true and Proxy = WebRequest.DefaultWebProxy or null for system default.
Authentication WebProxy.Credentials WebProxy.Credentials (if WebProxy is used)
SOCKS Proxy Not directly supported. Direct SOCKS5 support via Proxy property set to new WebProxy("socks5://...")
Default in .NET Default for .NET Framework. Default for .NET Core 2.1+ / .NET 5+.

Configuring Proxy with SocketsHttpHandler

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class SocketsHttpHandlerProxySetup
{
    public static async Task Main(string[] args)
    {
        string proxyAddress = "http://your.proxy.server:8080";
        string targetUrl = "http://httpbin.org/get";

        var webProxy = new WebProxy(proxyAddress);

        // SocketsHttpHandler is the default in modern .NET, but can be explicitly used
        var handler = new SocketsHttpHandler
        {
            Proxy = webProxy, // Assign IWebProxy instance
            UseProxy = true,  // Explicitly enable proxy usage
            AllowAutoRedirect = true, // Example of other SocketsHttpHandler properties
            PooledConnectionLifetime = TimeSpan.FromMinutes(5)
        };

        using (var httpClient = new HttpClient(handler))
        {
            try
            {
                HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("Request successful using SocketsHttpHandler.");
                Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"Request error: {e.Message}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error: {e.Message}");
            }
        }
    }
}

For using the system default proxy with SocketsHttpHandler, set UseProxy = true and Proxy = WebRequest.DefaultWebProxy. If Proxy is null and UseProxy is true, SocketsHttpHandler will attempt to use the system's default proxy.

Error Handling and Debugging

When encountering issues with proxy configuration, consider the following:
* Network Connectivity: Verify that the application host can reach the proxy server.
* Proxy Server Status: Ensure the proxy server is operational and correctly configured.
* Authentication: Double-check proxy credentials. Incorrect credentials often result in HTTP 407 Proxy Authentication Required errors.
* Firewall Rules: Check local and network firewall rules that might block traffic to or from the proxy.
* Proxy Logs: If access to the proxy server logs is available, inspect them for connection attempts and errors.
* Exceptions: Catch HttpRequestException and WebException (for HttpClientHandler in .NET Framework) for detailed error messages.

Security Considerations

  • Trust: Only route traffic through trusted proxy servers. Malicious proxies can intercept, modify, or log sensitive data.
  • Credentials: Store proxy credentials securely, avoiding hardcoding them directly in source code. Use environment variables, configuration files, or secret management services.
  • SSL/TLS: Ensure the proxy properly handles SSL/TLS traffic. If the proxy performs SSL inspection (Man-in-the-Middle), the application might require trusting an additional root certificate authority. HttpClientHandler has a ServerCertificateCustomValidationCallback property for custom certificate validation, but this should be used with caution.
Auto-update: 03.03.2026
All Categories

Advantages of our proxies

25,000+ proxies from 120+ countries