esc_url( string $url, array $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.


Parameters Parameters

$url

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

$protocols

(array) (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 ↑

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', $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 a relative
	 * link starting with /, # or ? or a php file).
	 */
	if ( strpos( $url, ':' ) === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
		! 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 1 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.