Skip to content
PHP cURL & Guzzle

How to use proxies in PHP with cURL and Guzzle

In PHP, set CURLOPT_PROXY to HOST:PORT and CURLOPT_PROXYUSERPWD to USERNAME:PASSWORD on your cURL handle. For SOCKS5, also set CURLOPT_PROXYTYPE to CURLPROXY_SOCKS5_HOSTNAME; in Guzzle, pass the full proxy URL in the proxy option.

What you need

PHP's cURL extension wraps libcurl, so every proxy feature of the command-line tool is available through curl_setopt. Guzzle and Laravel's HTTP client sit on top of it and take a single proxy URL.
  • An active CleanProxies plan: static ISP proxies for fixed US IPs, or rotating residential / mobile proxies for pools. The trial works too.
  • Your credential line from the dashboard's proxy manager: host (or IP), port, username and password.
  • PHP 8 with the cURL extension (php -m | grep curl).
  • Optional: Guzzle (composer require guzzlehttp/guzzle) or a Laravel app.

New to proxies? For the overview, read Using proxies with cURL, Python and Node.js. This guide goes deeper on PHP only.

Your CleanProxies credentials

Every CleanProxies product works over HTTP(S) and SOCKS5. This is what the dashboard gives you.
ProductLine in your dashboardNotes
Static ISP proxiesIP:PORT:USER:PASSOne line per dedicated IP. With IP whitelisting turned on, the line is just IP:PORT and no password is sent.
Rotating residential and mobileHOST:PORT:USER:PASSGenerated in the proxy manager. The username carries the location and session you pick, so generate a new list to change them.

Most tools want the same details as a URL: http://USERNAME:PASSWORD@HOST:PORT for HTTP(S) or socks5://USERNAME:PASSWORD@HOST:PORT for SOCKS5. The examples on this page use those placeholders; copy the host, port, username and password from your CleanProxies dashboard. To convert a whole list at once, paste it into the proxy list formatter.

How to set up CleanProxies in PHP

  1. 1

    Copy your proxy line

    From the CleanProxies dashboard, copy the host (or IP), port, username and password.
  2. 2

    Set the proxy options

    Add CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and, for SOCKS5, CURLOPT_PROXYTYPE before curl_exec.
  3. 3

    Set timeouts

    Add CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT so a slow target can't hang a PHP worker.
  4. 4

    Check the exit IP

    Request https://api.ipify.org and print the response.

PHP cURL proxy example (HTTP and SOCKS5)

HTTP(S) proxyPHP
<?php
$ch = curl_init('https://api.ipify.org');
curl_setopt_array($ch, [
    CURLOPT_PROXY          => 'HOST:PORT',
    CURLOPT_PROXYUSERPWD   => 'USERNAME:PASSWORD',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT        => 30,
]);

$ip = curl_exec($ch);
if ($ip === false) {
    echo 'Proxy error: ' . curl_error($ch) . PHP_EOL;
} else {
    echo "Exit IP: $ip" . PHP_EOL;
}
curl_close($ch);
SOCKS5 with DNS resolved by the proxyPHP
curl_setopt_array($ch, [
    CURLOPT_PROXY        => 'HOST:PORT',
    CURLOPT_PROXYUSERPWD => 'USERNAME:PASSWORD',
    CURLOPT_PROXYTYPE    => CURLPROXY_SOCKS5_HOSTNAME,
]);

CURLPROXY_SOCKS5 resolves the hostname in PHP and sends only the IP; CURLPROXY_SOCKS5_HOSTNAME lets the proxy resolve it, which keeps DNS consistent with the exit IP.

Guzzle and Laravel HTTP client

Guzzle's proxy option takes a URL and hands it to cURL. You can set it per request or per protocol.

GuzzlePHP
use GuzzleHttp\Client;

$client = new Client(['timeout' => 30]);

$response = $client->get('https://api.ipify.org', [
    'proxy' => 'http://USERNAME:PASSWORD@HOST:PORT',
    // SOCKS5 with remote DNS: 'socks5h://USERNAME:PASSWORD@HOST:PORT'
]);

echo $response->getBody();
Laravel HTTP clientPHP
use Illuminate\Support\Facades\Http;

$ip = Http::withOptions([
    'proxy' => 'http://USERNAME:PASSWORD@HOST:PORT',
])->timeout(30)->get('https://api.ipify.org')->body();

URL-encode the username and password with rawurlencode() if they contain reserved characters such as @, : or /.

Pick a different ISP proxy per request

Random line from proxies.txtPHP
$lines = file('proxies.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
[$host, $port, $user, $pass] = explode(':', $lines[array_rand($lines)], 4);

curl_setopt($ch, CURLOPT_PROXY, "$host:$port");
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "$user:$pass");

Static ISP vs rotating residential in PHP

Both products use the same setup. What changes is how long an IP stays with you.

Static ISP proxies

Each ISP line is one dedicated US IP that never changes while you hold it. Use one line per customer account or job so logins keep coming from the same address.

Static ISP ProxiesAs low as $0.75/IP

Rotating residential proxies

A rotating residential line gives each new connection a fresh IP. For checkout-style flows that need several requests from one IP, generate a sticky list and reuse the same cURL handle so the connection is kept alive.

Rotating Residential ProxiesAs low as $0.63/GB

Verify your exit IP

Run the first example from the command line with php proxy-test.php. It prints the exit IP, or the cURL error message if the proxy refused the connection.

Open What is my IP? through the proxy to see the address and headers a website receives, or paste up to ten lines into the free proxy checker to test connectivity, latency and exit IP before you start.

Troubleshooting PHP proxy errors

ProblemLikely causeFix
HTTP 407 / Received HTTP code 407 from proxy after CONNECTWrong credentials, or an ISP proxy set to IP whitelisting for another server.Copy the line again, or authorize your web server's public IP in the dashboard.
Connection timed out after N millisecondsWrong port or the hosting provider blocks outbound ports.Test with curl -x from the same server; ask your host to allow outbound traffic to the proxy port.
SSL certificate problemAn outdated CA bundle on the server, unrelated to the proxy.Update the CA bundle (curl.cainfo in php.ini). Don't disable CURLOPT_SSL_VERIFYPEER.
DNS leaks over SOCKS5CURLPROXY_SOCKS5 or a socks5:// URL resolves locally.Use CURLPROXY_SOCKS5_HOSTNAME or socks5h://.

Still stuck? Our 24/7 support team answers fast: contact us with the error and the line you used (leave the password out).

PHP proxy FAQs

Only awkwardly: you need a stream context with a proxy option and a manual Proxy-Authorization header, and HTTPS targets need request_fulluri tweaks. cURL or Guzzle is far more reliable.

Get CleanProxies for PHP

Super clean US ISP IPs from $0.75/IP with unlimited bandwidth, rotating residential from $0.63/GB and mobile from $0.79/GB. Instant delivery, 99.9% uptime and 24/7 support.