All articles
cURLproxy setupresidential proxies

How to Set Up a Proxy with cURL (Every Option Explained)

JL
James Liu
Lead Engineer @ ProxyLabs
March 15, 2026
8 min read
Share

cURL is the fastest way to test a proxy connection — one command and you know if it's working, what IP you're getting, and how fast the response is. But cURL has over a dozen proxy-related flags, and the documentation doesn't explain when to use which. This is the complete reference for every proxy option in cURL, with working examples using residential proxies.

Basic Proxy Syntax

There are three ways to specify a proxy in cURL:

# Method 1: -x / --proxy flag (most common)
curl -x http://gate.proxylabs.app:8080 https://httpbin.org/ip

# Method 2: Environment variable
export https_proxy=http://gate.proxylabs.app:8080
curl https://httpbin.org/ip

# Method 3: .curlrc config file
echo "proxy = http://gate.proxylabs.app:8080" >> ~/.curlrc
curl https://httpbin.org/ip

Method 1 is best for testing. Method 2 is best for scripts where every request should go through the proxy. Method 3 is useful for development machines, but be aware it affects all cURL commands — including package managers and other tools that use cURL under the hood.

Proxy Authentication

Most residential proxies require username/password. cURL supports auth in the URL or via a separate flag:

# Auth in URL (simplest)
curl -x http://your-username:[email protected]:8080 https://httpbin.org/ip

# Auth via --proxy-user flag (avoids credentials in URL)
curl -x http://gate.proxylabs.app:8080 \
     --proxy-user your-username:your-password \
     https://httpbin.org/ip

# Auth via -U shorthand
curl -x http://gate.proxylabs.app:8080 \
     -U your-username:your-password \
     https://httpbin.org/ip

The --proxy-user flag is preferred in scripts because the proxy URL won't contain credentials if it shows up in logs or ps output. That said, cURL does try to hide credentials from ps by overwriting the argument in memory after parsing.

Geo-Targeting

With ProxyLabs, append country and city modifiers to the username:

# US IP
curl -x http://gate.proxylabs.app:8080 \
     -U your-username-country-US:your-password \
     https://httpbin.org/ip

# UK IP from London
curl -x http://gate.proxylabs.app:8080 \
     -U your-username-country-GB-city-London:your-password \
     https://httpbin.org/ip

# German IP from Berlin
curl -x http://gate.proxylabs.app:8080 \
     -U your-username-country-DE-city-Berlin:your-password \
     https://httpbin.org/ip

Verify the IP location with the ProxyLabs IP Lookup tool.

Sticky Sessions

By default, each cURL request through a rotating proxy gets a different IP. To keep the same IP across multiple requests, add a session ID:

# All three requests use the same IP
curl -x http://gate.proxylabs.app:8080 \
     -U your-username-session-mysession01:your-password \
     https://httpbin.org/ip

curl -x http://gate.proxylabs.app:8080 \
     -U your-username-session-mysession01:your-password \
     https://httpbin.org/ip

curl -x http://gate.proxylabs.app:8080 \
     -U your-username-session-mysession01:your-password \
     https://httpbin.org/ip

The session ID can be any string. It stays active for up to 30 minutes. For more on when to use sticky vs rotating, see rotating vs sticky proxies.

HTTPS Through Proxies (CONNECT Tunneling)

When you curl an HTTPS URL through an HTTP proxy, cURL uses the CONNECT method to establish a tunnel. The proxy sees the hostname but can't read the encrypted traffic.

# This automatically uses CONNECT for HTTPS
curl -x http://your-username:[email protected]:8080 \
     https://httpbin.org/ip

# Force tunnel mode explicitly
curl -x http://your-username:[email protected]:8080 \
     --proxytunnel \
     https://httpbin.org/ip

The --proxytunnel flag is usually unnecessary — cURL uses tunneling automatically for HTTPS. But it's useful when you want to tunnel non-HTTP protocols through an HTTP proxy.

SOCKS5 Proxies

If your proxy provider supports SOCKS5 (ProxyLabs' gateway is HTTP, but this is useful to know):

# SOCKS5 proxy
curl --socks5 proxy-host:1080 https://httpbin.org/ip

# SOCKS5 with authentication
curl --socks5 proxy-host:1080 \
     --proxy-user username:password \
     https://httpbin.org/ip

# SOCKS5 with DNS resolved by the proxy (recommended — prevents DNS leaks)
curl --socks5-hostname proxy-host:1080 \
     --proxy-user username:password \
     https://httpbin.org/ip

The difference between --socks5 and --socks5-hostname matters: --socks5 resolves DNS locally (your machine resolves the domain, then sends the IP to the proxy). --socks5-hostname sends the domain name to the proxy, which resolves it. Use --socks5-hostname to avoid DNS leaks.

Every Proxy-Related cURL Flag

FlagDescriptionExample
-x, --proxySet proxy URL-x http://proxy:8080
-U, --proxy-userProxy credentials-U user:pass
--proxy-basicForce Basic auth (default)--proxy-basic
--proxy-digestUse Digest auth--proxy-digest
--proxy-ntlmUse NTLM auth--proxy-ntlm
--proxy-headerSend header only to proxy--proxy-header "X-Custom: val"
--proxytunnelForce CONNECT tunnel--proxytunnel
--proxy-insecureSkip proxy TLS verification--proxy-insecure
--proxy-cacertCA cert for proxy connection--proxy-cacert ca.pem
--proxy-certClient cert for proxy--proxy-cert client.pem
--noproxyBypass proxy for hosts--noproxy localhost,127.0.0.1
--socks5SOCKS5 proxy--socks5 proxy:1080
--socks5-hostnameSOCKS5 + remote DNS--socks5-hostname proxy:1080
--socks4SOCKS4 proxy--socks4 proxy:1080
--preproxyFirst proxy in chain--preproxy socks5://first:1080

Useful Debugging Flags

When your proxy isn't working, these flags help diagnose the issue:

# Verbose output — shows connection details, headers, TLS handshake
curl -v -x http://your-username:[email protected]:8080 \
     https://httpbin.org/ip

# Show timing breakdown
curl -x http://your-username:[email protected]:8080 \
     -o /dev/null -s -w "\
     DNS lookup:  %{time_namelookup}s\n\
     Connect:     %{time_connect}s\n\
     TLS:         %{time_appconnect}s\n\
     First byte:  %{time_starttransfer}s\n\
     Total:       %{time_total}s\n\
     HTTP code:   %{http_code}\n" \
     https://httpbin.org/ip

# Write response headers to stderr
curl -x http://your-username:[email protected]:8080 \
     -D - https://httpbin.org/ip

The timing breakdown is especially useful. Typical values with residential proxies:

PhaseExpected rangeIf too high
DNS lookup0-50msDNS resolution issue (not proxy-related)
Connect20-150msNetwork path to proxy gateway
TLS handshake50-200msTLS negotiation with target via proxy
First byte100-500msProxy routing + target server response
Total200-1000msNormal for residential proxy

Scripting with cURL and Proxies

Batch Requests with IP Rotation

#!/bin/bash
# Scrape multiple URLs with rotating IPs

PROXY_HOST="gate.proxylabs.app:8080"
PROXY_USER="your-username"
PROXY_PASS="your-password"

URLS=(
    "https://example.com/page/1"
    "https://example.com/page/2"
    "https://example.com/page/3"
)

for url in "${URLS[@]}"; do
    echo "Fetching: $url"
    curl -s -x "http://${PROXY_HOST}" \
         -U "${PROXY_USER}:${PROXY_PASS}" \
         -o "$(basename "$url").html" \
         -w "  Status: %{http_code}, Time: %{time_total}s, Size: %{size_download} bytes\n" \
         "$url"
    sleep $((RANDOM % 3 + 2))  # 2-4 second random delay
done

Parallel Requests with xargs

#!/bin/bash
# Parallel cURL with proxies — 5 concurrent requests

PROXY="http://your-username:[email protected]:8080"

cat urls.txt | xargs -P 5 -I {} \
    curl -s -x "$PROXY" \
         -o "/tmp/output_{#}.html" \
         -w "{} -> %{http_code} (%{time_total}s)\n" \
         {}

Testing Proxy Rotation

Verify that each request gets a different IP:

#!/bin/bash
# Confirm IP rotation — should show 10 different IPs

PROXY_HOST="gate.proxylabs.app:8080"
PROXY_USER="your-username"
PROXY_PASS="your-password"

echo "Testing IP rotation (10 requests):"
for i in $(seq 1 10); do
    IP=$(curl -s -x "http://${PROXY_HOST}" \
         -U "${PROXY_USER}:${PROXY_PASS}" \
         https://httpbin.org/ip | grep -o '"origin": "[^"]*"' | cut -d'"' -f4)
    echo "  Request $i: $IP"
done

Testing Geo-Targeting

#!/bin/bash
# Verify geo-targeting for different countries

PROXY_HOST="gate.proxylabs.app:8080"
PROXY_PASS="your-password"

COUNTRIES=("US" "GB" "DE" "JP" "BR")

for country in "${COUNTRIES[@]}"; do
    IP=$(curl -s -x "http://${PROXY_HOST}" \
         -U "your-username-country-${country}:${PROXY_PASS}" \
         https://httpbin.org/ip | grep -o '"origin": "[^"]*"' | cut -d'"' -f4)
    echo "$country: $IP"
done

Common Errors and Fixes

curl: (56) Proxy CONNECT aborted

The proxy server rejected the CONNECT request. Usually means bad credentials.

# Check your credentials
curl -v -x http://gate.proxylabs.app:8080 \
     -U your-username:your-password \
     https://httpbin.org/ip 2>&1 | grep "< HTTP"
# Should show: < HTTP/1.1 200 Connection established

curl: (7) Failed to connect to proxy

Can't reach the proxy server. Check the hostname and port.

# Test basic connectivity
curl -v -x http://gate.proxylabs.app:8080 http://httpbin.org/ip
# If this fails, check DNS resolution and firewall rules

curl: (35) SSL connect error

TLS handshake failed through the proxy. Try --proxy-insecure for debugging (don't use in production):

curl -x http://your-username:[email protected]:8080 \
     --proxy-insecure \
     https://httpbin.org/ip

Empty response or timeout

The target site might be blocking the proxy IP. Try a different country or add headers:

curl -x http://gate.proxylabs.app:8080 \
     -U your-username-country-US:your-password \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
     -H "Accept: text/html,application/xhtml+xml" \
     --connect-timeout 10 \
     --max-time 30 \
     https://example.com

Environment Variables for Persistent Proxy

Set these in your shell profile (~/.bashrc, ~/.zshrc) to route all cURL traffic through a proxy:

# Add to ~/.bashrc or ~/.zshrc
export http_proxy="http://your-username:[email protected]:8080"
export https_proxy="http://your-username:[email protected]:8080"
export no_proxy="localhost,127.0.0.1,.local"

# These also work (uppercase)
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export NO_PROXY="$no_proxy"

Be careful: these environment variables affect most command-line HTTP tools (wget, httpie, Python requests, Node.js fetch). Use no_proxy to exclude local services.

For testing proxy connections quickly before building more complex scrapers, use the ProxyLabs Proxy Tester. For full scraping setups, see our guides for Python (Scrapy), Selenium, Puppeteer, and Playwright.

Ready to try the fastest residential proxies?

Join developers and businesses who trust ProxyLabs for mission-critical proxy infrastructure.

~200ms responseBest anti-bot bypass£2.50/GB
Start Building NowNo subscription required
cURLproxy setupresidential proxiescommand lineweb scrapingnetworking
JL
James Liu
Lead Engineer @ ProxyLabs

Building proxy infrastructure since 2019. Previously failed at many things, now failing slightly less.

Found this helpful? Share it with others.

Share