Reportia

Actualizado 4 junio 2026 · 12 min de lectura

Crear PDF desde HTML y CSS con API REST (sin instalar nada)

Convertir HTML a PDF es una necesidad común: facturas, reportes, certificados, contratos. Pero las soluciones tradicionales requieren instalar software pesado en tu servidor.

En este tutorial te muestro cómo convertir cualquier HTML+CSS a PDF profesional con una sola llamada API. Sin wkhtmltopdf, sin Puppeteer, sin Docker.

Por qué no usar wkhtmltopdf o Puppeteer

HerramientaProblema
wkhtmltopdfProyecto abandonado (sin actualizaciones desde 2020). Vulnerabilidades de seguridad conocidas. Renderizado basado en WebKit antiguo: no soporta flexbox ni grid.
Puppeteer / PlaywrightRequiere instalar Chromium (+300MB). Lento (2-5 segundos por PDF). Consume mucha RAM. Difícil de escalar.
ReportLabNo acepta HTML. Debes posicionar cada elemento manualmente con coordenadas X/Y.
API externa (Reportia)Envías HTML → recibes PDF. Sin instalar nada. ~200ms por documento.

Paso 1: Escribe tu plantilla HTML

Puedes usar cualquier HTML válido con CSS moderno. Flexbox, grid, variables CSS, @media print — todo funciona.

<!DOCTYPE html>
<html>
<head>
  <style>
    body { font-family: system-ui; padding: 40px; color: #1a1a1a; }
    .header { display: flex; justify-content: space-between; border-bottom: 2px solid #059669; padding-bottom: 20px; }
    .logo { font-size: 24px; font-weight: 700; color: #059669; }
    table { width: 100%; border-collapse: collapse; margin-top: 30px; }
    th { background: #f0fdf4; text-align: left; padding: 10px; }
    td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
    .total { font-size: 20px; font-weight: 700; text-align: right; margin-top: 20px; }
  </style>
</head>
<body>
  <div class="header">
    <div class="logo">Mi Empresa</div>
    <div>Factura #001<br>Fecha: {{ fecha }}</div>
  </div>
  <table>
    <thead><tr><th>Concepto</th><th>Cantidad</th><th>Precio</th></tr></thead>
    <tbody>
      {% for item in items %}
      <tr><td>{{ item.desc }}</td><td>{{ item.qty }}</td><td>${{ item.price }}</td></tr>
      {% endfor %}
    </tbody>
  </table>
  <p class="total">Total: ${{ total }}</p>
</body>
</html>

Las variables entre {{ }} son Jinja2 — se reemplazan automáticamente con los datos que envíes.

Paso 2: Envía el HTML a la API

Con cURL

curl -X POST https://reportia.4l3.org/v1/render \
  -H "Content-Type: application/json" \
  -d '{
    "template_html": "<tu HTML aquí>",
    "data": {
      "fecha": "2026-06-04",
      "items": [
        {"desc": "Diseño web", "qty": 1, "price": 15000},
        {"desc": "Hosting anual", "qty": 1, "price": 2400}
      ],
      "total": 17400
    },
    "format": "pdf"
  }' \
  --output factura.pdf

Con Python

import requests

html = open("mi-plantilla.html").read()

r = requests.post("https://reportia.4l3.org/v1/render", json={
    "template_html": html,
    "data": {
        "fecha": "2026-06-04",
        "items": [
            {"desc": "Diseño web", "qty": 1, "price": 15000},
            {"desc": "Hosting anual", "qty": 1, "price": 2400},
        ],
        "total": 17400,
    },
    "format": "pdf",
})

with open("factura.pdf", "wb") as f:
    f.write(r.content)

print(f"PDF generado: {len(r.content):,} bytes")

Con JavaScript (Node.js)

const fs = require('fs');

const res = await fetch('https://reportia.4l3.org/v1/render', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    template_html: fs.readFileSync('mi-plantilla.html', 'utf8'),
    data: {
      fecha: '2026-06-04',
      items: [
        { desc: 'Diseño web', qty: 1, price: 15000 },
        { desc: 'Hosting anual', qty: 1, price: 2400 },
      ],
      total: 17400,
    },
    format: 'pdf',
  }),
});

fs.writeFileSync('factura.pdf', Buffer.from(await res.arrayBuffer()));
console.log('PDF generado');

Con PHP

$html = file_get_contents('mi-plantilla.html');

$ch = curl_init('https://reportia.4l3.org/v1/render');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'template_html' => $html,
        'data' => [
            'fecha' => '2026-06-04',
            'items' => [
                ['desc' => 'Diseño web', 'qty' => 1, 'price' => 15000],
            ],
            'total' => 15000,
        ],
        'format' => 'pdf',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);

$pdf = curl_exec($ch);
file_put_contents('factura.pdf', $pdf);
echo "PDF: " . strlen($pdf) . " bytes\n";

Prueba ahora mismo

50 PDFs gratis al mes. Sin tarjeta. Sin registro para la API básica.

Abrir el editor visual →  |  Ver documentación API →

Paso 3: Formatos de salida

Además de PDF, puedes recibir el documento en otros formatos:

Ventajas vs. soluciones self-hosted

Preguntas frecuentes

¿Puedo usar imágenes?

Sí. Usa URLs absolutas (<img src="https://...">) o imágenes en base64. Las imágenes relativas no se resuelven porque no hay servidor local.

¿Soporta páginas múltiples?

Sí. Usa page-break-before: always en CSS para forzar saltos de página. También puedes configurar el tamaño de página con @page { size: letter; margin: 2cm; }.

¿Funciona con tablas largas?

Sí. Las tablas se paginan automáticamente. Los headers se repiten en cada página si usas <thead>.

¿Cuánto cuesta?

Plan Free: 50 PDFs/mes con marca de agua. Pro: $9 USD/mes, 1,000 PDFs sin marca. Lifetime: $25 USD pago único. Ver planes →

¿Listo para probarlo?

Genera tu primer PDF en 30 segundos. Sin registro.

Crear mi primer PDF →

Artículos relacionados