esc_url( string $url, string[] $protocols = null, string $_context = 'display' )

Checks and cleans a URL.


Description Description

A number of characters are removed from the URL. If the URL is for displaying (the default behaviour) ampersands are also replaced. The ‘clean_url’ filter is applied to the returned cleaned URL.


Top ↑

Parameters Parameters

$url

(string) (Required) The URL to be cleaned.

$protocols

(string[]) (Optional) An array of acceptable protocols. Defaults to return value of wp_allowed_protocols().

Default value: null

$_context

(string) (Optional) Private. Use esc_url_raw() for database usage.

Default value: 'display'


Top ↑

Return Return

(string) The cleaned URL after the 'clean_url' filter is applied.


Top ↑

More Information More Information

Always use esc_url when sanitizing URLs (in text nodes, attribute nodes or anywhere else). Rejects URLs that do not have one of the provided whitelisted protocols (defaulting to http, https, ftp, ftps, mailto, news, irc, gopher, nntp, feed, and telnet), eliminates invalid characters and removes dangerous characters. This function encodes characters as HTML entities: use it when generating an (X)HTML or XML document. Encodes ampersands (&) and single quotes (‘) as numeric entity references (&#038, &#039).

If the URL appears to be an absolute link that does not contain a scheme, prepends http://. Please note that relative urls (/my-url/parameter2/), as well as anchors (#myanchor) and parameter items (?myparam=yes) are also allowed and filtered as a special case, without prepending the default protocol to the filtered url.

Replaces the deprecated clean_url().


Top ↑

Source Source

File: wp-includes/formatting.php

function esc_url( $url, $protocols = null, $_context = 'display' ) {
	$original_url = $url;

	if ( '' === $url ) {
		return $url;
	}

	$url = str_replace( ' ', '%20', ltrim( $url ) );
	$url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url );

	if ( '' === $url ) {
		return $url;
	}

	if ( 0 !== stripos( $url, 'mailto:' ) ) {
		$strip = array( '%0d', '%0a', '%0D', '%0A' );
		$url   = _deep_replace( $strip, $url );
	}

	$url = str_replace( ';//', '://', $url );
	/*
	 * If the URL doesn't appear to contain a scheme, we presume
	 * it needs http:// prepended (unless it's a relative link
	 * starting with /, # or ?, or a PHP file).
	 */
	if ( strpos( $url, ':' ) === false && ! in_array( $url[0], array( '/', '#', '?' ), true ) &&
		! preg_match( '/^[a-z0-9-]+?\.php/i', $url ) ) {
		$url = 'http://' . $url;
	}

	// Replace ampersands and single quotes only when displaying.
	if ( 'display' === $_context ) {
		$url = wp_kses_normalize_entities( $url );
		$url = str_replace( '&', '&', $url );
		$url = str_replace( "'", ''', $url );
	}

	if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) {

		$parsed = wp_parse_url( $url );
		$front  = '';

		if ( isset( $parsed['scheme'] ) ) {
			$front .= $parsed['scheme'] . '://';
		} elseif ( '/' === $url[0] ) {
			$front .= '//';
		}

		if ( isset( $parsed['user'] ) ) {
			$front .= $parsed['user'];
		}

		if ( isset( $parsed['pass'] ) ) {
			$front .= ':' . $parsed['pass'];
		}

		if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) {
			$front .= '@';
		}

		if ( isset( $parsed['host'] ) ) {
			$front .= $parsed['host'];
		}

		if ( isset( $parsed['port'] ) ) {
			$front .= ':' . $parsed['port'];
		}

		$end_dirty = str_replace( $front, '', $url );
		$end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty );
		$url       = str_replace( $end_dirty, $end_clean, $url );

	}

	if ( '/' === $url[0] ) {
		$good_protocol_url = $url;
	} else {
		if ( ! is_array( $protocols ) ) {
			$protocols = wp_allowed_protocols();
		}
		$good_protocol_url = wp_kses_bad_protocol( $url, $protocols );
		if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) {
			return '';
		}
	}

	/**
	 * Filters a string cleaned and escaped for output as a URL.
	 *
	 * @since 2.3.0
	 *
	 * @param string $good_protocol_url The cleaned URL to be returned.
	 * @param string $original_url      The URL prior to cleaning.
	 * @param string $_context          If 'display', replace ampersands and single quotes only.
	 */
	return apply_filters( 'clean_url', $good_protocol_url, $original_url, $_context );
}


Top ↑

Changelog Changelog

Changelog
Version Description
2.8.0 Introduced.

Top ↑

User Contributed Notes User Contributed Notes

  1. Skip to note 2 content
    Contributed by Elio Rivero

    If the URI protocol is not one of the allowed protocols, the result of esc_url() is an empty string. The list of default protocols allowed by WordPress can be extended with the following code:

    <?php
    /**
     * Extend list of allowed protocols.
     *
     * @param array $protocols List of default protocols allowed by WordPress.
     *
     * @return array $protocols Updated list including new protocols.
     */
    function wporg_extend_allowed_protocols( $protocols ){
    	$protocols[] = 'skype';
    	$protocols[] = 'spotify';
    	$protocols[] = 'macappstores';
    	return $protocols;
    }
    add_filter( 'kses_allowed_protocols' , 'wporg_extend_allowed_protocols' );
    ?>

You must log in before being able to contribute a note or feedback.