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
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
| Product | Line in your dashboard | Notes |
|---|---|---|
| Static ISP proxies | IP:PORT:USER:PASS | One line per dedicated IP. With IP whitelisting turned on, the line is just IP:PORT and no password is sent. |
| Rotating residential and mobile | HOST:PORT:USER:PASS | Generated 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
Copy your proxy line
From the CleanProxies dashboard, copy the host (or IP), port, username and password. - 2
Set the proxy options
AddCURLOPT_PROXY,CURLOPT_PROXYUSERPWDand, for SOCKS5,CURLOPT_PROXYTYPEbeforecurl_exec. - 3
Set timeouts
AddCURLOPT_CONNECTTIMEOUTandCURLOPT_TIMEOUTso a slow target can't hang a PHP worker. - 4
Check the exit IP
Requesthttps://api.ipify.organd print the response.
PHP cURL proxy example (HTTP and SOCKS5)
<?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);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.
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();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
$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
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.
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.
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
| Problem | Likely cause | Fix |
|---|---|---|
| HTTP 407 / Received HTTP code 407 from proxy after CONNECT | Wrong 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 milliseconds | Wrong 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 problem | An 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 SOCKS5 | CURLPROXY_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.