Escáner QR HTML5

El escáner que funciona y la explicación de la API para quien lo va a construir.

La cámara solo se pide al pulsar el botón. Los fotogramas se descifran en este dispositivo y se descartan.

Un escáner HTML5 son tres API del navegador apiladas: getUserMedia para obtener el flujo de cámara, canvas para muestrear fotogramas y un decodificador. El decodificador es el BarcodeDetector nativo si existe, y si no, el decodificador JavaScript incluido. No hay plugins ni código nativo.

Esta página sirve como herramienta y como explicación porque mucha gente que busca esto va a construir el suyo y quiere saber dónde está la parte crítica.

Cómo se usa

  1. Si solo quieres leer un código, usa el escáner de arriba.
  2. Si vas a implementarlo, lee el orden de las API más abajo.
  3. Antes de elegir decodificador para producción, revisa las notas de compatibilidad.

El orden de implementación

getUserMedia({ video: { facingMode: 'environment' } }) para obtener el flujo, conectarlo a un elemento video y añadir playsinline: sin eso, Safari en iOS abre el vídeo a pantalla completa. Después se dibuja en un canvas a unas 8-10 fps y se pasa el canvas al decodificador. Al acertar, se detienen las pistas.

La trampa está en la resolución: pasar fotogramas a 1080p es lento y no mejora la precisión frente a 640 px de ancho. Reduce antes y decodifica a intervalos, no en cada requestAnimationFrame.

Revisado el 2026-10-21. Esta herramienta funciona por completo en tu navegador: sin servidor, sin cuenta y sin guardar nada de lo que generas.

Preguntas frecuentes

¿Hace falta una librería como html5-qrcode?

No es obligatorio. Una librería asume las diferencias entre navegadores y la interfaz; vale la pena si necesitas muchos formatos, pero para QR solo, BarcodeDetector con respaldo jsQR son unas decenas de líneas y mucho menos peso.

¿Por qué getUserMedia lanza una excepción en mi sitio?

Necesita un contexto seguro (HTTPS o localhost). En HTTP plano, navigator.mediaDevices es undefined, y esa es la causa más habitual.

¿Cómo se apaga la cámara al terminar?

Con stream.getTracks().forEach(t => t.stop()). Si el usuario puede salir a mitad, escucha pagehide y libera ahí también.

Herramientas relacionadas

Más de Códigos QR.