v1.10.82-f67ee7d
Skip to main content
← Back to Code Snippets

PHP Guzzle Proxy

Complete Guzzle proxy integration example for PHP with Hex Proxies. Includes authentication, timeouts, and error handling.

PHPGuzzle
Install:composer require guzzlehttp/guzzle
PHP / Guzzle
<?php
require "vendor/autoload.php";

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;

$client = new Client([
    "proxy"           => "http://user:pass@gate.hexproxies.com:8080",
    "timeout"         => 30,
    "connect_timeout" => 10,
    "verify"          => true,
]);

try {
    $response = $client->get("https://httpbin.org/ip");
    $data = json_decode($response->getBody(), true);
    echo "Origin IP: " . $data["origin"] . "\n";
} catch (ConnectException $e) {
    echo "Proxy connection failed: " . $e->getMessage() . "\n";
} catch (RequestException $e) {
    echo "Request error: " . $e->getMessage() . "\n";
}
?>

Why Guzzle for Proxy Work

Guzzle is the standard HTTP client for modern PHP applications, deeply integrated with frameworks like Laravel, Symfony, and WordPress. Its PSR-7 compliant message interface, middleware pipeline, and promise-based async support bring the ergonomics of modern JavaScript HTTP clients to the PHP ecosystem. For proxy work, Guzzle's middleware system is particularly powerful: you can inject proxy selection, credential management, retry logic, and request logging as composable middleware layers without modifying your application's HTTP calling code.

Guzzle abstracts away the complexity of PHP's cURL bindings behind a fluent object-oriented interface while still leveraging libcurl's performance under the hood. This means you get the connection pooling, HTTP/2 support, and protocol-level features of cURL without managing resource handles manually. When routing traffic through gate.hexproxies.com:8080, Guzzle handles credential encoding, proxy tunneling for HTTPS, and connection reuse automatically, letting you focus on your application's data extraction or monitoring logic.

Configuration Patterns

Guzzle accepts proxy configuration at the client level (applied to all requests) or the request level (applied to a single call). The client-level `proxy` option takes a string URL for all-protocol proxying, or an associative array with `http` and `https` keys for protocol-specific proxies. Per-request overrides use the same option names in the request options array: `$client->get($url, ['proxy' => 'http://alt-proxy:8080'])`.

Guzzle's middleware stack enables sophisticated proxy integration patterns. Create a middleware that reads proxy configuration from a database or API, selects the appropriate proxy for each request based on the target domain, and attaches it to the request options. Stack a retry middleware on top that catches `ConnectException` and retries with a different proxy. This composable approach keeps each concern isolated and testable, following PSR-15 middleware principles.

Common Pitfalls

Guzzle's exception hierarchy is important for proxy error handling but often misunderstood. `ConnectException` fires when the TCP connection to the proxy fails (proxy unreachable, DNS failure). `ClientException` fires for 4xx HTTP responses from the target (not the proxy). `ServerException` fires for 5xx responses. A 407 Proxy Authentication Required is a `ClientException`, not a `ConnectException`, because the proxy accepted the TCP connection but rejected the credentials. Catch each exception type separately for precise error handling.

Guzzle's default behavior of throwing exceptions on 4xx and 5xx responses can mask proxy-level issues. If the proxy returns a 502 Bad Gateway because the target site is down, Guzzle throws a `ServerException` that looks like a target error. Check `$e->getResponse()->getReasonPhrase()` and the response body to distinguish between proxy errors and target errors. Set `'http_errors' => false` during debugging to receive all responses without exceptions, then inspect status codes manually.

Performance Optimization

Guzzle supports concurrent requests through its `Pool` class, which manages a queue of requests with configurable concurrency. Create a Pool with your proxied Guzzle client and set concurrency to match your proxy allocation's capacity. The Pool dispatches requests asynchronously using cURL multi-handles internally, achieving true parallelism without threads or fibers. Handle results through the Pool's `fulfilled` and `rejected` callbacks for non-blocking result processing.

For Laravel applications, use Guzzle through Laravel's HTTP client facade, which adds automatic retry with exponential backoff via `->retry(3, 100)`. Combine this with a proxy middleware registered in the HTTP client's handler stack. Laravel's HTTP client also supports concurrent requests via `Http::pool()`, which maps cleanly to proxy workloads that need to fan out to multiple targets. Monitor proxy performance with Laravel Telescope or a custom event listener on Guzzle's `on_stats` callback, which provides detailed transfer timing including proxy connect time.

Tips

  • 1
    Guzzle supports per-request proxy overrides via the request options array.
  • 2
    Use ConnectException to catch proxy-specific connection failures.
  • 3
    Enable Guzzle middleware for automatic retries on proxy timeouts.

Ready to Integrate?

Get proxy credentials and start coding in minutes.