wppaste
WordPress

wp_parse_url( string $url, int $component = -1 ): mixed

Since
4.4.0, 4.7.0
Source
wp-includes/http.php:733

Parses a URL into its components (scheme, host, path, query, etc.) while correcting inconsistencies PHP's own parse_url() has across versions. Pass a PHP_URL_* constant as the second argument to get a single piece back instead of the full array. Useful for pulling the host or query string out of a permalink, REST endpoint, or user-supplied URL before validating or rewriting it.

A wrapper for PHP's parse_url() function that handles consistency in the return values across PHP versions.

Description

Across various PHP versions, schemeless URLs containing a ":" in the query are being handled inconsistently. This function works around those differences.

Compatibility

WordPress
since 4.7.0
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$urlstring
The URL to parse.
$componentintoptional
The specific component to retrieve. Use one of the PHP predefined constants to specify which one.
Defaults to -1 (= return all parts as an array).Default: -1

Return value

mixed
False on parse failure; Array of URL components on success; When a specific component has been requested: null if the component doesn't exist in the given URL; a string or - in the case of PHP_URL_PORT - integer when it does. See parse_url()'s return values.

Code examples

Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.

Break a post permalink into its URL components

Grab the full permalink for post ID 1 and inspect its scheme, host, path and query as an array.

$permalink = get_permalink( 1 );
$parts     = wp_parse_url( $permalink );

echo esc_html( 'Permalink: ' . $permalink ) . "\n";
echo '<pre>' . esc_html( print_r( $parts, true ) ) . '</pre>';

Read just the query string from a URL without parsing the whole thing

Build a link to post 2 with an extra query var and pull out only the query component using the PHP_URL_QUERY constant.

$url = home_url( '/?p=2&source=featured' );

$query = wp_parse_url( $url, PHP_URL_QUERY );
echo esc_html( 'Query string: ' . $query ) . "\n";

$host = wp_parse_url( '//example.com/path/to/page', PHP_URL_HOST );
echo esc_html( 'Host from a protocol-relative URL: ' . $host );

For a protocol-relative URL (starting with //) there is no scheme, so requesting PHP_URL_SCHEME here would return null rather than an empty string.

Common problems and fixes · 3

Why does asking for PHP_URL_SCHEME on my URL come back null instead of an empty string?

For URLs starting with // or /, the function temporarily prepends a placeholder scheme/host so PHP's parse_url() can parse them at all, then unsets that same key from the result before returning it. That means 'scheme' (and 'host' for absolute paths) is simply absent from the array, not an empty string. - Check with isset() or array_key_exists() rather than assuming an empty-string value. - If you need a usable absolute URL, prepend home_url() or site_url() yourself before parsing.

Why did wp_parse_url() return false?

The function returns whatever PHP's own parse_url() returns on failure, false, when the string it's given cannot be parsed as a URL at all (severely malformed input). It does not throw or warn. - Always check false === $result before treating the return value as an array or scalar. - Cast or sanitize the input first (the function itself just casts $url to a string, it does not validate it).

Why do I still get an array back even though I passed a component?

$component defaults to -1, which means "return everything as an array". If you meant to get a single piece back, pass one of PHP's PHP_URL_SCHEME, PHP_URL_HOST, PHP_URL_PORT, PHP_URL_USER, PHP_URL_PASS, PHP_URL_PATH, PHP_URL_QUERY, or PHP_URL_FRAGMENT constants explicitly. - wp_parse_url( $url, PHP_URL_HOST ) for just the host. - wp_parse_url( $url ) (or -1) for the full array.

Alternatives and related functions

parse_url
When you are not working around the schemeless URL quirks this function fixes and plain PHP behavior is acceptable.
wp_parse_str
When you already have an isolated query string and need it turned into an array of variables rather than parsing a whole URL.
esc_url
When the goal is to output a URL safely in HTML rather than to inspect or read its individual components.
add_query_arg
When you need to add or modify query parameters on a URL rather than just read its existing pieces.

Performance profile

How much work a call to wp_parse_url() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Light

Touches nothing outside its own arguments.

Scaling
Scales with input

The body loops, so the work grows with what you pass in.

Instructions
16–26

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 33.

Plugin surface
None

Nothing here hands control to plugin code.

Called by
31

31 places in core call this, so the cost is paid more often than your own code shows.

What one call costs · 2 distinct outcomes

One number would be a lie: the work depends on which branch runs. These are every distinct cost wp_parse_url() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
$parts === false16–19parse_url()
$parts !== false22–26parse_url(), _get_component_from_parsed_url_array()

Across PHP versions

PHPCompiledExecutedBranchesNotes
8.6-dev3316–265
8.53316–265
8.43316–2656 fewer instructions than PHP 8.3
8.33921–325
8.23921–325
8.13921–325
7.43921–325

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Uses · 2

Used by · 31

Show all 31

Source code

function wp_parse_url( $url, $component = -1 ) {	$to_unset = array();	$url      = (string) $url; 	if ( str_starts_with( $url, '//' ) ) {		$to_unset[] = 'scheme';		$url        = 'placeholder:' . $url;	} elseif ( str_starts_with( $url, '/' ) ) {		$to_unset[] = 'scheme';		$to_unset[] = 'host';		$url        = 'placeholder://placeholder' . $url;	} 	$parts = parse_url( $url ); 	if ( false === $parts ) {		// Parsing failure.		return $parts;	} 	// Remove the placeholder values.	foreach ( $to_unset as $key ) {		unset( $parts[ $key ] );	} 	return _get_component_from_parsed_url_array( $parts, $component );}

Changelog

Introduced in 4.4.0. Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

4.7.0
The $component parameter was added for parity with PHP's parse_url().from the docblock
4.4.0
Introduced.from the docblock

About this page

Parsed data
Generated from the wordpress-develop 6.8.8 tag, from src/wp-includes/http.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.