DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

html-pdf npm is Abandoned: Here's the Modern Alternative

html-pdf npm is Abandoned: Here's the Modern Alternative

If you're using the html-pdf npm package, you probably already know it's broken. It hasn't been maintained since 2019. It fails on Node 18+. It's built on PhantomJS, which is also abandoned. And if you're trying to install it now, you're hitting permission errors or segmentation faults.

You're not alone. Thousands of developers are stuck on html-pdf because migrating seemed hard. It isn't.

Why html-pdf is Broken

html-pdf relies on PhantomJS — a headless browser that was abandoned in 2018. PhantomJS doesn't work on modern Node versions, doesn't support modern JavaScript, and has zero security updates.

The html-pdf package itself hasn't been updated in years. Issues pile up on GitHub. PRs go unreviewed. It's unmaintained.

If you're on Node 18+, you're probably seeing:

npm ERR! ERR! code EBUILD
npm ERR! node-gyp rebuild
npm ERR! gyp ERR! configure error
Enter fullscreen mode Exit fullscreen mode

This is html-pdf trying to compile native bindings that don't work on modern systems.

Before: html-pdf Setup

Here's the current approach:

npm install html-pdf
Enter fullscreen mode Exit fullscreen mode

Then in your code:

const pdf = require('html-pdf');

const htmlContent = `
  <h1>Invoice #12345</h1>
  <p>Amount: $100</p>
`;

const options = {
  width: '8.5in',
  height: '11in',
  format: 'Letter',
};

pdf.create(htmlContent, options).toFile('invoice.pdf', (err, res) => {
  if (err) {
    console.log('PDF generation failed:', err);
    return;
  }
  console.log('PDF created:', res.filename);
});
Enter fullscreen mode Exit fullscreen mode

Problems:

  • ❌ Async callback hell (no Promises)
  • ❌ Crashes randomly on complex HTML/CSS
  • ❌ No support for CSS Grid, Flexbox, modern features
  • ❌ Slow (5-10 seconds per PDF on average)
  • ❌ Breaks on Node 18+
  • ❌ No built-in error recovery

After: PageBolt PDF API

Modern approach using PageBolt:

npm uninstall html-pdf
npm install node-fetch
Enter fullscreen mode Exit fullscreen mode

Then in your code:

const fetch = require('node-fetch');

const htmlContent = `
  <h1>Invoice #12345</h1>
  <p>Amount: $100</p>
`;

const response = await fetch('https://pagebolt.dev/api/v1/pdf', {
  method: 'POST',
  headers: {
    'x-api-key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    html: htmlContent,
    format: 'A4',
    margin: '0.5in',
  }),
});

if (!response.ok) {
  throw new Error(`PDF generation failed: ${response.status}`);
}

const buffer = await response.arrayBuffer();
fs.writeFileSync('invoice.pdf', Buffer.from(buffer));
console.log('PDF created successfully');
Enter fullscreen mode Exit fullscreen mode

Better:

  • ✅ Async/await (modern JavaScript)
  • ✅ Handles CSS Grid, Flexbox, modern CSS
  • ✅ Fast (under 1 second)
  • ✅ Works on all Node versions
  • ✅ Built-in error handling
  • ✅ No system dependencies

Migration in 3 Steps

Step 1: Uninstall html-pdf

npm uninstall html-pdf
Enter fullscreen mode Exit fullscreen mode

This removes PhantomJS, native bindings, and all the broken dependencies.

Step 2: Install fetch (if needed)

npm install node-fetch
Enter fullscreen mode Exit fullscreen mode

If you're on Node 18+, you have fetch built-in. For older Node, install node-fetch.

Step 3: Replace the code

Old (html-pdf callback):

pdf.create(html, options).toFile('output.pdf', (err, res) => {
  if (err) console.error(err);
  else console.log('Done:', res.filename);
});
Enter fullscreen mode Exit fullscreen mode

New (PageBolt promise):

const response = await fetch('https://pagebolt.dev/api/v1/pdf', {
  method: 'POST',
  headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ html, format: 'A4' }),
});
const buffer = await response.arrayBuffer();
fs.writeFileSync('output.pdf', Buffer.from(buffer));
Enter fullscreen mode Exit fullscreen mode

Real-World Example: Invoice Generation

Before (html-pdf, broken):

const pdf = require('html-pdf');
const handlebars = require('handlebars');

function generateInvoice(invoiceData) {
  const template = handlebars.compile(invoiceTemplate);
  const html = template(invoiceData);

  return new Promise((resolve, reject) => {
    pdf.create(html).toFile(`invoice-${invoiceData.id}.pdf`, (err, res) => {
      if (err) reject(err);
      else resolve(res.filename);
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

After (PageBolt, modern):

const fetch = require('node-fetch');
const handlebars = require('handlebars');

async function generateInvoice(invoiceData) {
  const template = handlebars.compile(invoiceTemplate);
  const html = template(invoiceData);

  const response = await fetch('https://pagebolt.dev/api/v1/pdf', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.PAGEBOLT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ html, format: 'A4', margin: '0.5in' }),
  });

  if (!response.ok) throw new Error(`PDF failed: ${response.status}`);

  const buffer = await response.arrayBuffer();
  const filename = `invoice-${invoiceData.id}.pdf`;
  fs.writeFileSync(filename, Buffer.from(buffer));
  return filename;
}
Enter fullscreen mode Exit fullscreen mode

Cleaner. Faster. Works.

Performance Comparison

Metric html-pdf PageBolt
PDF Generation 5-10 seconds 0.5-1 second
Node 18+ Support ❌ Broken ✅ Yes
CSS Support Basic Full (Grid, Flexbox, modern)
Memory Usage 150MB+ < 50MB
Error Handling Poor Detailed status codes
Maintenance 🪦 Dead ✅ Active

Pricing

Plan Requests/Month Cost Best For
Free 100 $0 Testing & small projects
Starter 5,000 $29 500 invoices/month
Growth 25,000 $79 2,000+ invoices/month
Scale 100,000 $199 Enterprise billing systems

Migration Checklist

  • [ ] Uninstall html-pdf and PhantomJS
  • [ ] Install node-fetch (if needed)
  • [ ] Get API key from PageBolt dashboard
  • [ ] Update code to use fetch + /api/v1/pdf
  • [ ] Test with existing HTML templates
  • [ ] Deploy and monitor
  • [ ] Remove old npm scripts that reference html-pdf

Summary

  • html-pdf is unmaintained and broken on Node 18+
  • ❌ PhantomJS is dead and insecure
  • ✅ PageBolt replaces it with a modern, fast API
  • ✅ Migration takes 10 minutes
  • ✅ Zero system dependencies
  • ✅ Works with existing HTML/CSS

If you're still using html-pdf, migrate today. Your invoices will generate 10x faster, your code will be cleaner, and you'll never hit another Node compatibility error.

Get started free100 requests/month, no credit card required →

Top comments (0)