<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ProxiesThatWork]]></title><description><![CDATA[ProxiesThatWork]]></description><link>https://proxiesthatwork.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>ProxiesThatWork</title><link>https://proxiesthatwork.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 15 Sep 2026 20:16:21 GMT</lastBuildDate><atom:link href="https://proxiesthatwork.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Use a Proxy in Rust: A reqwest Client Guide]]></title><description><![CDATA[If you're building an HTTP client in Rust and need to route requests through a proxy, reqwest handles it natively. You don't need a separate crate.
Build a Proxy with reqwest::Proxy::http(), pass it t]]></description><link>https://proxiesthatwork.hashnode.dev/how-to-use-a-proxy-in-rust-reqwest-guide</link><guid isPermaLink="true">https://proxiesthatwork.hashnode.dev/how-to-use-a-proxy-in-rust-reqwest-guide</guid><category><![CDATA[Rust]]></category><category><![CDATA[proxy]]></category><category><![CDATA[webscraping ]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[ProxiesThatWork]]></dc:creator><pubDate>Thu, 10 Sep 2026 11:48:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a4e698352e0d13e098868e1/b3c733d4-0d42-44ab-b524-5f9d4e7726e0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you're building an HTTP client in Rust and need to route requests through a proxy, reqwest handles it natively. You don't need a separate crate.</p>
<p>Build a <code>Proxy</code> with <code>reqwest::Proxy::http()</code>, pass it to <code>ClientBuilder::proxy()</code>, and every request made with that client goes through it. That's the whole setup.</p>
<p>Here's the minimal version:</p>
<pre><code class="language-rust">use reqwest::{Client, Proxy};

#[tokio::main]
async fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error&gt;&gt; {
    let client = Client::builder()
        .proxy(Proxy::http("http://proxy-host:proxy-port")?)
        .build()?;

let body = client
    .get("https://example.com")
    .send()
    .await?
    .text()
    .await?;

println!("{body}");
Ok(())

}
</code></pre>
<p>That's it. Every request made with <code>client</code> now goes through the proxy.</p>
<h2>HTTP-only, HTTPS-only, or both</h2>
<p>reqwest gives you three constructors depending on what you want routed:</p>
<ul>
<li><p><code>Proxy::http(url)</code> — proxies HTTP requests only</p>
</li>
<li><p><code>Proxy::https(url)</code> — proxies HTTPS requests only</p>
</li>
<li><p><code>Proxy::all(url)</code> — proxies everything, regardless of scheme</p>
</li>
</ul>
<p>Most setups just want everything routed the same way, so <code>Proxy::all()</code> is usually the one you reach for:</p>
<pre><code class="language-rust">let client = Client::builder()
    .proxy(Proxy::all("http://proxy-host:proxy-port")?)
    .build()?;
</code></pre>
<p>If you need different proxies for different destinations; say, one proxy for a specific domain and a fallback for everything else, chain multiple <code>.proxy()</code> calls on the builder, or use <code>Proxy::custom()</code> with a closure that returns the right proxy URL per request.</p>
<h2>Adding authentication</h2>
<p>Most paid proxies need a username and password. reqwest has a method for exactly this, you don't build the header yourself:</p>
<pre><code class="language-rust">let proxy = Proxy::all("http://proxy-host:proxy-port")?
    .basic_auth("username", "password");

let client = Client::builder().proxy(proxy).build()?;
</code></pre>
<p><code>basic_auth()</code> sets the <code>Proxy-Authorization</code> header on every request that goes through this proxy. If your provider expects a non-Basic auth scheme, <code>custom_http_auth()</code> takes a raw header value instead, so you're not locked into Basic if your provider doesn't use it.</p>
<h2>Using environment variables instead of hardcoding</h2>
<p>If you don't call <code>.proxy()</code> at all, reqwest still checks <code>HTTP_PROXY</code>, <code>HTTPS_PROXY</code>, and <code>NO_PROXY</code> in your environment and uses them automatically:</p>
<pre><code class="language-rust">let client = Client::builder().build()?;
// picks up HTTP_PROXY / HTTPS_PROXY / NO_PROXY if they're set
</code></pre>
<p>This is on by default, so it's worth knowing how to turn off if you want a client that never proxies, regardless of what's in the environment:</p>
<pre><code class="language-rust">let client = Client::builder()
    .no_proxy()
    .build()?;
</code></pre>
<p><code>no_proxy()</code> here disables all proxying on the client, including the automatic environment-variable lookup. That's different from <code>Proxy::no_proxy()</code>, which sets a bypass list on one specific proxy, don't confuse the two.</p>
<h2>Turning on SOCKS5 support</h2>
<p>reqwest's SOCKS5 support sits behind a Cargo feature, so if your proxy provider gives you a <code>socks5://</code> address, add the feature first:</p>
<pre><code class="language-[dependencies]">[dependencies]
reqwest = { version = "0.12", features = ["socks"] }
</code></pre>
<p>Then point <code>Proxy::all()</code> at the SOCKS5 URL the same way you would an HTTP one:</p>
<pre><code class="language-rust">let client = Client::builder()
    .proxy(Proxy::all("socks5://proxy-host:proxy-port")?)
    .build()?;
</code></pre>
<p>Skip this step and you'll get a compile error the moment you try to build a <code>socks5://</code> proxy URL, not a runtime failure, so it's an easy one to catch early.</p>
<h2>Confirming the proxy is actually being used</h2>
<p>A <code>200 OK</code> response isn't proof the proxy is in the request path. If your proxy config is silently ignored, you'll still reach the target site directly and never notice.</p>
<p>Hit an IP-echo endpoint with and without the proxy, and compare:</p>
<pre><code class="language-rust">let body = client
    .get("https://api.ipify.org")
    .send()
    .await?
    .text()
    .await?;
</code></pre>
<p>If the returned IP matches your proxy's IP, not your machine's, the proxy is doing its job. If it matches your own connection, check that the <code>Client</code> you're using is the one you built with <code>.proxy()</code>, it's easy to accidentally send a request through a plain <code>Client::new()</code> left over from earlier in the code.</p>
<h2>Handling the errors you'll actually hit</h2>
<p>Three errors show up most often once you're running this against a real proxy:</p>
<p><code>error sending request... error trying to connect: tcp connect error</code> The proxy host or port is wrong, or the proxy is down. Check the address before debugging anything else in your code.</p>
<p><code>407 Proxy Authentication Required</code> Your credentials are missing or wrong. If a password contains special characters, make sure it's URL-encoded before it goes into the proxy URL string, or pass it through <code>basic_auth()</code> instead of embedding it in the URL.</p>
<p><strong>Requests that hang and eventually time out</strong> Set an explicit timeout so a dead proxy fails fast instead of hanging your program:</p>
<pre><code class="language-rust">let client = Client::builder()
    .proxy(Proxy::all("http://proxy-host:proxy-port")?)
    .timeout(std::time::Duration::from_secs(10))
    .build()?;
</code></pre>
<p>Without this, a client using a bad proxy can hang far longer than you'd expect, reqwest doesn't apply a request timeout by default.</p>
<h2>Putting it together</h2>
<p>For most Rust projects, this is enough:</p>
<pre><code class="language-rust">use reqwest::{Client, Proxy};
use std::time::Duration;

fn build_proxy_client(
    proxy_url: &amp;str,
    username: &amp;str,
    password: &amp;str,
) -&gt; Result&lt;Client, reqwest::Error&gt; {
    let proxy = Proxy::all(proxy_url)?.basic_auth(username, password);

    Client::builder()
        .proxy(proxy)
        .timeout(Duration::from_secs(10))
        .build()
}

#[tokio::main]
async fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error&gt;&gt; {
    let client = build_proxy_client("http://proxy-host:proxy-port", "username", "password")?;

    let resp = client.get("https://example.com").send().await?;
    println!("status: {}", resp.status());
    Ok(())
}
</code></pre>
<p>One <code>Client</code>, built once, reused across every request that needs to go through the proxy. No dependencies beyond reqwest itself, plus the <code>socks</code> feature if you're on SOCKS5.</p>
<p>If you're testing this against a real proxy pool rather than a single static proxy, keep in mind that providers billing <a href="https://www.proxiesthatwork.com/">per successfully authenticated IP</a> expect exactly this kind of username/password setup, so the code above should work against most of them without changes beyond the host, port, and credentials.</p>
]]></content:encoded></item></channel></rss>