Title: WP_Http_Streams::request
Published: April 25, 2014
Last modified: April 28, 2025

---

# WP_Http_Streams::request( string $url, string|array $args = array() ): array|󠀁[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)󠁿

## In this article

 * [Description](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#description)
    - [See also](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#see-also)
 * [Parameters](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#wp--skip-link--target)

Send a HTTP request to a URI using PHP Streams.

## 󠀁[Description](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#description)󠁿

### 󠀁[See also](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#see-also)󠁿

 * [WP_Http::request()](https://developer.wordpress.org/reference/classes/WP_Http/request/):
   For default options descriptions.

## 󠀁[Parameters](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#parameters)󠁿

 `$url`stringrequired

The request URL.

`$args`string|arrayoptional

Override the defaults.

Default:`array()`

## 󠀁[Return](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#return)󠁿

 array|[WP_Error](https://developer.wordpress.org/reference/classes/wp_error/) Array
containing `'headers'`, `'body'`, `'response'`, `'cookies'`, `'filename'`. A [WP_Error](https://developer.wordpress.org/reference/classes/wp_error/)
instance upon error

## 󠀁[Source](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#source)󠁿

    ```php
    public function request( $url, $args = array() ) {
    	$defaults = array(
    		'method'      => 'GET',
    		'timeout'     => 5,
    		'redirection' => 5,
    		'httpversion' => '1.0',
    		'blocking'    => true,
    		'headers'     => array(),
    		'body'        => null,
    		'cookies'     => array(),
    		'decompress'  => false,
    		'stream'      => false,
    		'filename'    => null,
    	);

    	$parsed_args = wp_parse_args( $args, $defaults );

    	if ( isset( $parsed_args['headers']['User-Agent'] ) ) {
    		$parsed_args['user-agent'] = $parsed_args['headers']['User-Agent'];
    		unset( $parsed_args['headers']['User-Agent'] );
    	} elseif ( isset( $parsed_args['headers']['user-agent'] ) ) {
    		$parsed_args['user-agent'] = $parsed_args['headers']['user-agent'];
    		unset( $parsed_args['headers']['user-agent'] );
    	}

    	// Construct Cookie: header if any cookies are set.
    	WP_Http::buildCookieHeader( $parsed_args );

    	$parsed_url = parse_url( $url );

    	$connect_host = $parsed_url['host'];

    	$secure_transport = ( 'ssl' === $parsed_url['scheme'] || 'https' === $parsed_url['scheme'] );
    	if ( ! isset( $parsed_url['port'] ) ) {
    		if ( 'ssl' === $parsed_url['scheme'] || 'https' === $parsed_url['scheme'] ) {
    			$parsed_url['port'] = 443;
    			$secure_transport   = true;
    		} else {
    			$parsed_url['port'] = 80;
    		}
    	}

    	// Always pass a path, defaulting to the root in cases such as http://example.com.
    	if ( ! isset( $parsed_url['path'] ) ) {
    		$parsed_url['path'] = '/';
    	}

    	if ( isset( $parsed_args['headers']['Host'] ) || isset( $parsed_args['headers']['host'] ) ) {
    		if ( isset( $parsed_args['headers']['Host'] ) ) {
    			$parsed_url['host'] = $parsed_args['headers']['Host'];
    		} else {
    			$parsed_url['host'] = $parsed_args['headers']['host'];
    		}
    		unset( $parsed_args['headers']['Host'], $parsed_args['headers']['host'] );
    	}

    	/*
    	 * Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect
    	 * to ::1, which fails when the server is not set up for it. For compatibility, always
    	 * connect to the IPv4 address.
    	 */
    	if ( 'localhost' === strtolower( $connect_host ) ) {
    		$connect_host = '127.0.0.1';
    	}

    	$connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host;

    	$is_local   = isset( $parsed_args['local'] ) && $parsed_args['local'];
    	$ssl_verify = isset( $parsed_args['sslverify'] ) && $parsed_args['sslverify'];

    	if ( $is_local ) {
    		/**
    		 * Filters whether SSL should be verified for local HTTP API requests.
    		 *
    		 * @since 2.8.0
    		 * @since 5.1.0 The `$url` parameter was added.
    		 *
    		 * @param bool|string $ssl_verify Boolean to control whether to verify the SSL connection
    		 *                                or path to an SSL certificate.
    		 * @param string      $url        The request URL.
    		 */
    		$ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify, $url );
    	} elseif ( ! $is_local ) {
    		/** This filter is documented in wp-includes/class-wp-http.php */
    		$ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify, $url );
    	}

    	$proxy = new WP_HTTP_Proxy();

    	$context = stream_context_create(
    		array(
    			'ssl' => array(
    				'verify_peer'       => $ssl_verify,
    				// 'CN_match' => $parsed_url['host'], // This is handled by self::verify_ssl_certificate().
    				'capture_peer_cert' => $ssl_verify,
    				'SNI_enabled'       => true,
    				'cafile'            => $parsed_args['sslcertificates'],
    				'allow_self_signed' => ! $ssl_verify,
    			),
    		)
    	);

    	$timeout  = (int) floor( $parsed_args['timeout'] );
    	$utimeout = 0;

    	if ( $timeout !== (int) $parsed_args['timeout'] ) {
    		$utimeout = 1000000 * $parsed_args['timeout'] % 1000000;
    	}

    	$connect_timeout = max( $timeout, 1 );

    	// Store error number.
    	$connection_error = null;

    	// Store error string.
    	$connection_error_str = null;

    	if ( ! WP_DEBUG ) {
    		// In the event that the SSL connection fails, silence the many PHP warnings.
    		if ( $secure_transport ) {
    			$error_reporting = error_reporting( 0 );
    		}

    		if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
    			// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
    			$handle = @stream_socket_client(
    				'tcp://' . $proxy->host() . ':' . $proxy->port(),
    				$connection_error,
    				$connection_error_str,
    				$connect_timeout,
    				STREAM_CLIENT_CONNECT,
    				$context
    			);
    		} else {
    			// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
    			$handle = @stream_socket_client(
    				$connect_host . ':' . $parsed_url['port'],
    				$connection_error,
    				$connection_error_str,
    				$connect_timeout,
    				STREAM_CLIENT_CONNECT,
    				$context
    			);
    		}

    		if ( $secure_transport ) {
    			error_reporting( $error_reporting );
    		}
    	} else {
    		if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) {
    			$handle = stream_socket_client(
    				'tcp://' . $proxy->host() . ':' . $proxy->port(),
    				$connection_error,
    				$connection_error_str,
    				$connect_timeout,
    				STREAM_CLIENT_CONNECT,
    				$context
    			);
    		} else {
    			$handle = stream_socket_client(
    				$connect_host . ':' . $parsed_url['port'],
    				$connection_error,
    				$connection_error_str,
    				$connect_timeout,
    				STREAM_CLIENT_CONNECT,
    				$context
    			);
    		}
    	}

    	if ( false === $handle ) {
    		// SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken.
    		if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str ) {
    			return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) );
    		}

    		return new WP_Error( 'http_request_failed', $connection_error . ': ' . $connection_error_str );
    	}

    	// Verify that the SSL certificate is valid for this request.
    	if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) {
    		if ( ! self::verify_ssl_certificate( $handle, $parsed_url['host'] ) ) {
    			return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) );
    		}
    	}

    	stream_set_timeout( $handle, $timeout, $utimeout );

    	if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { // Some proxies require full URL in this field.
    		$request_path = $url;
    	} else {
    		$request_path = $parsed_url['path'] . ( isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '' );
    	}

    	$headers = strtoupper( $parsed_args['method'] ) . ' ' . $request_path . ' HTTP/' . $parsed_args['httpversion'] . "\r\n";

    	$include_port_in_host_header = (
    		( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) )
    		|| ( 'http' === $parsed_url['scheme'] && 80 !== $parsed_url['port'] )
    		|| ( 'https' === $parsed_url['scheme'] && 443 !== $parsed_url['port'] )
    	);

    	if ( $include_port_in_host_header ) {
    		$headers .= 'Host: ' . $parsed_url['host'] . ':' . $parsed_url['port'] . "\r\n";
    	} else {
    		$headers .= 'Host: ' . $parsed_url['host'] . "\r\n";
    	}

    	if ( isset( $parsed_args['user-agent'] ) ) {
    		$headers .= 'User-agent: ' . $parsed_args['user-agent'] . "\r\n";
    	}

    	if ( is_array( $parsed_args['headers'] ) ) {
    		foreach ( (array) $parsed_args['headers'] as $header => $header_value ) {
    			$headers .= $header . ': ' . $header_value . "\r\n";
    		}
    	} else {
    		$headers .= $parsed_args['headers'];
    	}

    	if ( $proxy->use_authentication() ) {
    		$headers .= $proxy->authentication_header() . "\r\n";
    	}

    	$headers .= "\r\n";

    	if ( ! is_null( $parsed_args['body'] ) ) {
    		$headers .= $parsed_args['body'];
    	}

    	fwrite( $handle, $headers );

    	if ( ! $parsed_args['blocking'] ) {
    		stream_set_blocking( $handle, 0 );
    		fclose( $handle );
    		return array(
    			'headers'  => array(),
    			'body'     => '',
    			'response' => array(
    				'code'    => false,
    				'message' => false,
    			),
    			'cookies'  => array(),
    		);
    	}

    	$response     = '';
    	$body_started = false;
    	$keep_reading = true;
    	$block_size   = 4096;

    	if ( isset( $parsed_args['limit_response_size'] ) ) {
    		$block_size = min( $block_size, $parsed_args['limit_response_size'] );
    	}

    	// If streaming to a file setup the file handle.
    	if ( $parsed_args['stream'] ) {
    		if ( ! WP_DEBUG ) {
    			$stream_handle = @fopen( $parsed_args['filename'], 'w+' );
    		} else {
    			$stream_handle = fopen( $parsed_args['filename'], 'w+' );
    		}

    		if ( ! $stream_handle ) {
    			return new WP_Error(
    				'http_request_failed',
    				sprintf(
    					/* translators: 1: fopen(), 2: File name. */
    					__( 'Could not open handle for %1$s to %2$s.' ),
    					'fopen()',
    					$parsed_args['filename']
    				)
    			);
    		}

    		$bytes_written = 0;

    		while ( ! feof( $handle ) && $keep_reading ) {
    			$block = fread( $handle, $block_size );
    			if ( ! $body_started ) {
    				$response .= $block;
    				if ( strpos( $response, "\r\n\r\n" ) ) {
    					$processed_response = WP_Http::processResponse( $response );
    					$body_started       = true;
    					$block              = $processed_response['body'];
    					unset( $response );
    					$processed_response['body'] = '';
    				}
    			}

    			$this_block_size = strlen( $block );

    			if ( isset( $parsed_args['limit_response_size'] )
    				&& ( $bytes_written + $this_block_size ) > $parsed_args['limit_response_size']
    			) {
    				$this_block_size = ( $parsed_args['limit_response_size'] - $bytes_written );
    				$block           = substr( $block, 0, $this_block_size );
    			}

    			$bytes_written_to_file = fwrite( $stream_handle, $block );

    			if ( $bytes_written_to_file !== $this_block_size ) {
    				fclose( $handle );
    				fclose( $stream_handle );
    				return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) );
    			}

    			$bytes_written += $bytes_written_to_file;

    			$keep_reading = (
    				! isset( $parsed_args['limit_response_size'] )
    				|| $bytes_written < $parsed_args['limit_response_size']
    			);
    		}

    		fclose( $stream_handle );

    	} else {
    		$header_length = 0;

    		while ( ! feof( $handle ) && $keep_reading ) {
    			$block     = fread( $handle, $block_size );
    			$response .= $block;

    			if ( ! $body_started && strpos( $response, "\r\n\r\n" ) ) {
    				$header_length = strpos( $response, "\r\n\r\n" ) + 4;
    				$body_started  = true;
    			}

    			$keep_reading = (
    				! $body_started
    				|| ! isset( $parsed_args['limit_response_size'] )
    				|| strlen( $response ) < ( $header_length + $parsed_args['limit_response_size'] )
    			);
    		}

    		$processed_response = WP_Http::processResponse( $response );
    		unset( $response );

    	}

    	fclose( $handle );

    	$processed_headers = WP_Http::processHeaders( $processed_response['headers'], $url );

    	$response = array(
    		'headers'  => $processed_headers['headers'],
    		// Not yet processed.
    		'body'     => null,
    		'response' => $processed_headers['response'],
    		'cookies'  => $processed_headers['cookies'],
    		'filename' => $parsed_args['filename'],
    	);

    	// Handle redirects.
    	$redirect_response = WP_Http::handle_redirects( $url, $parsed_args, $response );
    	if ( false !== $redirect_response ) {
    		return $redirect_response;
    	}

    	// If the body was chunk encoded, then decode it.
    	if ( ! empty( $processed_response['body'] )
    		&& isset( $processed_headers['headers']['transfer-encoding'] )
    		&& 'chunked' === $processed_headers['headers']['transfer-encoding']
    	) {
    		$processed_response['body'] = WP_Http::chunkTransferDecode( $processed_response['body'] );
    	}

    	if ( true === $parsed_args['decompress']
    		&& true === WP_Http_Encoding::should_decode( $processed_headers['headers'] )
    	) {
    		$processed_response['body'] = WP_Http_Encoding::decompress( $processed_response['body'] );
    	}

    	if ( isset( $parsed_args['limit_response_size'] )
    		&& strlen( $processed_response['body'] ) > $parsed_args['limit_response_size']
    	) {
    		$processed_response['body'] = substr( $processed_response['body'], 0, $parsed_args['limit_response_size'] );
    	}

    	$response['body'] = $processed_response['body'];

    	return $response;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/class-wp-http-streams.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/class-wp-http-streams.php#L32)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/class-wp-http-streams.php#L32-L415)

## 󠀁[Hooks](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#hooks)󠁿

 [apply_filters( ‘https_local_ssl_verify’, bool|string $ssl_verify, string $url )](https://developer.wordpress.org/reference/hooks/https_local_ssl_verify/)

Filters whether SSL should be verified for local HTTP API requests.

 [apply_filters( ‘https_ssl_verify’, bool|string $ssl_verify, string $url )](https://developer.wordpress.org/reference/hooks/https_ssl_verify/)

Filters whether SSL should be verified for non-local requests.

## 󠀁[Related](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#related)󠁿

| Uses | Description | 
| [WP_Http_Encoding::should_decode()](https://developer.wordpress.org/reference/classes/wp_http_encoding/should_decode/)`wp-includes/class-wp-http-encoding.php` |

Whether the content be decoded based on the headers.

  | 
| [WP_Http_Encoding::decompress()](https://developer.wordpress.org/reference/classes/wp_http_encoding/decompress/)`wp-includes/class-wp-http-encoding.php` |

Decompression of deflated string.

  | 
| [WP_Http_Streams::verify_ssl_certificate()](https://developer.wordpress.org/reference/classes/wp_http_streams/verify_ssl_certificate/)`wp-includes/class-wp-http-streams.php` |

Verifies the received SSL certificate against its Common Names and subjectAltName fields.

  | 
| [WP_Http::handle_redirects()](https://developer.wordpress.org/reference/classes/wp_http/handle_redirects/)`wp-includes/class-wp-http.php` |

Handles an HTTP redirect and follows it if appropriate.

  | 
| [WP_Http::buildCookieHeader()](https://developer.wordpress.org/reference/classes/wp_http/buildcookieheader/)`wp-includes/class-wp-http.php` |

Takes the arguments for a ::request() and checks for the cookie array.

  | 
| [WP_Http::processResponse()](https://developer.wordpress.org/reference/classes/wp_http/processresponse/)`wp-includes/class-wp-http.php` |

Parses the responses and splits the parts into headers and body.

  | 
| [WP_Http::processHeaders()](https://developer.wordpress.org/reference/classes/wp_http/processheaders/)`wp-includes/class-wp-http.php` |

Transforms header string into an array.

  | 
| [WP_Http::chunkTransferDecode()](https://developer.wordpress.org/reference/classes/wp_http/chunktransferdecode/)`wp-includes/class-wp-http.php` |

Decodes chunk transfer-encoding, based off the HTTP 1.1 specification.

  | 
| [__()](https://developer.wordpress.org/reference/functions/__/)`wp-includes/l10n.php` |

Retrieves the translation of $text.

  | 
| [wp_parse_args()](https://developer.wordpress.org/reference/functions/wp_parse_args/)`wp-includes/functions.php` |

Merges user defined arguments into defaults array.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  | 
| [WP_Error::__construct()](https://developer.wordpress.org/reference/classes/wp_error/__construct/)`wp-includes/class-wp-error.php` |

Initializes the error.

  |

[Show 7 more](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#)

## 󠀁[Changelog](https://developer.wordpress.org/reference/classes/wp_http_streams/request/?output_format=md#changelog)󠁿

| Version | Description | 
| [3.7.0](https://developer.wordpress.org/reference/since/3.7.0/) | Combined with the fsockopen transport and switched to stream_socket_client(). | 
| [2.7.0](https://developer.wordpress.org/reference/since/2.7.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Fclasses%2Fwp_http_streams%2Frequest%2F)
before being able to contribute a note or feedback.