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.Please, please close that parenthese. Please, I beg of you. I can do it for you if you'd like.) There. Sorry.
The edit button is gone, sorry :)
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.
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
You’d probably want it to match YouTube’s preview image, so if your reader sees the video on YouTube proper at a later date, they’ll recognize it. I’m not sure of a good way to do that, since it’s not necessarily a screengrab from the middle of the video.
Does YT not allow you to set a poster frame? I'm not a heavy YT poster and am much more familiar with Vimeo that does allow a custom poster frame. In that case, you could ensure the poster is the same everywhere.
I don’t know how possible that is anymore. Youtube is letting creators A/B test thumbnails and titles now. So the thumbnail and title isn’t consistent between users or page visits.
It’s tripped me up several times. Although it’s unclear how much it’s the new feature or creators manually trying to game the algorithm by shuffling the title and thumbnail around.
I believe it's consistent per user (account or logged out) while the test is ongoing then switches to the "winning" thumbnail for everyone once it concludes. Tests can be re-run as many times as you want though.
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.
That reminds me of another YouTube embarrassment: Some ten years ago, Facebook added a "translate" button to every comment. The translations were pretty bad (they used Bing Translate rather than the much better Google Translate), but it was really useful to understand people from all over the world.
You would think YouTube (owned by Google) would in short order also add such a button to comments. Haha, no. They didn't.
About a decade later, probably more, they finally implemented it, albeit only in desktop mode. Not a big deal, just millions and millions of unreadable comments for millions of users for many years. Was probably prioritized at #837,434,211.
Even right now the translate button on YouTube is still broken, it doesn't depend of the languages of your account but on an inaccessible list somewhere.
You can have your translate button language different than your account language. (Which is the case for my account)
I think it has to do with the fact that YouTube basically never had serious competitors except in the very early days. The only semi-competition is now TikTok, which they copied with YouTube Shorts. But their regular video business has been completely unchallenged for 15 years. In an environment without competition, efficiency and effectiveness of internal decision making can easily degrade over time.
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!Author here, hi all. There are a number of ways to skin this cat. This is my preferred method. What's yours?
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.
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/
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.
So playing around with the goal of "highest quality thumbnail" in mind, I notice that the oEmbed data appears to always return the hqdefault.jpg url, regardless of what's available.
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"
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