Cargando Core...

YouTube JS Modal: implementación que NO activa la alerta “Inicia sesión para confirmar que no eres un bot”

Por qué esta implementación NO activa la alerta “Inicia sesión para confirmar que no eres un bot”

El mensaje antibot de YouTube se dispara principalmente cuando su firewall detecta patrones típicos de scrapers o peticiones huérfanas: ausencia de cabeceras de referencia claras, peticiones duplicadas sin descarga visual, o carga en segundo plano sin interacción real de usuario.

Código del snippet JS:

 

Esta arquitectura lo previene gracias a 4 mecanismos clave:

  1. Uso de youtube-nocookie.com (Línea 9): El host de privacidad mejorada sirve un reproductor optimizado para cumplimiento legal (RGPD) y tiene umbrales de seguridad antibot mucho más permisivos, ya que está diseñado específicamente para embeberse sin rastrear al usuario mediante cookies previas.

  2. Certificación criptográfica de dominio vía origin (Líneas 24-34): Un bot normalmente realiza peticiones headless (sin dominio de origen verificado). Al añadir dinámicamente el parámetro origin=[https://tudominio.com](https://tudominio.com) en la URL del iframe, le estás indicando a la API de YouTube exactamente desde qué host autorizado se está sirviendo el vídeo.

  3. Encabezado referrerpolicy="strict-origin-when-cross-origin" (Líneas 101): Fuerza al navegador del usuario a enviar la cabecera HTTP Referer hacia los servidores de Google. YouTube verifica que esa cabecera coincide con el parámetro origin de la URL. Esta doble validación confirma que es un navegador legítimo y no un script automatizado.

  4. Carga “Zero-Leak” bajo Demanda (Lazy Ingestion): El iframe no existe en el HTML inicial. Un patrón común de los bots es generar 10 o 20 iframes en el DOM oculto al cargar la página. Aquí, el vídeo solo se solicita a los servidores de YouTube después de que un usuario físico haga clic en el botón y se active el evento de Bootstrap (show.bs.modal).

Documentación técnica línea por línea

1. Encapsulamiento y Constantes

  • Línea 7 (function() {: Define una IIFE (Immediately Invoked Function Expression). Aísla absolutamente todas las variables en un ámbito local para no contaminar el espacio global (window) ni crear colisiones con otros scripts en producción.

  • Línea 8 'use strict';: Activa el modo estricto de ES5/ES6. Impide el uso de variables no declaradas y deshabilita características propensas a errores o agujeros de seguridad.

  • Líneas 10-12 const VIDEOS = { ... };: Objeto inmutable que actúa como diccionario para mapear el ID del botón (video-2) con su URL limpia (usando youtube-nocookie.com).

  • Líneas 14-17: Declaración de variables de estado inicializadas en null que actuarán como punteros en memoria para el nodo del modal, el contenedor del iframe, la instancia de Bootstrap y la URL en curso.

2. Optimizador de URL (prepareSecureYoutubeUrl)

  • Línea 26 if (!url) return '';: Cláusula de guarda para evitar ejecuciones nulas.

  • Línea 27 try { ... } catch (e): Bloque de seguridad para prevenir que una URL malformada rompa la ejecución del hilo principal de JavaScript.

  • Línea 28 const urlObj = new URL(url, window.location.href);: Instancia un objeto nativo URL de JavaScript, lo que permite manipular parámetros de consulta (query strings) de forma segura sin concatenar cadenas de texto en bruto.

  • Líneas 30-32 if (!urlObj.searchParams.has('origin')...: Verifica si la URL ya tiene el parámetro origin. Si no lo tiene y el protocolo web no es null (evitando errores al probar en archivos locales file://), inyecta el dominio del sitio (window.location.origin).

3. Construcción del DOM y Ciclo de Vida (createModal)

  • Líneas 41-45: Verifica mediante document.getElementById('videoModal') si el modal ya se había insertado previamente (por ejemplo, si la función se llamase más de una vez). Si existe, recupera sus referencias en el DOM y detiene la ejecución del constructor (return).

  • Líneas 47-60: Plantilla Literal (Template String) que define el HTML semántico del modal compatible con Bootstrap 5, manteniendo los atributos de accesibilidad (aria-hidden="true", aria-label="Cerrar").

  • Línea 62 document.body.insertAdjacentHTML('beforeend', html);: Inserta el HTML justo antes del cierre del </body> sin romper ni reconstruir el resto del árbol DOM (mucho más eficiente en rendimiento que usar innerHTML).

  • Líneas 66-73: Comprueba la existencia global del objeto bootstrap.Modal. Si está disponible, inicializa el modal permitiendo cerrarlo al pulsar ESC (keyboard: true) o al hacer clic en el fondo oscuro (backdrop: true). Si no, emite un error por consola y aborta.

  • Líneas 76-82 (show.bs.modal): Evento nativo de Bootstrap que se dispara cuando el modal empieza a abrirse.

    • Comprueba si hay una URL activa y si no hay un iframe previo cargado, invocando a loadIframe(currentVideoUrl).

    • Aplica overflow: 'hidden' y paddingRight: '0px' al body para evitar saltos visuales en la barra de desplazamiento (scroll jumping).

  • Líneas 85-91 (hidden.bs.modal): Evento que se dispara en cuanto el modal termina de cerrarse.

    • Llama a destroyIframe() para eliminar instantáneamente el reproductor.

    • Restaura los estilos del body y reinicia el estado de currentVideoUrl.

4. Inyección Segura del Iframe (loadIframe)

  • Líneas 99-100: Cláusula de guarda y ejecución preventiva de destroyIframe() para garantizar que jamás existan dos iframes simultáneos en el contenedor.

  • Líneas 102-103: Pasa la URL por el optimizador de seguridad y crea en la memoria del navegador el elemento <iframe />.

  • Líneas 105-108: Asigna las propiedades base (src, title, frameborder) e inyecta la API de permisos del navegador (allow) autorizando la reproducción automática, giroscopio y pantalla completa.

  • Líneas 112-113:

    • referrerpolicy="strict-origin-when-cross-origin": Punto crítico antibot. Obliga al navegador a validar la procedencia legítima ante YouTube.

    • loading="eager": Indica al motor de renderizado que cargue el recurso de inmediato sin diferirlo, evitando retrasos una vez que el modal se ha abierto.

  • Línea 115 videoContainer.appendChild(iframe);: Inserta finalmente el nodo del iframe dentro del contenedor del modal, iniciando la solicitud de red hacia los servidores de Google.

5. Destrucción Radical y Gestión de Memoria (destroyIframe)

  • Líneas 124-130: Selecciona el iframe si existe.

    • iframe.src = '';: Punto crítico de rendimiento. Vaciando el src antes de destruir el elemento, se obliga al motor del navegador (especialmente WebKit en Safari/iOS) a abortar cualquier conexión HTTP o transmisión de audio pendiente.

    • iframe.remove();: Desvincula el elemento del DOM.

  • Líneas 133-137: Limpieza profunda del contenedor. Utiliza el método nativo moderno replaceChildren() (más rápido que alterar strings con innerHTML = '') para garantizar que no queden referencias en memoria que puedan provocar fugas (memory leaks).

6. Inicialización y Evento de Arranque (init)

  • Línea 144 createModal();: Prepara el contenedor oculto en el DOM.

  • Líneas 147-164: Recorre el objeto VIDEOS usando Object.entries().

    • Busca en el DOM cada botón (por ejemplo, #video-2).

    • Le asigna un detector de clic (click).

    • Línea 153 e.preventDefault();: Previene el comportamiento por defecto (evita que un enlace <a href="#"> haga saltar la página hacia arriba).

    • Líneas 156-160: Comprueba si el modal ya estaba abierto en pantalla (modalElement.classList.contains('show')). Si lo está, recarga el iframe con el nuevo vídeo al vuelo. Si estaba cerrado, ordena a la API de Bootstrap abrirlo (bsModal.show()).

  • Líneas 168-172: Prevención de condiciones de carrera en el DOM (Race Conditions). Comprueba si el documento aún se está procesando (loading). Si el script se cargó en la cabecera, espera al evento DOMContentLoaded; si se cargó en el pie de página y el DOM ya está listo, ejecuta init() inmediatamente.

Documento monolítico HTML5: aplicación autónoma y lista para producción. Incluye las dependencias por CDN (Bootstrap 5 y FontAwesome) para que puedas probarlo directamente guardando el código en un único archivo index.html o (index.php).

En esta arquitectura se incorporan:

  1. Capa de Sanitización defensiva contra XSS para validar y sanitizar URLs y cadenas antes de inyectarlas en el DOM.

  2. Caché persistente del DOM (DOMCache) usando estructuras de datos eficientes (Map) para evitar lecturas recurrentes al árbol de nodos durante eventos repetidos de clic.

  3. CSS3 encapsulado y responsivo con soporte para aspect-ratio 16:9 nativo y padding-bottom como fallback, evitando saltos de reflow visual (CLS – Cumulative Layout Shift).

Detalles Técnicos de las Nuevas Capas

  1. Capa de Sanitización XSS (escapeHTML y isValidHttpUrl):

    • escapeHTML() convierte caracteres potencialmente peligrosos (<, >, ", ', &) en entidades HTML equivalentes.

    • isValidHttpUrl() descarta cualquier esquema invalido (como javascript: o cadenas corruptas) antes de permitir que la URL llegue al atributo .src del iframe.

  2. Caché del DOM (DOMCache):

    • En lugar de declarar múltiples variables sueltas, se centraliza la memoria del módulo en un objeto DOMCache.

    • Los elementos de interfaz disparadores (botones) se registran en una instancia de Map(), ofreciendo búsquedas directas con tiempo de complejidad $O(1)$ sin realizar recorridos repetidos sobre el documento.

  3. Optimización CSS de Aspect Ratio (Previene Reflow y CLS):

    • Se utiliza la propiedad moderna CSS3 aspect-ratio: 16 / 9 junto a una regla @supports que mantiene el soporte tradicional padding-bottom: 56.25% para navegadores antiguos. Esto garantiza que el reproductor ocupe exactamente el espacio del contenedor antes y durante la carga del video, eliminando parpadeos visuales.

 

Scroll al inicio