Capturas fiables en navegadores headless
Flujo práctico para capturas headless fiables con viewport de perfil, señales de disponibilidad, captura nativa completa, revisión del final y memoria para contenedores.
Prefieres la documentación del producto mantenida?
Este artículo tiene una página equivalente en el centro de documentación. Usa los docs para el flujo canónico, las flags actuales y la referencia duradera.
Empiece por el viewport del perfil
Una captura solo resulta útil cuando representa la página que el navegador debía renderizar. En una sesión basada en un perfil, el viewport es el primer elemento del acuerdo de renderizado. Controla los saltos de línea, los puntos de cambio responsive, la navegación fija, el tamaño de las imágenes y la cantidad de contenido visible antes de desplazarse. No es un valor temporal que el script pueda cambiar para facilitar una captura.
Un fallo habitual consiste en dejar que la biblioteca de automatización elija un viewport cómodo. El contexto puede ser más estrecho que el perfil seleccionado y la página se reorganiza antes de crear la imagen. Otro fallo consiste en poner la altura del viewport a la altura del documento para conseguir una captura completa. Eso cambia el diseño responsive y hace que el resultado ya no represente la sesión del navegador.
Cuando el perfil debe proporcionar las dimensiones, deje el viewport del contexto
sin configurar. En Puppeteer use defaultViewport: null. En Playwright cree el
contexto sin sobrescribir viewport. Si el producto necesita otro tamaño, incluya
esa decisión en el perfil y en la especificación de captura, y manténgala igual
en las ejecuciones comparables.
const browser = await chromium.launch({
executablePath: process.env.BROWSER_BINARY,
args: [`--bot-profile=${process.env.BROWSER_PROFILE}`],
});
const context = await browser.newContext();
const page = await context.newPage();
El ejemplo no contiene una configuración de viewport a propósito. Esa omisión es la parte importante. No use una función de resize para hacer coincidir la altura del documento. Un documento largo debe seguir siendo largo dentro del viewport del perfil.

Defina el estado listo con señales de la página
Que termine la navegación no significa que la imagen esté lista. La página puede haber terminado su carga inicial mientras la aplicación coloca tarjetas, carga un gráfico, selecciona el idioma o cambia las fuentes de reserva por las definitivas. Una captura tomada entre esos pasos es una imagen válida de un estado que el lector no debía recibir.
Defina un pequeño acuerdo de disponibilidad para cada ruta. Un marcador creado por la página suele ser más fiable que una espera fija, porque la página puede crearlo cuando está presente el contenido necesario. Puede ser un elemento con un atributo estable, un estado visible o un componente de ruta que solo aparece después del último cambio de diseño. El acuerdo debe describir el contenido visible y no depender de un evento privado del navegador.
Un acuerdo útil suele comprobar lo siguiente:
- El contenedor principal existe y está visible.
- Los datos de la vista solicitada ya se han renderizado.
- Han terminado los cambios de diseño posteriores a la llegada de los datos.
- Las fuentes de títulos, etiquetas y texto están listas.
- Las imágenes de la zona solicitada han cargado o han llegado a un estado de reserva intencionado.
- Una captura completa tiene un marcador claro de final.
El marcador final es especialmente útil en páginas progresivas. Que aparezca la primera tarjeta no dice nada sobre la mitad inferior de un informe. Esperar el marcador de final proporciona un límite estable. Si la ruta no tiene un final natural, defina un límite de captura deliberado en lugar de tratar un documento que crece sin límite como si estuviera completo.
Orden de espera práctico
El siguiente patrón combina un marcador de ruta, la disponibilidad de fuentes y el estado de las imágenes. No duerme durante un intervalo arbitrario. Cambie los selectores para cada página y haga que los marcadores formen parte del acuerdo de la ruta, no de un selector genérico usado en todo el sitio.
async function waitForCaptureReady(page) {
await page.waitForLoadState('domcontentloaded');
await page.locator('[data-capture-ready]').waitFor({ state: 'visible' });
await page.locator('[data-capture-end]').waitFor({ state: 'visible' });
await page.evaluate(async () => {
await document.fonts.ready;
await Promise.all(
[...document.images].map(image =>
image.complete
? undefined
: new Promise(resolve => {
image.addEventListener('load', resolve, { once: true });
image.addEventListener('error', resolve, { once: true });
})
)
);
});
}
La rama de imágenes trata una miniatura opcional que no llega como una reserva terminada, para que un recurso secundario no bloquee el trabajo. Si todas las imágenes son necesarias, haga que el marcador de la página espere a los recursos obligatorios y registre una falta clara cuando uno no esté disponible.
La ausencia de actividad de red puede servir como señal auxiliar, pero no debe ser la única. Las actualizaciones en vivo, las conexiones persistentes y las consultas periódicas pueden mantener ocupada una página cuando el contenido visible ya está listo. Por otro lado, un renderizado del cliente puede terminar sin otra petición. El acuerdo de la página debe expresar el estado que el lector necesita ver.
Evite una pausa fija después de la navegación. En una página rápida solo añade espera y en una página lenta todavía puede capturar demasiado pronto. También oculta la razón por la que la página no estaba disponible. Un marcador estable deja un punto que se puede revisar cuando cambia la ruta.
Capture la página completa sin estirar el viewport
Para una imagen del viewport, use la opción de captura normal. Para una imagen del documento, use la opción nativa de página completa de la biblioteca de automatización. Esa opción conserva el viewport del perfil y llega al contenido situado debajo de la zona visible.
await waitForCaptureReady(page);
await page.screenshot({
path: outputPath,
fullPage: true,
type: 'png',
});
No establezca la altura del viewport a la altura del documento antes de esta llamada. Ese atajo cambia el diseño responsive, puede impedir que el desplazamiento active contenido diferido y crea una imagen que ya no representa el perfil elegido. También puede producir una superficie mayor que la capacidad del sistema gráfico o de la memoria del contenedor.
Si hay contenido diferido, puede prepararlo con desplazamiento normal antes de la captura nativa. Desplazarse sirve para pedir a la página que cargue el rango que se quiere conservar. No sustituye a la captura completa. Vuelva a la posición superior, confirme de nuevo el acuerdo de disponibilidad y deje que la opción nativa recopile el documento.
El desplazamiento infinito necesita un límite explícito. Decida si la imagen termina en el conjunto cargado, en una sección con nombre o en un estado final de la ruta. No permita que el trabajo se desplace indefinidamente mientras la página añade elementos. Un informe con límites definidos es más fácil de revisar, almacenar y comparar, y su altura no depende del momento exacto de la captura.
Elementos fijos y diseño responsive
Las cabeceras adhesivas, paneles de consentimiento, botones de chat y barras flotantes pueden cubrir contenido en una imagen completa. Si no forman parte del informe, la ruta de captura debe ofrecer una presentación de impresión o archivo. Una hoja de estilos pequeña y específica para la captura suele ser más clara que intentar borrar elementos después de crear la imagen. Mantenga el viewport del perfil sin cambios.
Use el mismo viewport en ejecuciones comparables. Cambiar el ancho cambia los saltos de línea y la posición de las tarjetas aunque los datos sean iguales. Cambiar el factor de píxeles del dispositivo también cambia las dimensiones de salida y la memoria necesaria durante la creación. Registre estos valores como metadatos de la captura, no como decisiones accidentales del script.
Revise la parte inferior de cada imagen larga
El final de una imagen larga merece una comprobación propia. La parte superior puede verse bien mientras el pie, la última fila, los bordes o el fondo se cortan. También puede quedar un marcador de carga en la parte inferior. Abrir siempre la imagen desde la esquina superior hace que estos problemas pasen desapercibidos.
Añada un marcador final estable a la página e inclúyalo en la muestra de revisión. Puede ser el título del pie, la última sección del informe o una zona de finalización que tenga sentido para el lector. Debe aparecer en la imagen final, no ser una marca oculta de la ejecución del navegador.
Revise el extremo inferior de tres maneras:
- Abra una vista reducida y confirme que el documento llega al final previsto.
- Abra la última parte a una escala legible y revise la última fila, el pie, los bordes y el relleno del fondo.
- Compare las dimensiones y el tamaño del archivo con el registro de captura. Un cambio repentino puede indicar un movimiento de diseño, una sección ausente o un recurso que no llegó.
Las comprobaciones automáticas deben centrarse en el acuerdo de la página y en el archivo generado. Confirme que el marcador final estaba visible antes de capturar, que el archivo existe y que la imagen se puede decodificar. Conserve unas pocas páginas largas representativas para revisión visual. La comparación de píxeles es útil en un conjunto controlado, pero conviene acompañarla con una revisión legible: las fuentes, el renderizado de la plataforma y los cambios legítimos de contenido pueden modificar píxeles concretos.
No use la altura bruta del documento como única condición de éxito. La altura puede existir antes de que se pinte el contenido y puede seguir creciendo después de crear la imagen. El marcador final y la revisión del archivo responden mejor a la pregunta que importa: ¿llegó el contenido previsto a la imagen final?
Reserve memoria compartida para imágenes altas en contenedores
Una imagen larga consume más que el tamaño final del PNG o JPEG en disco. El navegador necesita espacio de trabajo mientras compone la página, la capa de automatización necesita espacio mientras recibe el resultado y el codificador lo necesita mientras escribe el archivo. Un perfil de alta densidad de píxeles aumenta la superficie en ambas direcciones. Un montaje pequeño de memoria compartida puede fallar solo con la página más larga y parecer un problema ocasional.
Reserve memoria compartida según el trabajo real. Considere el viewport del perfil,
el factor de píxeles, el documento más largo aprobado, el formato de imagen y las
capturas que puedan coexistir en el contenedor. Deje espacio para el arranque del
navegador y el renderizado habitual. Establezca de forma explícita el tamaño de
/dev/shm con el runtime del contenedor o con el ajuste equivalente de Compose, en
lugar de aceptar el valor pequeño predeterminado.
docker run --rm \
--shm-size="${BROWSER_SHM_SIZE}" \
-e BROWSER_PROFILE=/run/profiles/capture.enc \
screenshot-worker
El valor debe pertenecer a la configuración de despliegue porque depende del conjunto de páginas aprobado. No copie la configuración de una prueba de página corta a un trabajo de documentos largos. Cuando cambie el conjunto, vuelva a capturar la página representativa más exigente y revise tanto el resultado como los recursos del contenedor.
También importan otros recursos. El directorio de salida debe admitir la imagen completa y su escritura temporal, el montaje debe tener la propiedad que usa el worker y el almacenamiento del perfil debe estar separado de los artefactos finales. Una escritura fallida no debe reemplazar la imagen aprobada anterior con un archivo parcial. Escriba primero con un nombre temporal en el mismo volumen, cierre el archivo y después use la operación atómica normal del sistema de archivos.
Si la configuración Linux aprobada usa Xvfb, su superficie debe cubrir el viewport del perfil y utilizar la configuración de color validada para el despliegue. El modo headless nativo puede no necesitar Xvfb. No añada una pantalla virtual solo porque la imagen sea alta. Elija un camino compatible, pruébelo con las páginas objetivo y manténgalo igual en desarrollo y producción.
Elija el formato según el uso
PNG es una opción segura para texto, diagramas, interfaces y regresiones visuales. Conserva los bordes definidos y evita artefactos cerca de las etiquetas pequeñas. JPEG puede ser apropiado para vistas previas con muchas fotografías cuando importa más el tamaño del archivo que la precisión de los bordes. Incluya el formato en la especificación para que otro trabajo no cambie el criterio de revisión.
La salida de alta densidad de píxeles ayuda cuando el lector ampliará un informe o cuando la imagen se conservará como archivo. También aumenta memoria, transferencia y almacenamiento. El perfil seleccionado debe proporcionar el factor de píxeles; no lo sobrescriba en el contexto solo para conseguir una imagen más nítida. Si se necesita una vista previa pequeña, créela después de conservar la captura aprobada.
Use nombres estables que registren la ruta, la familia del perfil, el modo, el formato y la fecha, sin incluir datos privados de la página. Conserve el artefacto original cuando genere una variante. Así se puede distinguir un cambio de renderizado de un cambio de miniatura en una revisión posterior.
Un patrón de producción pequeño
La función de captura debe mostrar el orden sin ambigüedad: abrir una página basada en el perfil, navegar, esperar el acuerdo de la página, usar la opción nativa de página completa cuando corresponda y cerrar la página si la captura falla.
async function capture(page, url, outputPath, fullPage = false) {
await page.goto(url, { waitUntil: 'domcontentloaded' });
await waitForCaptureReady(page);
await page.screenshot({
path: outputPath,
fullPage,
type: 'png',
});
}
Si varias rutas comparten la misma política de sesión aprobada, cree el navegador fuera de esta función. Mantenga clara la propiedad de cada página, ciérrela cuando el artefacto esté completo y entregue el error junto con la ruta y el modo. Una captura fallida debe ser visible para el ejecutor, no sustituirse en silencio por un archivo antiguo.
En un lote, cada página debe pasar por las mismas comprobaciones de disponibilidad y artefacto. No cree una vía rápida que omita el marcador final para las páginas que vienen después. La primera página suele verse bien; una página lenta revela memoria insuficiente, fuentes tardías o un documento que sigue creciendo. Un acuerdo común facilita interpretar esas diferencias.
Síntomas y orden de revisión
La imagen está vacía o casi vacía. Confirme que la navegación llegó a la ruta prevista, que apareció el marcador de listo y que el camino de pantalla elegido está disponible. Revise la salida del navegador para saber si la página se detuvo antes del marcador, en vez de añadir otra pausa.
La imagen termina antes de la última sección. Confirme el marcador final, prepare el contenido diferido con desplazamiento normal y compruebe que el desplazamiento infinito tiene un límite. Después revise el extremo inferior del archivo.
El texto cambia entre capturas. Confirme el mismo viewport del perfil, factor de píxeles, fuentes, esquema de color y datos. Espere a que las fuentes estén listas y revise los cambios de diseño antes de capturar.
El contenedor falla solo con páginas largas. Revise juntos el montaje de memoria compartida, el espacio temporal, el volumen de salida y la superficie de pantalla. Una página corta no demuestra que quepa la imagen más larga. Ajuste el recurso, repita la captura representativa y guarde el ajuste con el registro del trabajo.
Un control flotante cubre el informe. Use la presentación de archivo de la ruta o capture un elemento de contenido significativo. No edite los píxeles después y confirme que la presentación conserva el viewport del perfil.
Aparece un marcador de carga. Haga que el marcador de listo espere al recurso necesario o declare la reserva como intencionada. El estado de red por sí solo no indica si el lector puede aceptar un marcador.
Revise antes de convertir la captura en referencia
Mantenga una muestra pequeña y representativa para la revisión del despliegue. Incluya una página corta, un informe largo, una página con fuentes web, una página con medios diferidos y un diseño responsive que use el perfil seleccionado. La intención no es reunir todas las rutas, sino cubrir los estados que cambian el límite de la imagen o la demanda de recursos.
Para cada ruta registre el perfil, el origen del viewport, el modo, el formato, el camino de pantalla, la política de memoria del contenedor, el marcador de listo y el marcador final. Revise la primera pantalla y la parte inferior. Confirme que el artefacto se puede decodificar, tiene la orientación esperada y se guarda en el lugar previsto. Cuando un cambio sea intencionado, actualice también el registro de captura.
Una captura fiable es un flujo de renderizado, no el último clic. El perfil aporta un viewport estable, la página aporta un estado listo con significado, la opción nativa de página completa alcanza el contenido inferior sin cambiar el viewport y la revisión presta atención a la parte que más fácilmente se pierde. La memoria compartida y el almacenamiento completan el acuerdo para documentos largos y de alta densidad de píxeles. Así las imágenes siguen siendo útiles para revisión visual, archivo y controles de calidad autorizados en distintos entornos.
Artículos Relacionados
Lleva BotBrowser de la investigación a producción
Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.