Before you start

  • The .NET SDK, version 6 or later. The code relies on the implicit usings and top-level statements that the console template has produced since .NET 6.
  • A terminal. Step 1 creates the project with dotnet new console.
  • HOST, PORT, USERNAME and PASSWORD copied from the service page.

Your connection details

Sign in to the dashboard and open the service you bought. Its page shows the host, port, username and password for that service. There is no single ProxyPanda address to remember, so copy them from there each time. The code in these guides uses the placeholders below; replace each one with your own value.

HOST
The proxy address for this service, exactly as the service page shows it.
PORT
The port to connect to. Copy it with the host, since it can differ from one service to the next.
USERNAME
Your proxy login. It is separate from the email you use for the dashboard.
PASSWORD
Copy it in full. On residential, the options you choose in the dashboard are added to the end of the password, so a password typed from memory loses them.

You can skip the username and password by adding the IP address you connect from to the service’s allowlist. Then only HOST and PORT go into your code.

The examples use HTTP, which reaches https sites through an encrypted tunnel. SOCKS5 works too: residential ports accept both, and ISP and datacenter proxies switch protocol in the dashboard.

Steps

  1. Create a console project

    dotnet --version confirms the SDK. The template writes a Program.cs with implicit usings, so each example below adds a single using line, which brings in WebProxy and NetworkCredential. Replace Program.cs with an example and start it with dotnet run.

    terminal
    dotnet --version
    dotnet new console -o ProxyCheck
    cd ProxyCheck
  2. Give the handler a WebProxy with credentials

    WebProxy takes the proxy as http://HOST:PORT, and its Credentials property carries USERNAME and PASSWORD. UseProxy defaults to true; it is written out because a handler with UseProxy set to false ignores its Proxy without complaint. HttpClient.Timeout caps each request, the tunnel setup included.

    Program.cs
    using System.Net;
    
    var handler = new HttpClientHandler
    {
        Proxy = new WebProxy("http://HOST:PORT")
        {
            Credentials = new NetworkCredential("USERNAME", "PASSWORD"),
        },
        UseProxy = true,
    };
    
    using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
    
    var response = await client.GetAsync("https://api.ipify.org?format=json");
    Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
  3. Run it and read the exit address

    dotnet run builds and starts the project, which prints 200 and the JSON from api.ipify.org. The test proxy logged two CONNECT requests: the first without a login, refused with 407, then a second carrying it. The handler deals with that challenge on its own.

  4. Keep one HttpClient per proxy

    A new HttpClient disposed after every request closes its connection each time, and each closed socket sits in TIME_WAIT for a while afterwards. Under steady load the machine can run out of local ports, which surfaces as connection errors that have nothing to do with the proxy. Create clients once and reuse them for the life of the program.

  5. Rotate across static IPs with SocketsHttpHandler

    This second Program.cs reads proxies.txt from the project folder, one HOST:PORT:USERNAME:PASSWORD line per fixed IP, and builds a SocketsHttpHandler with its own HttpClient for each line. ConnectTimeout bounds the connection to the proxy, and PooledConnectionLifetime retires pooled connections after five minutes. Request i goes to client i modulo the list length; a proxy that fails prints its message and the others carry on.

    Program.cs
    using System.Net;
    
    var clients = File.ReadLines("proxies.txt")
        .Where(line => !string.IsNullOrWhiteSpace(line))
        .Select(line =>
        {
            var p = line.Trim().Split(':', 4);
            var handler = new SocketsHttpHandler
            {
                Proxy = new WebProxy(p[0], int.Parse(p[1]))
                {
                    Credentials = new NetworkCredential(p[2], p[3]),
                },
                UseProxy = true,
                ConnectTimeout = TimeSpan.FromSeconds(10),
                PooledConnectionLifetime = TimeSpan.FromMinutes(5),
            };
            return new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
        })
        .ToList();
    
    for (var i = 0; i < 6; i++)
    {
        var client = clients[i % clients.Count];
        try
        {
            Console.WriteLine($"{i} {await client.GetStringAsync("https://api.ipify.org")}");
        }
        catch (Exception e) when (e is HttpRequestException or TaskCanceledException)
        {
            Console.WriteLine($"{i} {e.Message}");
        }
    }

Rotating and sticky IPs

A handler pools connections. In testing, three requests through one client shared a single CONNECT tunnel, and a shared tunnel keeps one exit address. On Sticky IP and on ISP or datacenter IPs that is the goal.

On residential with Randomize IP, set PooledConnectionLifetime to TimeSpan.Zero, or set Headers.ConnectionClose to true on each HttpRequestMessage. Either one produced a new tunnel for every request in testing, and each new tunnel can leave from a different address.

One HttpClient can serve many concurrent tasks, so a worker pool needs a client per proxy and no more.

Common errors and fixes

HttpRequestException: The proxy tunnel request to proxy '…' failed with status code '407'

The proxy turned down the login. Copy USERNAME and PASSWORD again, and check the NetworkCredential sits on the WebProxy: Credentials on the handler itself are sent to the site, not the proxy.

HttpRequestException: Connection refused

Nothing is listening at HOST:PORT from your network. Compare both values with the service page and check that the service has not expired.

TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout

No answer came back inside HttpClient.Timeout. Residential exits run over home connections and some are slow, so allow more time for those requests and retry the single URL that failed.

The response shows your own IP

The WebProxy was set on a different handler from the one passed to HttpClient, or UseProxy is false. Build the handler, assign Proxy, then hand that same instance to the client.

Which line to pick

C# services that call APIs or fetch pages in volume stay cheapest on datacenter IPs wherever the target accepts them. Switch to residential once server ranges get refused, and pin a long-running worker to an ISP IP when it needs the same address across sessions.

Stuck on a step?

Paste the command and the error into Discord, with your password taken out. People there have met most of these errors before.

Join the Discorddiscord.gg/proxypanda
Start with $5Ask in Discord