Skip to content

Instantly share code, notes, and snippets.

@joshuafredrickson
Last active December 11, 2025 20:53
Show Gist options
  • Select an option

  • Save joshuafredrickson/bb7ff4dc1e150f41d00a5d708b55f500 to your computer and use it in GitHub Desktop.

Select an option

Save joshuafredrickson/bb7ff4dc1e150f41d00a5d708b55f500 to your computer and use it in GitHub Desktop.
Fix YouTube 153 errors on existing embedded iframes
<script>
(function () {
const OEMBED_URL_BASE = "https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=";
const processedIframes = new WeakSet();
function getVideoIdFromSrc(src) {
if (!src) return null;
try {
const url = new URL(src, window.location.origin);
if (url.hostname.includes("youtu.be")) {
const idPath = url.pathname.replace(/\/+/, "");
if (idPath) return idPath;
}
const path = url.pathname || "";
const embedIndex = path.indexOf("/embed/");
if (embedIndex !== -1) {
const rest = path.substring(embedIndex + 7);
if (rest) return rest.split("/")[0];
}
const v = url.searchParams.get("v");
if (v) return v;
} catch (e) {
const m = src.match(/embed\/([^?&]+)/);
if (m && m[1]) return m[1];
}
return null;
}
async function replaceIframeFromOEmbed(iframe, videoId) {
if (!videoId) return;
const url = OEMBED_URL_BASE + encodeURIComponent(videoId) + "&format=json";
try {
const res = await fetch(url);
if (!res.ok) return;
const data = await res.json();
if (!data || !data.html) return;
const tmp = document.createElement("div");
tmp.innerHTML = data.html;
const newIframe = tmp.querySelector("iframe");
if (!newIframe) return;
// Preserve layout/styling attributes from the original iframe
if (iframe.className) {
newIframe.className = iframe.className;
}
if (iframe.getAttribute("style")) {
newIframe.setAttribute("style", iframe.getAttribute("style"));
}
const width = iframe.getAttribute("width");
const height = iframe.getAttribute("height");
if (width) newIframe.setAttribute("width", width);
if (height) newIframe.setAttribute("height", height);
iframe.replaceWith(newIframe);
} catch (e) {
// swallow
}
}
function applyPolicy(root) {
const base = root || document;
const elements = [];
if (base.tagName === "IFRAME") {
elements.push(base);
}
base
.querySelectorAll('iframe[src*="youtube.com"], iframe[src*="youtu.be"]')
.forEach((el) => elements.push(el));
elements.forEach((el) => {
const src = el.getAttribute("src") || "";
if (processedIframes.has(el)) {
return;
}
// Only touch iframes that do NOT already specify a referrerpolicy
if (el.hasAttribute("referrerpolicy")) {
processedIframes.add(el);
return;
}
const videoId = getVideoIdFromSrc(src);
if (!videoId) {
processedIframes.add(el);
return;
}
processedIframes.add(el);
replaceIframeFromOEmbed(el, videoId);
});
}
// Run once on load/DOM ready
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => applyPolicy(document));
} else {
applyPolicy(document);
}
window.addEventListener("load", () => applyPolicy(document));
// Watch for iframes that get injected later
const mo = new MutationObserver((mutations) => {
for (const m of mutations) {
for (const n of m.addedNodes || []) {
if (n.nodeType !== 1) continue; // elements only
applyPolicy(n);
}
}
});
mo.observe(document.documentElement, { childList: true, subtree: true });
})();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment