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

4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
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:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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.