C# HttpClient Proxy Setup: Credentials, Bypass, and Reuse

Configure a proxy for C# HttpClient with HttpClientHandler and WebProxy, separate proxy credentials, apply narrow bypass rules, reuse connections, and verify the route.

Written by the Mexela Editorial Team. Technical guides are reviewed by the Mexela Technical Team under the Mexela Editorial Policy.

C sharp HttpClient request objects passing through a red proxy gateway to a secure web service

Key topics:

PROXY PLANS

Ready to buy proxies for this workflow?

Use the guide below to choose the right proxy type, then start with private proxies for dedicated IPv4 access or shared proxies when price matters more.

To use a proxy with C# HttpClient, create a WebProxy for http://HOST:PORT, assign it to HttpClientHandler.Proxy, set UseProxy = true, and build one reusable HttpClient from that handler. Put proxy credentials on the WebProxy.Credentials property, not on HttpClientHandler.Credentials, because the latter authenticates with the destination server.

Scope: this guide covers explicit HTTP forward-proxy configuration for modern .NET applications outside browser-only runtimes. It keeps TLS certificate validation enabled and separates proxy authentication, origin authentication, bypass rules, timeouts, and connection reuse. For protocol background, start with HTTP, HTTPS, and SOCKS5 proxy behavior; for adjacent language guides, use the Developer Guides hub.

Create a small console project for the first acceptance test

Use a maintained .NET SDK approved by the project. Create a disposable console application so proxy behavior can be tested without unrelated dependency injection, retry middleware, destination tokens, or application state.

dotnet new console -n ProxyCheck
cd ProxyCheck
dotnet --info

Record the runtime and operating system. Proxy defaults and authentication can vary between environments, especially when an application inherits corporate system settings. The first version should configure the route explicitly so the result is attributable.

Configure HttpClientHandler with an explicit proxy

The official HttpClientHandler.Proxy documentation states that the property supplies proxy information for internet requests and overrides the local machine or application proxy setting when specified. Use an absolute proxy URI and keep endpoint components outside source control.

using System.Net;
using System.Net.Http;

var proxyUri = new Uri("http://HOST:PORT");
var proxy = new WebProxy(proxyUri);

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

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

The scheme in proxyUri describes the client-to-proxy connection. An HTTP proxy commonly creates a CONNECT tunnel for an HTTPS destination. Do not change the proxy scheme to https merely because the requested URL uses HTTPS; use the scheme documented for the assigned gateway.

UseProxy = true makes the intention obvious. Setting it to false bypasses even an assigned Proxy. Keep both values in the same construction method so a configuration refactor cannot leave contradictory settings.

Use WebProxy for endpoint, credentials, and bypass policy

The current WebProxy reference implements IWebProxy and provides the proxy address, credentials, local bypass behavior, and bypass list. A minimal explicit object is easier to review than relying on ambient desktop settings in a server process.

Read non-secret endpoint values from validated configuration. Reject an empty host, non-numeric port, unsupported scheme, or URI containing unexpected path/query components before constructing the handler. Avoid printing the full URI after credentials are attached.

Set proxy credentials on the proxy object

For username/password proxy authentication, use NetworkCredential on WebProxy.Credentials:

var proxy = new WebProxy(new Uri("http://HOST:PORT"))
{
    Credentials = new NetworkCredential("USER", "PASSWORD")
};

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

In production, replace the literal placeholders with values obtained from a secret provider at runtime. Do not store the password in appsettings.json, source control, exception messages, telemetry properties, or command-line arguments. A secret visible in process listings or build artifacts should be rotated.

HttpClientHandler.Credentials belongs to authentication requested by the destination server. DefaultProxyCredentials applies to the default system proxy when no explicit Proxy object is assigned. Microsoft documents this distinction in the DefaultProxyCredentials property. Setting every credential-related property “just in case” can leak ambient identities and makes a 401 impossible to distinguish from a 407.

The proxy authentication guide explains when source-IP allowlisting is preferable. If the application runs behind dynamic egress, do not allowlist an old public address and then compensate with repeated credential guesses.

Apply narrow bypass rules

A bypass sends selected destinations directly. Use it for explicit local or internal routes that must not traverse the external proxy. Do not treat the bypass as a performance shortcut because it changes the security and observation boundary.

var proxy = new WebProxy(new Uri("http://HOST:PORT"))
{
    Credentials = new NetworkCredential("USER", "PASSWORD"),
    BypassProxyOnLocal = true,
    BypassList = new[]
    {
        @"^localhost$",
        @"^127\.0\.0\.1$",
        @"^service\.internal\.example$"
    }
};

BypassList entries are regular-expression patterns in WebProxy. Escape dots and anchor a host when the intention is exact. A loose pattern such as example can match more destinations than expected. Test one route that must be proxied and one that must bypass, then record the observed path.

BypassProxyOnLocal has platform and naming implications. A flat host name, loopback address, and fully qualified internal name may not be classified identically. Explicit patterns are clearer when a server’s outbound policy depends on the distinction.

Reuse HttpClient and its connections

The official HttpClient guidelines recommend reusing clients so connection pools are reused and ports are not exhausted. A proxy adds another connection boundary, which makes per-request handler creation even less attractive.

In a small console acceptance test, using is fine because the process exits after one run. In a long-lived service, keep a static or singleton client with an appropriate PooledConnectionLifetime, or use IHttpClientFactory. Do not create and dispose a new handler for every request.

var sockets = new SocketsHttpHandler
{
    Proxy = proxy,
    UseProxy = true,
    PooledConnectionLifetime = TimeSpan.FromMinutes(5),
    ConnectTimeout = TimeSpan.FromSeconds(10)
};

var client = new HttpClient(sockets)
{
    Timeout = TimeSpan.FromSeconds(30)
};

Choose a pooled lifetime based on DNS, infrastructure rotation, and service behavior. Reuse does not mean “keep every connection forever,” and a short lifetime is not a retry policy. Measure connection churn and latency before tuning.

Verify the exit and response shape

Make one HTTPS request to a trusted endpoint that returns the caller’s address. Require success, validate the content type or JSON shape, and parse the address. The same client instance should then run the approved application smoke test.

using System.Net.Http.Json;

var result = await client.GetFromJsonAsync<IpResult>(
    "https://api.ipify.org?format=json");

if (result is null || !IPAddress.TryParse(result.Ip, out var observedIp))
{
    throw new InvalidOperationException("Exit check returned an invalid response.");
}

Console.WriteLine(new { ExitIp = observedIp.ToString() });

public sealed record IpResult(string Ip);

Expected observation: the request completes within the bounded timeout, TLS validation succeeds, the response contains a valid public address, and the address matches the assigned proxy exit rather than a separately recorded direct baseline.

A direct baseline must use a deliberately direct handler, not the same handler with an ambiguous bypass. Keep baseline and proxied results in separate records. If they match, confirm whether the provider intentionally routes through the same public address before assuming the proxy was ignored.

Use cancellation and classify timeouts

HttpClient.Timeout bounds the request, while a caller-provided CancellationToken lets the application stop work when a job is cancelled. Preserve whether cancellation was caller-requested or caused by a timeout.

using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20));
using var response = await client.GetAsync(
    "https://DESTINATION.example/approved-health",
    HttpCompletionOption.ResponseHeadersRead,
    cancellation.Token);

Console.WriteLine(new
{
    Status = (int)response.StatusCode,
    Reason = response.ReasonPhrase
});

Read response bodies with a size limit appropriate to the application. A 403, 429, or application error can prove the tunnel succeeded far enough to reach the destination. It is not a general instruction to change IPs.

Keep TLS certificate validation enabled

Do not set ServerCertificateCustomValidationCallback to accept every certificate. That converts a visible hostname, trust-chain, or interception failure into silent exposure of destination data and credentials. Check the device clock, destination hostname, trust store, and approved enterprise inspection policy.

If direct TLS succeeds but proxied TLS presents an unexpected issuer, stop and identify the accountable network component. Do not install an unknown root certificate from an error page or proxy list.

HttpClient proxy troubleshooting by symptom

Signal Likely boundary First check
Name resolution or connection refused Gateway DNS, route, port, or listener Validate HOST:PORT and the proxy URI scheme
407 Proxy authentication Check WebProxy.Credentials, account state, or allowlisted public IP
401 Destination authentication Inspect origin credentials without changing proxy credentials
Certificate exception TLS trust or interception Inspect chain and hostname; keep validation enabled
Request unexpectedly direct UseProxy, bypass rule, or another handler Inspect the actual client/handler instance and destination host
Socket or port exhaustion Client/handler lifetime Reuse clients and review connection pooling
Only one destination fails Destination policy or application response Compare the neutral exit check and preserve status

Use the layered proxy test and common proxy errors guide before replacing endpoints. Log the sanitized gateway label, destination host, status class, duration, and failing stage; never log proxy passwords, authorization headers, cookies, or response bodies containing sensitive data.

A production-friendly configuration boundary

Represent proxy configuration as validated options: enabled flag, scheme, host, port, authentication mode, secret references, and exact bypass hosts. Construct the handler once during service startup. Fail startup when enabled configuration is incomplete instead of silently falling back to a direct route.

Expose non-secret diagnostics such as “proxy enabled,” endpoint label, bypass count, and client lifetime. Keep the password in the secret provider and inject it only when the WebProxy is built. If configuration reload is required, create a new handler/client generation and retire the old pool predictably rather than mutating a handler with active requests.

Responsible-use boundary: send only authorized requests, follow destination terms and aggregate rate limits, bound concurrency and retries, and treat a denial as a stop signal for review. A stable proxy makes attribution and diagnostics easier; it does not grant permission or make destination data non-sensitive.

Select an endpoint after the client lifecycle is correct

Record the required country, authentication model, bypass policy, concurrent requests, session duration, connect/overall timeouts, and observed latency. If the approved service needs an exclusive stable route, compare those requirements with current private proxy options only after exit verification, application smoke testing, and client reuse are proven.