• ExitCodeZer0
  • Posts
  • Convert HTML to PDF with Node.js: A Complete Guide to Using the FileSlap API

Convert HTML to PDF with Node.js: A Complete Guide to Using the FileSlap API

Transform your HTML content into professional PDFs using Node.js and our lightning-fast API

Why Convert HTML to PDF with Node.js?

Node.js developers often need to generate PDFs from HTML content for:

  • Invoice generation - Create professional invoices for e-commerce

  • Report creation - Convert data dashboards to printable formats

  • Document processing - Generate PDFs from user-submitted content

  • Email attachments - Send formatted documents via email services

  • Content archiving - Convert blog posts and articles to PDF

While there are local Node.js libraries like puppeteer or wkhtmltopdf, they come with installation headaches, dependency issues, and inconsistent rendering across different systems. That's where the FileSlap API comes in - a cloud-based solution that handles all the complexity for you.

Getting Started with FileSlap API

1. Get Your API Key

First, sign up at fileslap.com and grab your API key. It's free to start with 50 conversions per month.

2. Install Required Dependencies

npm install node-fetch

That's it! No complex PDF libraries or system dependencies to worry about.

Basic HTML to PDF Conversion

Here's the simplest way to convert HTML to PDF:

import fetch from "node-fetch";
import fs from "fs";

async function convertHtmlToPdf(htmlContent, apiKey) {
  const url = "https://api.fileslap.com/api/convert";
  
  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": apiKey
    },
    body: JSON.stringify({ html: htmlContent })
  });
  
  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }
  
  // Save the PDF
  const buffer = await response.arrayBuffer();
  fs.writeFileSync("output.pdf", Buffer.from(buffer));
  console.log("PDF created successfully!");
}

// Example usage
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
    <title>Sample Document</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        h1 { color: #333; }
    </style>
</head>
<body>
    <h1>Hello from Node.js!</h1>
    <p>This HTML was converted to PDF using the FileSlap API.</p>
</body>
</html>
`;

const apiKey = "your_api_key_here";
convertHtmlToPdf(htmlContent, apiKey);

Using Native Fetch (Node.js 18+)

If you're using Node.js 18 or later, you can use the built-in fetch:

import fs from "fs";

async function convertHtmlToPdf(htmlContent, apiKey) {
  const response = await fetch("https://api.fileslap.com/api/convert", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": apiKey
    },
    body: JSON.stringify({ html: htmlContent })
  });
  
  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }
  
  const buffer = await response.arrayBuffer();
  fs.writeFileSync("output.pdf", Buffer.from(buffer));
  console.log("PDF created successfully!");
}

Real-World Examples

1. Invoice Generator

import fetch from "node-fetch";
import fs from "fs";

async function generateInvoice(orderData, apiKey) {
  const html = `
    <!DOCTYPE html>
    <html>
    <head>
        <title>Invoice #${orderData.orderNumber}</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 40px; }
            .header { text-align: center; border-bottom: 2px solid #333; padding-bottom: 20px; }
            .invoice-details { margin: 30px 0; }
            .items-table { width: 100%; border-collapse: collapse; margin: 20px 0; }
            .items-table th, .items-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
            .total { font-weight: bold; font-size: 18px; text-align: right; }
        </style>
    </head>
    <body>
        <div class="header">
            <h1>INVOICE</h1>
            <p>Order #${orderData.orderNumber} | Date: ${orderData.orderDate}</p>
        </div>
        
        <div class="invoice-details">
            <h3>Bill To:</h3>
            <p>${orderData.customerName}<br>
            ${orderData.customerEmail}<br>
            ${orderData.customerAddress}</p>
        </div>
        
        <table class="items-table">
            <thead>
                <tr>
                    <th>Item</th>
                    <th>Quantity</th>
                    <th>Price</th>
                    <th>Total</th>
                </tr>
            </thead>
            <tbody>
                ${orderData.items.map(item => `
                    <tr>
                        <td>${item.name}</td>
                        <td>${item.quantity}</td>
                        <td>$${item.price}</td>
                        <td>$${item.quantity * item.price}</td>
                    </tr>
                `).join('')}
            </tbody>
        </table>
        
        <div class="total">
            <p>Total: $${orderData.total}</p>
        </div>
    </body>
    </html>
  `;
  
  const response = await fetch("https://api.fileslap.com/api/convert", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": apiKey
    },
    body: JSON.stringify({ html })
  });
  
  if (!response.ok) {
    throw new Error(`PDF generation failed: ${response.status}`);
  }
  
  const buffer = await response.arrayBuffer();
  const filename = `invoice-${orderData.orderNumber}.pdf`;
  fs.writeFileSync(filename, Buffer.from(buffer));
  
  return filename;
}

// Usage
const orderData = {
  orderNumber: "ORD-12345",
  orderDate: new Date().toLocaleDateString(),
  customerName: "John Doe",
  customerEmail: "[email protected]",
  customerAddress: "123 Main St, City, State 12345",
  items: [
    { name: "Web Development", quantity: 1, price: 1500 },
    { name: "Hosting Setup", quantity: 1, price: 200 }
  ],
  total: 1700
};

generateInvoice(orderData, "your_api_key");

2. Report Generator with Charts

async function generateReport(data, apiKey) {
  // Create a simple chart using HTML/CSS
  const chartHtml = data.map(item => {
    const percentage = (item.value / Math.max(...data.map(d => d.value))) * 100;
    return `
      <div style="margin: 10px 0;">
        <div style="display: flex; justify-content: space-between;">
          <span>${item.label}</span>
          <span>${item.value}</span>
        </div>
        <div style="background: #f0f0f0; height: 20px; border-radius: 10px;">
          <div style="background: #007bff; height: 100%; width: ${percentage}%; border-radius: 10px;"></div>
        </div>
      </div>
    `;
  }).join('');
  
  const html = `
    <!DOCTYPE html>
    <html>
    <head>
        <title>Monthly Report</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 40px; }
            .header { text-align: center; margin-bottom: 30px; }
            .chart { margin: 20px 0; }
        </style>
    </head>
    <body>
        <div class="header">
            <h1>Monthly Sales Report</h1>
            <p>Generated on ${new Date().toLocaleDateString()}</p>
        </div>
        
        <div class="chart">
            <h2>Sales Performance</h2>
            ${chartHtml}
        </div>
    </body>
    </html>
  `;
  
  const response = await fetch("https://api.fileslap.com/api/convert", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": apiKey
    },
    body: JSON.stringify({ html })
  });
  
  if (!response.ok) {
    throw new Error(`PDF generation failed: ${response.status}`);
  }
  
  const buffer = await response.arrayBuffer();
  fs.writeFileSync("report.pdf", Buffer.from(buffer));
  console.log("Report generated successfully!");
}

// Usage
const reportData = [
  { label: "Product A", value: 1500 },
  { label: "Product B", value: 2200 },
  { label: "Product C", value: 800 }
];

generateReport(reportData, "your_api_key");

Error Handling and Best Practices

Robust Error Handling

async function convertWithRetry(htmlContent, apiKey, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch("https://api.fileslap.com/api/convert", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-API-KEY": apiKey
        },
        body: JSON.stringify({ html: htmlContent })
      });
      
      if (response.ok) {
        return await response.arrayBuffer();
      }
      
      if (response.status === 429) {
        const waitTime = Math.pow(2, attempt) * 1000;
        console.log(`Rate limited. Waiting ${waitTime}ms...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }
      
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
      
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      console.log(`Attempt ${attempt} failed:`, error.message);
    }
  }
}

Validate HTML Content

function validateHtml(htmlContent) {
  // Basic HTML validation
  const requiredTags = ['<html>', '<head>', '<body>'];
  const htmlLower = htmlContent.toLowerCase();
  
  for (const tag of requiredTags) {
    if (!htmlLower.includes(tag)) {
      return false;
    }
  }
  
  return true;
}

async function safeConvert(htmlContent, apiKey) {
  if (!validateHtml(htmlContent)) {
    throw new Error("Invalid HTML content");
  }
  
  return await convertWithRetry(htmlContent, apiKey);
}

Express.js Integration

import express from "express";
import fetch from "node-fetch";

const app = express();
app.use(express.json());

app.post('/generate-pdf', async (req, res) => {
  try {
    const { html } = req.body;
    const apiKey = process.env.FILESLAP_API_KEY;
    
    const response = await fetch("https://api.fileslap.com/api/convert", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-KEY": apiKey
      },
      body: JSON.stringify({ html })
    });
    
    if (!response.ok) {
      const errorText = await response.text();
      return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
    }
    
    const pdfBuffer = await response.arrayBuffer();
    
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
    res.send(Buffer.from(pdfBuffer));
    
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Next.js API Route

// pages/api/generate-pdf.js
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }
  
  try {
    const { html } = req.body;
    const apiKey = process.env.FILESLAP_API_KEY;
    
    const response = await fetch("https://api.fileslap.com/api/convert", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-KEY": apiKey
      },
      body: JSON.stringify({ html })
    });
    
    if (!response.ok) {
      const errorText = await response.text();
      return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
    }
    
    const pdfBuffer = await response.arrayBuffer();
    
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
    res.send(Buffer.from(pdfBuffer));
    
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

Serverless Function (Vercel/Netlify)

// api/generate-pdf.js
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }
  
  try {
    const { html } = req.body;
    const apiKey = process.env.FILESLAP_API_KEY;
    
    const response = await fetch("https://api.fileslap.com/api/convert", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-KEY": apiKey
      },
      body: JSON.stringify({ html })
    });
    
    if (!response.ok) {
      const errorText = await response.text();
      return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
    }
    
    const pdfBuffer = await response.arrayBuffer();
    
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
    res.send(Buffer.from(pdfBuffer));
    
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

Performance Tips

1. Batch Processing

async function batchConvert(htmlTemplates, apiKey) {
  const promises = htmlTemplates.map(async (template, index) => {
    try {
      const response = await fetch("https://api.fileslap.com/api/convert", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-API-KEY": apiKey
        },
        body: JSON.stringify({ html: template })
      });
      
      if (!response.ok) {
        throw new Error(`Failed to convert template ${index}`);
      }
      
      return await response.arrayBuffer();
    } catch (error) {
      console.error(`Error converting template ${index}:`, error);
      return null;
    }
  });
  
  return await Promise.all(promises);
}

2. Caching Strategies

import crypto from "crypto";

const cache = new Map();

function getCacheKey(htmlContent) {
  return crypto.createHash('md5').update(htmlContent).digest('hex');
}

async function convertWithCache(htmlContent, apiKey) {
  const cacheKey = getCacheKey(htmlContent);
  
  if (cache.has(cacheKey)) {
    console.log('Using cached PDF');
    return cache.get(cacheKey);
  }
  
  const pdfBuffer = await convertWithRetry(htmlContent, apiKey);
  cache.set(cacheKey, pdfBuffer);
  
  return pdfBuffer;
}

3. Stream Processing

import { Readable } from "stream";

async function streamPdf(htmlContent, apiKey, res) {
  const response = await fetch("https://api.fileslap.com/api/convert", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": apiKey
    },
    body: JSON.stringify({ html: htmlContent })
  });
  
  if (!response.ok) {
    throw new Error(`PDF generation failed: ${response.status}`);
  }
  
  const pdfBuffer = await response.arrayBuffer();
  const stream = Readable.from(Buffer.from(pdfBuffer));
  
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
  
  stream.pipe(res);
}

Environment Variables

Store your API key securely using environment variables:

# .env
FILESLAP_API_KEY=your_api_key_here
import dotenv from "dotenv";
dotenv.config();

const apiKey = process.env.FILESLAP_API_KEY;

Error Codes and Handling

The FileSlap API returns standard HTTP status codes:

  • 200: PDF generated successfully

  • 400: Bad request - invalid HTML or missing fields

  • 401: Unauthorized - invalid or missing API key

  • 429: Rate limit exceeded or quota exceeded

  • 500: Internal server error

async function handleApiResponse(response) {
  switch (response.status) {
    case 200:
      return await response.arrayBuffer();
    case 400:
      const error400 = await response.text();
      throw new Error(`Invalid request: ${error400}`);
    case 401:
      throw new Error('Invalid API key. Please check your credentials.');
    case 429:
      throw new Error('Rate limit exceeded. Please try again later.');
    case 500:
      throw new Error('Service temporarily unavailable. Please try again.');
    default:
      throw new Error(`Unexpected error: ${response.status}`);
  }
}

Get Started Today

Ready to simplify your PDF generation?

  1. Sign up at fileslap.com

  2. Get your API key from the dashboard

  3. Install node-fetch (or use native fetch in Node.js 18+)

  4. Start converting HTML to PDF with just a few lines of code

No more wrestling with local PDF libraries or dealing with system dependencies. The FileSlap API handles all the complexity while you focus on building great applications.

Need Help?

  • Documentation: fileslap.com/docs

  • API Reference: Complete API documentation with examples

  • Support: Reach out to our team for custom integration help

Transform your HTML content into professional PDFs with the power of Node.js and FileSlap's cloud-based API.

Tags: #NodeJS #PDF #API #HTML #JavaScript #WebDevelopment #FileSlap #Backend