11 comments

[ 5.8 ms ] story [ 35.7 ms ] thread
Author here, hi all. There are a number of ways to skin this cat. This is my preferred method. What's yours?
I generally prefer the oEmbed approach. It's mentioned on the SO question linked in Paul Irish's write-up. I'll throw together a sample at some point.
I made an Astro component for this [1] which does the iframe srcdoc thing [2] (example page with dozens of videos [3]). Most of the code is just TypeScript types and building a big srcdoc string, so easy to repurpose if anybody wants to.

Handling the fallback image has been sitting as an issue in the repo for a while, in favour of just checking it with the Astro dev server when I'm adding new videos, so… yoink‽

[1] https://github.com/insin/astro-lazy-youtube-embed#readme

[2] https://css-tricks.com/lazy-load-embedded-youtube-videos/

[3] https://jbscript.dev/notes/undefined/the-banterbox

I just took a look at the code that's returned when you open https://www.youtube.com/embed/<videoid>?feature=oembed and noticed a couple of additional image file names you may want to check.

        iurl: "default.jpg",
        iurlmq: "mqdefault.jpg",
        iurlhq: "hqdefault.jpg",
        iurlsd: "sddefault.jpg",
        iurlpop1: "pop1.jpg",
        iurlpop2: "pop2.jpg",
        iurlhq720: "hq720.jpg",
        iurlmaxres: "maxresdefault.jpg"

        120: "default.jpg",
        320: "mqdefault.jpg",
        480: "hqdefault.jpg",
        560: "pop1.jpg",
        640: "sddefault.jpg",
        854: "pop2.jpg",
        1280: "hq720.jpg"
Easiest solution is just to use the highest resolution thumbnail the official documentation says is supported on all videos (vs "some"), which is hqdefault.

https://developers.google.com/youtube/v3/docs/thumbnails

Maxresdefault is overkill for this purpose IMO. Why waste the data? Incidentally this is why I run an add-on that redirects all youtube thumbnails to mqdefault, it saves me a nice chunk of bandwidth / memory / perf.

If you can afford to add a little extra logic to your web server, you can solve this without JavaScript shenanigans (plus it doesn't leak your visitors' IPs to Google. On Nginx, for example:

  location ~ /vi/(.*)/thumbnail($|\..*) {
      error_page 404 = @hqdefault;
      proxy_intercept_errors on;
      proxy_pass https://img.youtube.com/vi/$1/maxresdefault$2;
  }
  
  location @hqdefault {
      proxy_pass https://img.youtube.com/vi/$1/hqdefault$2;
  }
Then simply use /vi/<id>/thumbnail.webp as the image source or adapt the location regex as needed. This can be chained with yet more fallback URLs.
If you're designing the website, why depend on a YT thumbnail? Can't you just use your own image that you have control over, and then load the actual YT when clicked? So many image gallery style components do this. Even if you don't need a gallery, it shows it is clearly possible. It's not like you're trying to work when JS is blocked
I seem to remember this stupid behavior with maxresdefault going back at least a decade.

As though there is no way that it could default to the correct thumbnail for any video -- surely it would not just help random hackers like OP, but also be more efficient for internal teams at Google to be able to render a preview for a video knowing only its ID, instead of making an API call to get the correct thumbnail name.

Great example of a 10-minute bug being prioritized at #837,434,212 and never resolved. I'd like to judge harshly, but let's be honest, most codebases older than a month have their share of these embarrassments.

So glad to find some like-minded folk who care about this! Nice post, Shane.

Thanks for calling out my research on this. Really glad you found it.

https://github.com/paulirish/lite-youtube-embed/pull/167 has my solution. Basically we only attempt the hqdefault.jpg and the sddefault.webp; no other ones. Based on my research this is (probably) the best solution that optimizes for both latency and coverage. Though, I could see switching the order of two in the future.

Pretty sure the oEmbed solutions folks are mentioning are only reasonable if you're doing this work server-side/eagerly. Obviously that changes things quite a bit.

would love to see the next post on Try fighting with youtube to get your chapters to be shown on a 20 min long video. no amount of editing the video description or metadata has retriggered their backend API to reconsider indexing chapters on your video. YT community posts are full of complaints on this
Have you seen the oEmbed format: https://abdus.dev/posts/youtube-oembed/ ?

I was really happy when I discovered it when I was researching how Wagtail CMS implements the embedded content previews.

For your example it returns:

  "thumbnail_url": "https://i.ytimg.com/vi/bJ7mTY9501c/hqdefault.jpg",
The file is smaller but shows up correctly!