Read this article in English.
HTML a imagen: 6 formas de convertir HTML en PNG o JPG (con código)
Respuesta corta: para pasar HTML a imagen necesitas algo que lo dibuje como un navegador y le haga una foto. Dentro de una página web, usa las librerías de JavaScript html-to-image o html2canvas. En un servidor, abre el HTML con Chrome sin ventana mediante Puppeteer o Playwright y llama a
screenshot(). Si no quieres mantener un navegador, manda el HTML a una API de HTML a imagen y recibe el PNG en una sola petición.
Convertir HTML en imagen es como se hacen la mayoría de tarjetas para redes, imágenes de vista previa (Open Graph), certificados, entradas, tickets y banners para emails: diseñas una vez en HTML y CSS, rellenas los datos y exportas un PNG, JPG o WebP. La idea es sencilla. Lo difícil es que las fuentes, las imágenes y el CSS salgan exactamente igual que en tu navegador, siempre y sin que se corte nada.
Esta guía recoge las seis formas que funcionan de verdad, con código para copiar, y cuándo conviene cada una.
Qué método elegir
| Método | Dónde funciona | ¿Igual que Chrome? | Ideal para |
|---|---|---|---|
| html-to-image | Navegador del visitante | Casi | Descargas desde tu web |
| html2canvas | Navegador del visitante | Casi | Lo mismo, más antigua |
| Puppeteer | Tu servidor | Sí | Proyectos en Node.js |
| Playwright | Tu servidor | Sí | Python, Java, .NET o Node |
| html2image | Tu ordenador | Sí | Scripts rápidos en Python |
| Una API | El servidor de otro | Sí | Sin código y sin navegador |
Falta uno a propósito: wkhtmltoimage (y imgkit en Python, que lo usa por debajo). Lleva un motor de navegador muy antiguo, el proyecto se archivó en 2023 y el CSS moderno, como las rejillas (grid), suele salir roto. Mejor no usarlo en proyectos nuevos.
1. En el navegador: html-to-image
Si el HTML ya está en pantalla y quieres que el visitante lo descargue como imagen, el paquete html-to-image lo hace sin servidor:
import { toPng } from 'html-to-image';
const node = document.getElementById('tarjeta');
const dataUrl = await toPng(node, { pixelRatio: 2 });
const link = document.createElement('a');
link.download = 'tarjeta.png';
link.href = dataUrl;
link.click();
También tiene toJpeg, toSvg y toBlob. A tener en cuenta: las imágenes de otro dominio solo salen si ese servidor lo permite (CORS), las fuentes web tienen que haber terminado de cargar y algún efecto de CSS puede salir un poco distinto. Solo funciona donde hay un navegador, así que no sirve en un servidor ni en una automatización.
2. En el navegador: html2canvas
html2canvas es la alternativa más antigua y muy popular. Lee el CSS de la página y lo vuelve a dibujar en un lienzo (canvas):
const canvas = await html2canvas(document.getElementById('tarjeta'), { scale: 2 });
const png = canvas.toDataURL('image/png');
Como hace el dibujo por su cuenta, el CSS que no entiende simplemente lo salta, así que revisa bien los diseños complejos. Mismos límites que arriba con las imágenes de otros dominios.
3. En un servidor con Node.js: Puppeteer
Cuando la imagen se tiene que crear en un servidor (una tarjeta por cada artículo nuevo, un certificado por alumno), hace falta un navegador de verdad. Puppeteer abre Chrome sin ventana, carga tu HTML y hace la captura:
import puppeteer from 'puppeteer';
const html = '<div style="font:700 48px sans-serif;padding:40px">Hola</div>';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 630, deviceScaleFactor: 2 });
await page.setContent(html, { waitUntil: 'networkidle0' });
await page.screenshot({ path: 'tarjeta.png' });
await browser.close();
El resultado es exactamente lo que enseña Chrome. El precio es mantener un navegador en tu servidor: memoria por cada página, actualizaciones, tiempos máximos y cuidado con la seguridad si el HTML lo escriben tus usuarios, porque ese navegador llega a todo lo que llega tu servidor.
4. En Python: Playwright o html2image
Playwright hace lo mismo desde Python (pip install playwright y después playwright install chromium):
from playwright.sync_api import sync_playwright
html = "<div style='font:700 48px sans-serif;padding:40px'>Hola</div>"
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1200, "height": 630}, device_scale_factor=2)
page.set_content(html, wait_until="networkidle")
page.screenshot(path="tarjeta.png")
browser.close()
Para un script rápido en tu ordenador, el paquete html2image usa el Chrome o el Edge que ya tienes instalado:
from html2image import Html2Image
hti = Html2Image(size=(1200, 630))
hti.screenshot(html_str="<h1>Hola</h1>", save_as="tarjeta.png")
5. En PHP, Java y .NET
La idea es la misma en todos los lenguajes: manejar un navegador sin ventana.
- PHP: Browsershot usa Puppeteer por debajo, así que necesita Node.js en el servidor:
Browsershot::html($html)->windowSize(1200, 630)->save('tarjeta.png'); - Java: Playwright para Java: carga el HTML con
page.setContent(html)y guárdalo conpage.screenshot(...). - .NET: Playwright para .NET o PuppeteerSharp, con los mismos dos pasos.
6. Con una API: sin navegador que mantener
Una API de HTML a imagen pone el navegador por ti: le mandas el HTML y te devuelve la imagen. Es la opción práctica si trabajas con una herramienta sin código, si no quieres tener Chrome funcionando en un servidor o si solo necesitas unas pocas imágenes al día.
Con Cofferdock basta una petición:
curl -X POST "https://api.cofferdock.com/capture?width=1200&height=630" \
-H "x-api-key: TU_LLAVE" \
-H "Content-Type: text/html" \
--data-binary "<h1 style='font-family:sans-serif'>Hola</h1>" \
-o tarjeta.png
Lo mismo desde Python, con las opciones en JSON:
import requests
r = requests.post(
"https://api.cofferdock.com/capture",
headers={"x-api-key": "TU_LLAVE"},
json={"html": "<h1>Hola</h1>", "width": 1200, "height": 630, "format": "png", "output": "binary"},
)
open("tarjeta.png", "wb").write(r.content)
Lo que conviene saber antes de elegirla: devuelve PNG, JPEG o WebP de hasta 3840 x 2160 píxeles (o la página entera de alto), las fuentes web y las imágenes de internet cargan bien y wait_ms espera hasta 5 segundos a que lleguen. No ejecuta JavaScript, así que un gráfico que dibuja un script necesita uno de los métodos de arriba, o un gráfico hecho por otra API. Cada imagen gasta 1 crédito; el plan gratis trae 50 al mes y puedes probarla sin cuenta antes.
En n8n, Make o Zapier es un solo paso HTTP: tienes las guías de n8n, Make y Zapier.
Problemas típicos (con cualquier método)
- La letra sale distinta. La fuente web aún no había cargado. Espera a que la red quede quieta (
networkidle) o añade una pequeña espera. - Faltan imágenes. En las librerías del navegador suele ser CORS; en un servidor, que la imagen aún no había terminado de cargar.
- La imagen sale borrosa. Genera a doble resolución:
pixelRatio: 2,scale: 2odeviceScaleFactor: 2. - Se corta parte del diseño. La ventana es más pequeña que el diseño: indica el ancho y el alto, o captura la página entera.
- Los emojis o las tildes salen como cuadrados. A los servidores, sobre todo a los contenedores Linux, les suelen faltar esas fuentes. Instálalas o carga una fuente web que las incluya.
- El HTML lo escriben tus usuarios. No lo abras en un navegador que pueda llegar a tu red interna: bloquea antes las direcciones privadas.
Preguntas frecuentes
¿Cuál es la forma más fácil de pasar HTML a imagen? Sin código, una API de HTML a imagen o su demo en línea. Con código dentro de una web, la librería html-to-image. En un servidor, Puppeteer o Playwright.
¿Se puede convertir HTML en imagen sin un navegador? No de forma fiable. Algo tiene que entender el CSS y dibujarlo. Las librerías que no usan navegador solo entienden una parte pequeña del CSS, y las API simplemente ponen el navegador por ti.
¿html-to-image y html2canvas son lo mismo? No. Las dos funcionan en el navegador del visitante, pero html-to-image copia el elemento dentro de un SVG y deja que lo dibuje el navegador, mientras que html2canvas lo vuelve a dibujar en un lienzo por su cuenta. html-to-image suele parecerse más al original.
¿PNG, JPG o WebP? PNG para texto, logos y bordes nítidos. JPG para fotos, cuando importa más el peso. WebP pesa menos que los dos, pero comprueba que donde vayas a usar la imagen lo acepten.
¿Cómo paso HTML a imagen en n8n? Con un nodo HTTP Request que manda el HTML a una API y devuelve el archivo. Paso a paso y con un flujo gratis para importar: HTML a imagen en n8n.
Guías relacionadas
- HTML a imagen en n8n, en Make y en Zapier
- Alternativa a htmlcsstoimage: cuándo te conviene Cofferdock y cuándo no
- Cómo hacer una captura de pantalla de una web entera
Referencia completa con todas las opciones: API de HTML a imagen. ¿Aún sin cuenta? Crea una gratis.