Handle Guzzle exception and get HTTP body?

You can easily handle Guzzle exceptions and get the HTTP body of the response (if it has any) by catching RequestException. This is a higher-level exception that covers BadResponseException, TooManyRedirectsException, and a few related exceptions.

Here is how the exceptions in Guzzle depend on each other:

. \RuntimeException
└── TransferException (implements GuzzleException)
    ├── ConnectException (implements NetworkExceptionInterface)
    └── RequestException
        ├── BadResponseException
        │   ├── ServerException
        │   └── ClientException
        └── TooManyRedirectsException

Here is an example of how to handle the RequestException in Guzzle and get the HTTP body (if there is one):

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

$client = new Client();

try {
    $response = $client->get('https://example.com/api');
    $body = $response->getBody();
    // Process response body normally...
} catch (RequestException $e) {
    // An exception was raised but there is an HTTP response body
    // with the exception (in case of 404 and similar errors)
    if ($e->hasResponse()) {
        $response = $e->getResponse();
        $body = $response->getBody();
        // Process error response body...
    } 
    // An exception was raised but this time there is no response
    else {
        // Handle network or other error...
    }
}

If you want to be more specific about the exceptions you catch, you can use these:

GuzzleHttp\Exception\ClientException for 400-level errors
GuzzleHttp\Exception\ServerException for 500-level errors
GuzzleHttp\Exception\BadResponseException for both

You can read more about various exceptions thrown by Guzzle in the official docs.

Related Guzzle web scraping questions: