Is your Guzzle scraper facing IP bans? Masking your IP with proxies helps bypass bans and geo-restrictions. But how can you set up proxies with Guzzle?
In this article, you'll learn how to set up proxies using Guzzle in PHP, including proxy rotation and authentication. We'll cover:
- How to set a proxy in Guzzle.
- Proxy authentication with Guzzle.
- Use a rotating proxy with Guzzle.
- Premium proxy to avoid getting blocked.
Let's get started!
What Is a Guzzle Proxy?
When using Guzzle, a proxy is a server that stands between your client and the destination server. It sends your request to the target server and gives your client the response, allowing you to appear as a different user.
Proxies can also help you bypass IP bans that prevent web scraping or restrict website access.
Let's see what you need to use a Guzzle proxy properly.
How to Set a Proxy in Guzzle
You'll use free proxies from the Free Proxy List and test the connection on HTTPBin to verify if the proxy works.
Make sure to select valid proxies with good uptime, and ensure the proxy URL follows this format:
<PROXY_PROTOCOL>://<PROXY_IP_ADDRESS>:<PROXY_PORT>
It's important to note that you can integrate a proxy with Guzzle using either request-options
or middleware.
If you need a simple and static proxy configuration and want to use different proxies per request, using request-options
is a good choice. Meanwhile, using middleware provides more flexibility and control over the proxy behavior but requires more setup.
Free proxies are only active for a limited time. The ones used in this example may not work for you, so replace them with new ones. Aside from HTTP and HTTPS, Guzzle supports other proxy protocols, including SOCKS5.
Let's explore these two methods.
Method #1: Set a Guzzle Proxy With request-options
To set a proxy with request-options
, import Guzzle's Client
and the RequestOptions
. Define an associative array of all the proxies you'll use. Then, create a Guzzle client and pass them as the Guzzle proxy
option. Finally, request the target site with the proxy and print its content:
<?php
// composer's autoloader
require 'vendor/autoload.php';
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
// set the target URL
$targetUrl = 'https://httpbin.io/ip';
// define the proxies
$proxies = [
'http' => 'http://159.54.187.233:8080',
'https' => 'http://159.54.187.233:8080',
];
// set up a client array
$client = new Client([
RequestOptions::PROXY => $proxies,
RequestOptions::VERIFY => false, # disable SSL certificate validation
RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);
// send request with the proxy
try {
$body = $client->get($targetUrl)->getBody();
echo $body->getContents();
} catch (\Exception $e) {
echo $e->getMessage();
}
?>
Run your script using php scraper.php
, and you'll get an output similar to the one below:
{
"origin": "159.54.187.233:55948"
}
Great! The value of the origin key is the IP address of the proxy server that sends the request on behalf of the Guzzle client.
Method #2: Use Middleware
Using middleware to set a Guzzle HTTP proxy is similar to the first method. The only difference in this case is that you'll first create and add proxy middleware to the default handler stack.
First, update your import to include the HandlerStack
and RequestInterface
modules. Create a custom middleware to handle the proxy and push it to a HandlerStack
. Then, initialize the proxy with options and request the target site:
<?php
# composer's autoloader
require 'vendor/autoload.php';
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\HandlerStack;
// set the target URL
$targetUrl = 'https://httpbin.io/ip';
// define the proxies
$proxies = [
'http' => 'http://159.54.187.233:8080',
'https' => 'http://159.54.187.233:8080',
];
// handle proxy with a custom middleware
function proxy_middleware(array $proxies)
{
return function (callable $handler) use ($proxies) {
return function (RequestInterface $request, array $options) use ($handler, $proxies) {
# add proxy to request option
$options[RequestOptions::PROXY] = $proxies;
return $handler($request, $options);
};
};
}
// create a HandlerStack and push the proxy middleware into it
$stack = HandlerStack::create();
$stack->push(proxy_middleware($proxies));
// initialize the Guzzle client with the stack
$client = new Client([
'handler' => $stack,
RequestOptions::VERIFY => false, # disable SSL certificate validation
RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);
// send request with the proxy
try {
$body = $client->get($targetUrl)->getBody();
echo $body->getContents();
} catch (\Exception $e) {
echo $e->getMessage();
}
?>
Again, the code outputs the proxy server's IP address, as shown:
{
"origin": "159.54.187.233:42934"
}
Nice! You now know how to set up proxies in Guzzle using the built-in option and custom middleware. Next, let's explore how to handle authenticated proxies.
Proxy Authentication with Guzzle
Some proxy servers require client authentication before granting access. This requirement is common when using premium proxies or commercial solutions.Â
If that's your case, add the options for authentication, usually a username and password, to the proxy string.
The syntax of the Guzzle proxy string will then look like this:
<PROXY_PROTOCOL>://<YOUR_USERNAME>:<YOUR_PASSWORD>@<PROXY_IP_ADDRESS>:<PROXY_PORT>
So, you only need to replace the proxy array in the previous code with the following:
// ...
// define the proxies
$proxies = [
'http' => 'http://<YOUR_USERNAME>:<YOUR_PASSWORD>@<PROXY_ADDRESS>:<PROXY_PORT>',
'https' => 'http://<YOUR_USERNAME>:<YOUR_PASSWORD>@<PROXY_ADDRESS>:<PROXY_PORT>',
];
// ...
The code will return an HTTP error with status code 407 (Proxy Authentication Required) if your authentication credentials are invalid. Ensure you pass the correct ones.
Use a Rotating Proxy with Guzzle
A rotating proxy is a proxy server that regularly switches between different IP addresses per request. This helps prevent IP blocking by making each request appear to come from a different source, making it harder for websites to track and block your activity.
To see how that works, you'll start with a scraper that uses a Guzzle proxy to request and retry for a maximum number of attempts until it succeeds using a list of free proxies.
First, write a function that returns random proxies from the Free Proxy List and add that function to your proxy configuration. Each request will use a different proxy:
<?php
// composer's autoloader
require 'vendor/autoload.php';
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
// set the target URL
$targetUrl = 'https://httpbin.io/ip';
function get_random_proxies(): array {
// define HTTP and HTTPs proxy arrays
$http_proxies = array(
'http://159.54.187.233:8080',
'http://201.182.251.142:999',
// ...
'http://169.55.89.6:80'
);
$https_proxies = array(
'http://159.54.187.233:8080',
'http://201.182.251.142:999',
// ...
'http://169.55.89.6:80'
);
$http_proxy = $http_proxies[array_rand($http_proxies)];
$https_proxy = $https_proxies[array_rand($https_proxies)];
# proxies
$proxies = [
'http' => $http_proxy,
'https' => $https_proxy,
];
return $proxies;
}
try {
// get a new proxy for this request
$current_proxy = get_random_proxies();
// set up a client array
$client = new Client([
RequestOptions::PROXY => $current_proxy,
RequestOptions::VERIFY => false, # disable SSL certificate validation
RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);
$body = $client->get($targetUrl)->getBody();
echo $body->getContents();
} catch (\Exception $e) {
echo $e->getMessage();
}
?>
The above code returns a different proxy address per request. Here's a sample response for three consecutive requests:
// ... request 1
{
"origin": "159.54.187.233:52236"
}
// ... request 2
{
"origin": "169.55.89.6:36657"
}
// ... request 3
{
"origin": "1201.182.251.142:25536"
}
Bravo! You're now randomizing proxies.Â
However, a better solution is to use a web scraping premium proxy. Let's see that next.
Premium Proxy to Avoid Getting Blocked
Free proxies have a short lifespan and don't guarantee success. They're only suitable for testing the proxy connection but not ideal for real-life projects.
The best way to increase your scraper's success rate is to use the ZenRows Residential Proxies, a proxy provider offering one of the most reliable premium proxies in the market. It auto-rotates proxies using 55+ million ethically sourced residential IPs distributed over 185+ countries.Â
ZenRows also offers flexible geo-targeting, allowing you to access localized and geo-restricted content.Â
Let's see how to set up the ZenRows Residential Proxy with your Guzzle scraper.
Sign up for free on ZenRows and go to Residential Proxies to open the Proxy Generator. Then, copy the proxy address and your proxy credentials (username and password).

Once you get your credentials, implement it in your scraper like so:
<?php
// composer's autoloader
require 'vendor/autoload.php';
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
// set the target URL
$targetUrl = 'https://httpbin.io/ip';
// define the proxies
$proxies = [
'http' => 'http://<ZENROWS_PROXY_USERNAME>:<ZENROWS_PROXY_PASSWORD>@superproxy.zenrows.com:1337',
'https' => 'http://<ZENROWS_PROXY_USERNAME>:<ZENROWS_PROXY_PASSWORD>@superproxy.zenrows.com:1337',
];
// set up a client array
$client = new Client([
RequestOptions::PROXY => $proxies,
RequestOptions::VERIFY => false, # disable SSL certificate validation
RequestOptions::TIMEOUT => 30, # timeout of 30 seconds
]);
// send request with the proxy
try {
$body = $client->get($targetUrl)->getBody();
echo $body->getContents();
} catch (\Exception $e) {
echo $e->getMessage();
}
?>
You've now set up the ZenRows Residential Proxy in Guzzle. Three consecutive requests output a different IP address, as shown below:
// request 1
{
"origin": "104.230.67.4:59674"
}
// request 2
{
"origin": "66.207.185.55:53381"
}
// request 3
{
"origin": "187.75.159.74:59638"
}
Congratulations! Your scraper now auto-rotates residential IPs per request.
Conclusion
You've learned how to set up proxies with Guzzle in PHP, including advanced cases like proxy rotation and authentication.
Keep in mind that proxy services vary in efficiency and reliability. We recommend ZenRows' Residential Proxies for guaranteed success and access to advanced scraping features.