So apparently the issue also happens in WordPress 5.6 (the latest release as of writing), and YouTube is probably at fault because the (oEmbed) <link>
tags are in the body
instead of the head
(see screenshot below), and that in turn causes the issue because WP_oEmbed::discover()
looks for the <link>
tags in the head
only. And secondly, YouTube uses http://
instead of https://
(secure protocol) in the <link>
tags, so you would need to replace that http://
with https://
if your site uses https://
or is SSL-enabled.
Screenshot 1: Elements inspector tab (in Chrome)
Screenshot 2: Server-generated HTML source (press Ctrl+U
on Chrome)
And maybe (YouTube is not at fault and) the WordPress core team should revise the function so that it tries to also search in the body
? Or perhaps use a better way to find the tags like using DOMDocument …?
But anyway, as mentioned by @Rup, you could alternatively use WP_oEmbed::get_provider()
which will load the sanctioned/trusted oEmbed providers defined in the class constructor, and (as of writing) YouTube is actually the very first in the providers list.
// So instead of:
// this fetches the <link> tags from the provider site
$provider = $oembed->discover( $video_url );
// Use this one:
// this finds in the sanctioned oEmbed providers first
// then tries with the above discover()..
$provider = $oembed->get_provider( $video_url );
Or as I said in the comments, if you just wanted to get the HTML/embed code, then you could simply use wp_oembed_get()
which should work since, although indirectly, the function uses WP_oEmbed::get_data()
which uses WP_oEmbed::get_provider()
:
// I'd prefer this:
echo wp_oembed_get( $video_url );
// But that is equivalent to:
$video = $oembed->get_data( $video_url );
echo $video->html;
// And that is equivalent to:
$provider = $oembed->get_provider( $video_url );
$video = $oembed->fetch( $provider, $video_url );
echo $video->html;