How to remove pingback from head?

I know this question has been asked and answered 1000 times. However, I’ve never truly found a solution that removes pingback link tag from “wp_head”. While there are several ways to block xml-rcp/pingback/trackback from wordpress I’m trying to add to that by blocking it from the head

So basically I don’t want this showing up in the rendered html:

Closest solution I’ve ever found was this:

add_filter( 'bloginfo_url', 'pmg_kt_kill_pingback_url', 10, 2 );
function pmg_kt_kill_pingback_url( $output, $show ) {
    if( $show == 'pingback_url' ) {
        $output = '';
    }
    return $output;
}

But it still shows up like this:

<link rel="pingback" href>

I know this isn’t really a big deal, it was more annoying me than anything. I’ve been messing learning regex the past few days and I think I got the right patterns to remove pingback from the head.

The following two patterns remove all cases (from what I’ve tested of pingback):

/<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>/i

/<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>/i

I used the output buffer to achieve this:

if (!is_admin()) {      
        function link_rel_buffer_callback($buffer) {
            $buffer = preg_replace('/<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>/i', '', $buffer);
            return $buffer;
        }
        function link_rel_buffer_start() {
            ob_start("link_rel_buffer_callback");
        }
        function link_rel_buffer_end() {
            ob_flush();
        }
        add_action('template_redirect', 'link_rel_buffer_start', -1);
        add_action('get_header', 'link_rel_buffer_start');
        add_action('wp_head', 'link_rel_buffer_end', 999);
    }

However if I try to combine the two regex patterns it doesn’t work

if (!is_admin()) {      
        function link_rel_buffer_callback($buffer) {
            $buffer = preg_replace('/(?:<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>|<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>)/i', '', $buffer);
            return $buffer;
        }
        function link_rel_buffer_start() {
            ob_start("link_rel_buffer_callback");
        }
        function link_rel_buffer_end() {
            ob_flush();
        }
        add_action('template_redirect', 'link_rel_buffer_start', -1);
        add_action('get_header', 'link_rel_buffer_start');
        add_action('wp_head', 'link_rel_buffer_end', 999);
    }

I think the problem is I need to use preg_match. I tried checking with this and it worked:

function print_preg_match() {         
$pattern = '/(?:<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>|<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>)/i';
$subject = '<link rel="pingback" href="http://example.com/xmlrpc.php">';
if (preg_match($pattern, $subject, $matches)) {
   echo 'You Got A Match';
   }
}
add_action('all_admin_notices', 'print_preg_match');

However, I don’t know how to use it correctly in this situation. This may be more of a stackoverflow question since it’s dealing with regex, but i figured since it was specific to wordpress I put it up here.

Solutions Collecting From Web of "How to remove pingback from head?"

It was just a mistake I had made, the above would work like this:

$buffer = preg_replace('/(<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>|<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>)/i', '', $buffer);

HERE is the revised answer:

if (!is_admin()) {      
    function link_rel_buffer_callback($buffer) {
        $buffer = preg_replace('/(<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>|<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>)/i', '', $buffer);
                return $buffer;
    }
    function link_rel_buffer_start() {
        ob_start("link_rel_buffer_callback");
    }
    function link_rel_buffer_end() {
        ob_flush();
    }
    add_action('template_redirect', 'link_rel_buffer_start', -1);
    add_action('get_header', 'link_rel_buffer_start');
    add_action('wp_head', 'link_rel_buffer_end', 999);
}


// Alternatively use this to just remove the url or use it together with the above
add_filter('bloginfo_url', function($output, $property){
    return ($property == 'pingback_url') ? null : $output;
}, 11, 2);

This removes pingback from the source code on your frontend programmatically.

While most developers include it in the header like this:

<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />

… there are many cases where it could be written and executed differently

Such as:

<link rel="pingback" href="http://www.example.com/xmlrpc.php" />
<link rel='pingback' href='http://example.com/xmlrpc.php' />
<link href='http://example.com/xmlrpc.php' rel='pingback'>

For a complete solution that blocks ALL functionality and access to XML-RPC pingback and trackback refer to this answer associated with the correct question. There have been many recent exploits to this file so it is wise to do this if you aren’t using trackbacks/pingbacks:

Is There a Way to Completely Turn Off Pingbacks/Trackbacks?

Here’s my improvement on it with less code for the same results:

add_action( 'plugins_loaded', 'wpse_158700_buffer' );

function wpse_158700_buffer() {
    # Enable output buffering
    ob_start( 'wpse_158700_pingback_url' );
}

function wpse_158700_pingback_url( $buffer ) {
    # If in the admin panel, don't run
    if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
        return $buffer;
    }
    $buffer = preg_replace( '/(<link.*?rel=("|\')pingback("|\').*?href=("|\')(.*?)("|\')(.*?)?\/?>|<link.*?href=("|\')(.*?)("|\').*?rel=("|\')pingback("|\')(.*?)?\/?>)/i', '', $buffer );
    return $buffer;
}