The HTTP API returns a response array on success and a WP_Error on failure, and the two share no shape at all — so any code that reaches straight for ['body'] produces a fatal the first time the remote host is slow.
$response = wp_remote_get( $url, array( 'timeout' => 5 ) );
if ( is_wp_error( $response ) ) {
return $response; // network failure, DNS, timeout
}
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
return new WP_Error( 'http', "Unexpected status {$code}" );
}
$body = wp_remote_retrieve_body( $response );
The second check is the one people skip: a 404 or a 500 is a perfectly successful HTTP transaction as far as the API is concerned, so is_wp_error() returns false and the body is an error page. The default timeout is five seconds, which is long enough to make a slow third party into a slow site — set it explicitly, lower, on anything in the request path.