← Back to Code Snippets

C# HttpClient Proxy

Complete HttpClient proxy integration example for C# with Hex Proxies. Includes authentication, timeouts, and error handling.

C#HttpClient
Install:dotnet new console (built-in System.Net.Http)
C# / HttpClient
using System.Net;
using System.Net.Http;

var proxy = new WebProxy("http://gate.hexproxies.com:8080")
{
    Credentials = new NetworkCredential("user", "pass"),
};

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

using var client = new HttpClient(handler)
{
    Timeout = TimeSpan.FromSeconds(30),
};

try
{
    var response = await client.GetStringAsync("https://httpbin.org/ip");
    Console.WriteLine(
quot;Response: {response}"); } catch (HttpRequestException ex) { Console.WriteLine(
quot;Request failed: {ex.Message}"); } catch (TaskCanceledException) { Console.WriteLine("Request timed out"); }

Why C# for Proxy Work

C# and the .NET platform provide a unique combination of high performance, strong typing, and enterprise-grade tooling that makes them well-suited for production proxy integrations. The .NET runtime's ahead-of-time compilation (NativeAOT in .NET 8+), efficient garbage collector, and optimized networking stack deliver throughput comparable to Go and Rust while maintaining the developer productivity of a managed language. For organizations already invested in the Microsoft ecosystem, C# proxy integrations plug directly into ASP.NET Core web services, Azure Functions, and Windows services without introducing new languages or runtime dependencies.

The System.Net.Http namespace, included in every .NET installation since .NET Core 1.0, provides a mature HTTP client stack with native proxy support, connection pooling, and HTTP/2 capabilities. Unlike dynamic languages where proxy libraries may have subtle compatibility issues across runtime versions, C#'s compiled nature catches configuration errors at build time. The HttpClient class is designed for long-lived reuse and internally manages connection pools to gate.hexproxies.com:8080, making it efficient for high-volume proxy workloads.

Configuration Patterns

C# separates proxy configuration into three layers. The WebProxy object encapsulates the proxy address, credentials, and bypass rules. The HttpClientHandler connects the proxy to the HTTP pipeline and provides TLS settings, cookie management, and redirect behavior. The HttpClient wraps everything with timeout configuration and a high-level request API. This layered design allows you to swap proxy configurations without rebuilding the entire client stack.

In ASP.NET Core applications, use IHttpClientFactory to manage HttpClient lifetimes and proxy configuration. Register a named client with proxy settings in Startup.ConfigureServices() using services.AddHttpClient("proxied", client => { ... }).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { Proxy = proxy }). The factory handles connection pool management, DNS refresh, and handler lifecycle, preventing the socket exhaustion issues that plague manually created HttpClient instances.

Common Pitfalls

The most impactful mistake in C# proxy code is creating and disposing HttpClient instances per request. Despite implementing IDisposable, HttpClient is designed for reuse. Each new instance creates a new connection pool with fresh DNS resolution and TCP connections, and the disposed instance's sockets linger in TIME_WAIT state for up to 240 seconds. In a proxy workload making hundreds of requests per second, this rapidly exhausts available sockets and causes SocketException errors. Use a single HttpClient instance or IHttpClientFactory.

TaskCanceledException in C# serves double duty for both user-initiated cancellation and timeout expiration, which makes proxy timeout detection ambiguous. When catching this exception, check ex.CancellationToken.IsCancellationRequested to distinguish between a timeout (where it is false) and a cancellation (where it is true). In .NET 5+, timeout-caused cancellations throw TaskCanceledException with an inner TimeoutException, making the distinction clearer but still requiring attention.

Performance Optimization

.NET 6+ introduced the SocketsHttpHandler as the default handler, replacing HttpClientHandler with a more efficient implementation that provides fine-grained control over connection pooling. Set PooledConnectionLifetime to rotate proxy connections periodically (prevents stale connections), MaxConnectionsPerServer to control concurrency to the proxy gateway, and PooledConnectionIdleTimeout to reclaim unused connections. These settings directly affect proxy throughput and resource utilization.

For maximum concurrency, use Task.WhenAll() with a SemaphoreSlim to control parallelism. Launch hundreds of proxied requests as tasks, bounded by the semaphore to match your proxy allocation's capacity. The async/await pattern in C# is zero-allocation for synchronous completions and uses efficient state machines for asynchronous continuations, making it competitive with Go's goroutines for I/O-bound proxy workloads. Profile with dotnet-trace and dotnet-counters to monitor HTTP connection pool utilization and identify bottlenecks.

Tips

  • 1
    Reuse HttpClient instances to avoid socket exhaustion.
  • 2
    Use IHttpClientFactory in ASP.NET Core for proper lifecycle management.
  • 3
    Catch TaskCanceledException to handle timeouts separately from other errors.

Ready to Integrate?

Get proxy credentials and start coding in minutes.