PHP Tunnel Proxy: curl / Guzzle / Stream Three Implementations

PHP curl, Guzzle, and Stream Context integrating 16Yun Crawler Proxy.

16Yun Engineering TeamMay 7, 20261 min read

PHP cURL

PHP's cURL extension configures proxies via the CURLOPT_PROXY parameter:

$host = getenv('PROXY_HOST') ?: 't.16yun.cn';
$port = getenv('PROXY_PORT') ?: '31111';
$user = getenv('PROXY_USERNAME') ?: 'user';
$pass = getenv('PROXY_PASSWORD') ?: 'password';
$tunnel = getenv('PROXY_TUNNEL') ?: 'php-curl-demo';
 
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://httpbin.org/ip');
curl_setopt($ch, CURLOPT_PROXY, $host);
curl_setopt($ch, CURLOPT_PROXYPORT, intval($port));
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "$user:$pass");
curl_setopt($ch, CURLOPT_PROXYHEADER, ["Proxy-Tunnel: $tunnel"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
 
$data = curl_exec($ch);
if ($data === false) {
    echo 'curl error: ' . curl_error($ch);
}
curl_close($ch);
echo $data;
ScenariocURL Implementation
A: Force SwitchEach curl_init + CURLOPT_FORBID_REUSE
B: Keep IPReuse curl handle
C-HTTP:Proxy-TunnelCURLOPT_PROXYHEADER + Proxy-Tunnel
C-HTTPS: Proxy-TunnelCURLOPT_PROXYHEADER sent during CONNECT

Guzzle

Guzzle configures via the proxy parameter and curl options:

use GuzzleHttp\Client;
 
$client = new Client([
    'proxy' => "http://$user:$pass@$host:$port",
    'curl' => [
        CURLOPT_PROXYHEADER => ["Proxy-Tunnel: $tunnel"],
    ],
    'timeout' => 15,
    'verify' => false,
]);
 
$resp = $client->get('https://httpbin.org/ip');
echo $resp->getBody();

Stream Context

PHP native stream context, zero dependencies:

$proxy = "tcp://$host:$port";
$auth = base64_encode("$user:$pass");
 
$opts = [
    'http' => [
        'proxy' => $proxy,
        'header' => [
            "Proxy-Authorization: Basic $auth",
            "Proxy-Tunnel: $tunnel",
        ],
        'timeout' => 15,
    ],
];
$context = stream_context_create($opts);
echo file_get_contents('http://httpbin.org/ip', false, $context);

Stream Context only supports HTTP targets. HTTPS requires the http:// wrapper with a tcp:// proxy address.

Comparison of Three Approaches

ApproachDependencyHTTPSHTTPS TunnelComplexity
cURLext-curlYesYesLow
Guzzlecomposer require guzzlehttp/guzzleYesYesLow
StreamNoneCaveat: Needs configurationNoMedium

Need an enterprise proxy plan?

We can tailor architecture to your target domains, concurrency, and reliability goals.