Actualizado 5 junio 2026 · 13 min de lectura
Generar PDF con Node.js y JavaScript (API REST sin Puppeteer)
Generar PDFs en Node.js suele significar una de dos cosas: instalar Puppeteer (y con él, un Chromium de 300MB+) o pelear con librerías como PDFKit que te obligan a posicionar cada elemento manualmente. Hay una tercera opción: una API REST donde envías JSON y recibes el PDF.
El problema con Puppeteer y alternativas
| Solución | Peso | Velocidad | Dificultad | Docker-friendly |
|---|---|---|---|---|
| Puppeteer | ~300MB (Chromium) | 1-5s | Media | Complejo (Chrome deps) |
| PDFKit | ~2MB | 50-200ms | Alta (layout manual) | Sí |
| jsPDF | ~500KB | 100-500ms | Alta (coordenadas) | Sí |
| wkhtmltopdf | ~50MB | 500ms-2s | Media | Complejo (Qt deps) |
| API REST | 0MB | 100-300ms | Baja (solo fetch) | Sí (sin deps) |
Ejemplo básico: generar un PDF con fetch()
Node.js 18+ incluye fetch() nativo. No necesitas instalar nada:
// generar-pdf.mjs
const response = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer TU_API_KEY"
},
body: JSON.stringify({
template: "factura-servicios",
format: "pdf",
data: {
folio: "F-2026-0042",
fecha: "5 de junio de 2026",
empresa: {
nombre: "Mi Startup SAS",
rfc: "MST210101ABC",
direccion: "Av. Reforma 123, CDMX"
},
cliente: {
nombre: "Acme Corp",
email: "[email protected]"
},
items: [
{ descripcion: "Licencia SaaS mensual", cantidad: 1, precio: "299.00", total: "299.00" },
{ descripcion: "Soporte premium", cantidad: 1, precio: "99.00", total: "99.00" }
],
gran_total: "398.00"
}
})
});
const buffer = Buffer.from(await response.arrayBuffer());
const fs = await import("fs");
fs.writeFileSync("factura-F-2026-0042.pdf", buffer);
console.log("PDF generado: factura-F-2026-0042.pdf");
Eso es todo. 30 líneas, cero dependencias, cero Chrome.
Integrar con Express.js (endpoint que sirve PDFs)
Caso común: tu app Express necesita un endpoint GET /facturas/:id/pdf que genera y sirve el PDF al usuario:
import express from "express";
const app = express();
app.get("/facturas/:id/pdf", async (req, res) => {
// 1. Obtener datos de tu base de datos
const factura = await db.facturas.findById(req.params.id);
if (!factura) return res.status(404).json({ error: "Factura no encontrada" });
// 2. Generar PDF via API
const pdfResponse = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.REPORTIA_API_KEY}`
},
body: JSON.stringify({
template: "factura-servicios",
format: "pdf",
data: factura
})
});
if (!pdfResponse.ok) {
return res.status(500).json({ error: "Error generando PDF" });
}
// 3. Servir al usuario
const buffer = Buffer.from(await pdfResponse.arrayBuffer());
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", `inline; filename="factura-${factura.folio}.pdf"`);
res.send(buffer);
});
app.listen(3000, () => console.log("Server en http://localhost:3000"));
Generar múltiples PDFs en paralelo
Para facturación masiva (fin de mes, lotes de 100+ facturas):
async function generarPDF(factura) {
const res = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.REPORTIA_API_KEY}`
},
body: JSON.stringify({
template: "factura-servicios",
format: "pdf",
data: factura
})
});
return Buffer.from(await res.arrayBuffer());
}
// Generar 50 facturas en paralelo (lotes de 10)
const facturas = await db.facturas.findPendientes();
const BATCH_SIZE = 10;
for (let i = 0; i < facturas.length; i += BATCH_SIZE) {
const batch = facturas.slice(i, i + BATCH_SIZE);
const pdfs = await Promise.all(batch.map(generarPDF));
// Guardar cada PDF
pdfs.forEach((buffer, j) => {
const folio = batch[j].folio;
fs.writeFileSync(`./output/${folio}.pdf`, buffer);
});
console.log(`Lote ${Math.floor(i/BATCH_SIZE) + 1}: ${batch.length} PDFs generados`);
}
console.log(`Total: ${facturas.length} facturas generadas`);
Generar Excel (.xlsx) con el mismo código
Cambia format: "pdf" por format: "xlsx" y obtén un Excel:
const response = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer TU_API_KEY"
},
body: JSON.stringify({
template: "reporte-ventas",
format: "xlsx", // <-- solo cambia esto
data: {
titulo: "Ventas Junio 2026",
filas: salesData
}
})
});
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("ventas-junio.xlsx", buffer);
Integrar con Next.js (API Route)
// pages/api/factura/[id].js (Next.js)
export default async function handler(req, res) {
const { id } = req.query;
const factura = await prisma.factura.findUnique({ where: { id } });
const pdfRes = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.REPORTIA_API_KEY}`
},
body: JSON.stringify({
template: "factura-servicios",
format: "pdf",
data: factura
})
});
const buffer = Buffer.from(await pdfRes.arrayBuffer());
res.setHeader("Content-Type", "application/pdf");
res.send(buffer);
}
Con TypeScript (tipado completo)
interface FacturaData {
folio: string;
fecha: string;
empresa: { nombre: string; rfc: string; direccion: string };
cliente: { nombre: string; email: string };
items: Array<{
descripcion: string;
cantidad: number;
precio: string;
total: string;
}>;
gran_total: string;
}
interface RenderRequest {
template: string;
format: "pdf" | "xlsx";
data: FacturaData;
}
async function generarFacturaPDF(data: FacturaData): Promise<Buffer> {
const body: RenderRequest = {
template: "factura-servicios",
format: "pdf",
data
};
const res = await fetch("https://reportia.4l3.org/v1/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.REPORTIA_API_KEY!}`
},
body: JSON.stringify(body)
});
if (!res.ok) throw new Error(`API error: ${res.status}`);
return Buffer.from(await res.arrayBuffer());
}
Genera tu primer PDF con Node.js gratis
50 documentos/mes en el plan gratuito. Funciona con fetch(), sin Puppeteer.
Empezar gratis →Preguntas frecuentes
¿Necesito instalar Puppeteer o Chrome para generar PDFs?
No. La API genera el PDF en el servidor. Tu aplicación Node.js solo necesita fetch() para enviar JSON y recibir el binario del PDF. Sin Chrome, sin Puppeteer, sin dependencias pesadas.
¿Puedo generar PDFs desde un frontend (React, Vue, Angular)?
Sí. Puedes llamar a la API desde el frontend con fetch(). Sin embargo, para proteger tu API key, es recomendable hacer la llamada desde tu backend (Express, Next.js API routes, etc.) y servir el PDF al usuario.
¿Cuánto tarda en generar un PDF?
Un documento típico (factura, reporte de 1-5 páginas) se genera en 100-300ms. Documentos más largos (50+ páginas) pueden tardar 1-3 segundos.
¿Funciona con Deno o Bun?
Sí. Cualquier runtime JavaScript con soporte para fetch() funciona. Deno y Bun lo soportan nativamente, al igual que Node.js 18+.