Command line and PHP cURL

cURL Proxy Guide: CURLOPT_PROXY, Authentication and Protocols

Use a proxy with cURL from the command line or PHP. For a complete implementation with reusable functions and error handling, follow our PHP cURL proxy examples. These examples cover --proxy, --proxy-user, HTTP and SOCKS schemes, remote DNS, environment variables, CURLOPT_PROXY, timeouts, and practical debugging.

Quick answer: pass the endpoint with --proxy, keep credentials separate with --proxy-user, and specify the scheme when protocol or DNS behavior matters. Add --verbose only for controlled troubleshooting because diagnostic output can reveal hostnames and authentication details. In PHP, set CURLOPT_PROXY, the proxy port or full URI, authentication, proxy type, and explicit connect/operation timeouts.

Basic cURL proxy command

curl --proxy http://proxy.example.net:8080 https://example.com/

The official CURLOPT_PROXY documentation accepts a hostname or IP plus a port, optionally prefixed with a scheme. Without a scheme, libcurl treats the endpoint as an HTTP proxy. Always specify the real port; do not assume every proxy uses the same default.

Add proxy authentication

curl 
  --proxy http://proxy.example.net:8080 
  --proxy-user "username:password" 
  https://example.com/

Use placeholder values in documentation. On a real system, command-line credentials may be visible in shell history or the process list. Prefer an environment variable, protected configuration, or another secret-handling method appropriate to the operating system. Avoid posting verbose output until credentials are removed.

export PROXY_URL="http://proxy.example.net:8080"
read -s PROXY_AUTH
curl --proxy "$PROXY_URL" --proxy-user "$PROXY_AUTH" https://example.com/

The shell snippet keeps the typed value out of normal echo output, but secret handling still depends on shell history, process inspection, CI logs, and host security. In automated systems, use the platform’s secret store.

HTTP, HTTPS and SOCKS proxy schemes

Scheme Meaning in cURL DNS behavior
http:// HTTP proxy; HTTPS destinations normally use CONNECT tunneling Depends on proxy/request handling
https:// TLS connection to a supported HTTPS proxy Depends on proxy/request handling
socks4:// SOCKS4 endpoint Host resolution normally local
socks4a:// SOCKS4a endpoint Proxy resolves hostname
socks5:// SOCKS5 endpoint Hostname normally resolved locally
socks5h:// SOCKS5 endpoint with proxy-side hostname resolution Proxy resolves hostname

Use socks5h:// when the proxy should resolve the destination hostname. This can matter when local DNS cannot resolve the name or when DNS resolution should follow the proxy route. The application and provider must support the selected protocol.

Useful cURL proxy examples

Check the public exit IP

curl --proxy http://proxy.example.net:8080 https://api.ipify.org?format=json

Set connect and total timeouts

curl 
  --proxy http://proxy.example.net:8080 
  --connect-timeout 10 
  --max-time 30 
  https://example.com/

Use a SOCKS5 proxy with remote DNS

curl 
  --proxy socks5h://proxy.example.net:1080 
  --proxy-user "username:password" 
  https://example.com/

Bypass the proxy for selected hosts

curl 
  --proxy http://proxy.example.net:8080 
  --noproxy "localhost,127.0.0.1,.internal.example" 
  https://example.com/

Proxy environment variables

cURL/libcurl recognizes scheme-specific proxy variables and all_proxy, while no_proxy defines exceptions. Explicit options override environment variables. Lowercase http_proxy is the portable convention for HTTP.

export http_proxy="http://proxy.example.net:8080"
export https_proxy="http://proxy.example.net:8080"
export no_proxy="localhost,127.0.0.1,.internal.example"

curl https://example.com/

Environment variables are convenient for a controlled shell or container, but they affect every compatible command in that environment. Unset them when the job is complete.

unset http_proxy https_proxy all_proxy no_proxy

Use CURLOPT_PROXY in PHP

<?php
$ch = curl_init('https://example.com/');

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_PROXY => 'proxy.example.net',
    CURLOPT_PROXYPORT => 8080,
    CURLOPT_PROXYUSERPWD => getenv('PROXY_USER') . ':' . getenv('PROXY_PASSWORD'),
    CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
]);

$body = curl_exec($ch);

if ($body === false) {
    throw new RuntimeException(curl_error($ch), curl_errno($ch));
}

$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

echo "HTTP {$status}n";
?>

Check that both environment variables exist before building credentials. In newer code, prefer separate proxy username/password options where the binding supports them so a colon inside a password is handled correctly. Never print the option array to logs.

PHP SOCKS5 example

<?php
$ch = curl_init('https://example.com/');

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_PROXY => 'proxy.example.net:1080',
    CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
    CURLOPT_PROXYUSERPWD => getenv('PROXY_USER') . ':' . getenv('PROXY_PASSWORD'),
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
]);

$body = curl_exec($ch);
if ($body === false) {
    throw new RuntimeException(curl_error($ch), curl_errno($ch));
}
curl_close($ch);
?>

CURLPROXY_SOCKS5_HOSTNAME requests proxy-side hostname resolution, corresponding to the command-line socks5h:// behavior.

Debug a cURL proxy connection

Add verbose mode for a single sanitized test:

curl --verbose 
  --proxy http://proxy.example.net:8080 
  --proxy-user "username:password" 
  --connect-timeout 10 
  https://example.com/

Review where the failure occurs: DNS resolution, connection to the proxy, proxy authentication, CONNECT tunnel, TLS handshake, or target response. The focused cURL proxy diagnostics checklist shows how to capture and classify those stages. Remove credentials, tokens, cookies, and private hostnames before sharing logs.

Common cURL proxy errors

Could not resolve proxy

Check the proxy hostname, DNS, spelling, and whether the environment can resolve it. Try the documented IP only if the provider supports direct IP use.

Connection refused or timed out

Confirm host, port, firewall, route, and endpoint status. Compare with the Proxy Tester.

407 Proxy Authentication Required

Check credentials, authorization model, quoting, and whether the username/password belongs to the proxy rather than the destination.

The IP does not change

Look for no_proxy, an empty explicit proxy value, application overrides, or a command that did not inherit the expected environment.

SOCKS hostname fails

Compare socks5:// with socks5h://. The first normally resolves locally; the second asks the proxy to resolve.

cURL proxy checklist

  • Specify the scheme and port.
  • Keep credentials out of source and logs.
  • Set connect and total timeouts.
  • Verify the exit IP.
  • Test the real permitted target.
  • Use socks5h:// only when remote DNS is intended.
  • Review environment variables and no_proxy.
  • Sanitize verbose output.

cURL proxy FAQ

What does CURLOPT_PROXY do?

It specifies the proxy endpoint used by a libcurl handle. Include a scheme when the proxy type must be explicit.

What is the difference between socks5 and socks5h?

With socks5://, hostname resolution is normally local. With socks5h://, the proxy resolves the destination hostname.

Why use –proxy-user?

It separates proxy credentials from the endpoint string and makes the command easier to read. Credentials still require secure handling.

Can cURL test whether a proxy works?

Yes. Check the public IP, then call the real permitted destination with reasonable timeouts. A general IP check alone does not prove target compatibility.

Test your cURL proxy one layer at a time

Confirm the endpoint, authentication, protocol, DNS behavior, exit IP, and target response. For more context, read our HTTP proxies, SOCKS proxies, and HTTP vs SOCKS guides.

For application code rather than shell commands, use the Node.js proxy guide with built-in HTTP_PROXY support, Undici and Axios.

Scroll to Top