html-to-pdf

Pixel-perfect HTML to PDF conversion with automatic RTL and Hebrew language support. Renders using Chrome headless engine with full CSS3/HTML5 support, including Flexbox, Grid, custom fonts, and JavaScript execution Automatic right-to-left direction detection for Hebrew, Arabic, and other RTL languages; includes --rtl flag for forced RTL mode Configurable page formats (A4, Letter, Legal, A3, A5), orientation, margins, scale, and optional headers/footers Requires one-time npm setup; includes critical guidance on fitting single-page content and verification workflow to prevent overflow and cut-off text

INSTALLATION
npx skills add https://github.com/aviz85/claude-skills-library --skill html-to-pdf
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2a

This runs automatically on every PDF generation. No flags needed.

CRITICAL: Fit Content to Single Page

**Backgrounds on html or body cause extra pages!** Put backgrounds on a container element instead:

@page { size: A4; margin: 0; }

html, body {

  width: 210mm;

  height: 297mm;

  margin: 0;

  padding: 0;

  overflow: hidden;

  /* NO background here! */

}

.container {

  width: 100%;

  height: 100%;

  padding: 20mm;

  box-sizing: border-box;

  background: linear-gradient(...); /* Background goes HERE */

}

Common causes of extra pages:

  • Background on html/body - always put on .container instead
  • Content overflow - use overflow: hidden
  • Margins/padding pushing content out

Tips:

  • Use --scale=0.75 --margin=0 if content still overflows
  • For landscape: use --landscape

Setup (One-time)

Before first use, install dependencies:

cd ~/.claude/skills/html-to-pdf && npm install

Quick Usage

Convert local HTML file:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js input.html output.pdf

Convert URL to PDF:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js https://example.com page.pdf

Hebrew document with forced RTL:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js hebrew.html hebrew.pdf --rtl

Pipe HTML content:

echo "<h1>שלום עולם</h1>" | node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js - output.pdf --rtl

Options Reference

Option

Description

Default

--format=<format>

Page format: A4, Letter, Legal, A3, A5

A4

--landscape

Use landscape orientation

false

--margin=<value>

Set all margins (e.g., "20mm", "1in")

20mm

--margin-top=<value>

Top margin

20mm

--margin-right=<value>

Right margin

20mm

--margin-bottom=<value>

Bottom margin

20mm

--margin-left=<value>

Left margin

20mm

--scale=<number>

Scale factor 0.1-2.0

1

--background

Print background graphics

true

--no-background

Don't print backgrounds

-

--header=<html>

Header HTML template

-

--footer=<html>

Footer HTML template

-

--wait=<ms>

Wait time for fonts/JS

1000

--rtl

Force RTL direction

auto-detect

--expect-pages=<N>

Expected page count (warns if different)

1

--no-page-check

Disable page count warning

-

Automatic Overflow Detection

The script automatically checks page count after generating the PDF. By default, it expects 1 page and warns if the output has more:

⚠️  WARNING: PAGE OVERFLOW DETECTED!

   Expected: 1 page(s)

   Actual:   2 page(s)

   Fix: Reduce content, margins, or font sizes in HTML

   Use --no-page-check to disable this warning

Usage:

  • Default: expects 1 page, warns on overflow
  • --expect-pages=3: expects 3 pages (for multi-page documents)
  • --no-page-check: disables the check entirely

Note: Requires pdfinfo to be installed (part of poppler-utils). If not available, the check is silently skipped.

Examples

Basic conversion:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js report.html report.pdf

Letter format with custom margins:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js doc.html doc.pdf --format=Letter --margin=1in

Hebrew invoice:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js invoice-he.html invoice.pdf --rtl

Landscape presentation:

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js slides.html slides.pdf --landscape --format=A4

No margins (full bleed):

node ~/.claude/skills/html-to-pdf/scripts/html-to-pdf.js poster.html poster.pdf --margin=0

Hebrew/RTL Best Practices

For best Hebrew rendering in your HTML:

  • Set lang attribute: <html lang="he" dir="rtl">
  • Use UTF-8: <meta charset="UTF-8">
  • CSS direction: Add direction: rtl; text-align: right; to body
  • Fonts: Use web fonts that support Hebrew (Noto Sans Hebrew, Heebo, Assistant)

Example Hebrew HTML structure (single-page):

<!DOCTYPE html>

<html lang="he" dir="rtl">

<head>

  <meta charset="UTF-8">

  <link href="https://fonts.googleapis.com/css2?family=Heebo:wght@400;700&#x26;display=swap" rel="stylesheet">

  <style>

    @page { size: A4; margin: 0; }

    html, body {

      width: 210mm;

      height: 297mm;

      margin: 0;

      padding: 0;

      overflow: hidden;

    }

    .container {

      width: 100%;

      height: 100%;

      padding: 20mm;

      box-sizing: border-box;

      font-family: 'Heebo', sans-serif;

      direction: rtl;

      text-align: right;

      background: #f5f5f5; /* Background on container, NOT body */

    }

  </style>

</head>

<body>

  <div class="container">

    <h1>שלום עולם</h1>

    <p>זהו מסמך בעברית</p>

  </div>

</body>

</html>

CRITICAL: Always Use scale=1.0 for Multi-Page PDFs

**NEVER use --scale < 1.0 for multi-page documents.** It causes:

  • Content offset (not centered on page)
  • RTL text overflow/clipping in grid layouts
  • Unpredictable viewport width calculations

Instead: reduce CSS font sizes and spacing to fit content at scale=1.0.

.page {

  width: 210mm;         /* Matches A4 exactly at scale=1.0 */

  height: 297mm;        /* Matches A4 exactly at scale=1.0 */

  padding: 8mm 10mm 12mm;

  page-break-after: always;

  position: relative;

  background: #f7f8fa;

  overflow: hidden;

  box-sizing: border-box;

}

If content overflows at scale=1.0: reduce font sizes (10-11px base), padding, margins — NOT the scale. This keeps 1:1 mapping between CSS and PDF, eliminating all layout artifacts.

Color tip: Pure white (#fff) backgrounds wash out colored accents. Use #f7f8fa or #f8fafb for subtle contrast that makes colors pop.

Troubleshooting

Fonts not rendering correctly

  • Add --wait=2000 for more font loading time
  • Ensure fonts are loaded via @font-face or Google Fonts

Hebrew appearing left-to-right

  • Use --rtl flag to force RTL direction
  • Add dir="rtl" to your HTML element

Page breaks not working

Use CSS page-break properties:

.page-break { page-break-after: always; }

.no-break { page-break-inside: avoid; }

Backgrounds not showing

  • Ensure --background is set (default is true)
  • Use --no-background only if you want to exclude backgrounds

Auto-Fit Content (MANDATORY VERIFICATION)

CRITICAL - Claude MUST do this after EVERY PDF generation:

  • Read the PDF file using the Read tool to visually inspect it
  • Check for vertical overflow (empty pages, content spilling to next page)
  • Check for horizontal overflow (text cut off at sides)
  • If ANY issue found → FIX and regenerate (max 5 attempts)
  • Only deliver PDF to user after verification passes

This is NOT optional. Never deliver a PDF without visual verification.

Problems to Look For

Problem

Symptom

Fix

Vertical overflow

Empty space at page bottom, content on next page

Reduce --scale

Horizontal cut-off

Text cut at left/right edges

Reduce --margin AND fix HTML width

Both issues

Content cut AND extra pages

Fix HTML CSS first, then adjust scale

Fix Strategy (Max 5 Attempts)

Attempt 1: Default settings

node scripts/html-to-pdf.js input.html output.pdf

Attempt 2: If vertical overflow → reduce scale

node scripts/html-to-pdf.js input.html output.pdf --scale=0.9

Attempt 3: If horizontal cut-off → reduce margins

node scripts/html-to-pdf.js input.html output.pdf --scale=0.9 --margin=10mm

Attempt 4: If still issues → smaller scale + margins

node scripts/html-to-pdf.js input.html output.pdf --scale=0.8 --margin=5mm

Attempt 5: If still failing → FIX THE HTML CSS:

/* Add to HTML to prevent horizontal overflow */

.container {

  width: 100%;

  max-width: 100%;

  overflow-wrap: break-word;

  word-wrap: break-word;

  box-sizing: border-box;

}

STOP after 5 attempts - regenerate HTML with proper constraints.

HTML Width Fix (Required for Horizontal Fit)

If content is cut at sides, the HTML MUST have:

html, body {

  width: 210mm;  /* A4 width */

  margin: 0;

  padding: 0;

  overflow: hidden;

}

.container {

  width: 100%;

  max-width: 100%;

  padding: 15mm;

  box-sizing: border-box;

  overflow-wrap: break-word;

}

Verification Checklist

After EVERY PDF generation, verify:

  • All text visible (not cut at edges)
  • No unnecessary empty pages
  • Content fills pages properly
  • No large gaps between sections

If ANY check fails → adjust and regenerate (max 5 times).

Technical Notes

  • Uses Puppeteer with Chrome headless for rendering
  • Waits for networkidle0 to ensure all resources load
  • Automatically waits for document.fonts.ready
  • Supports @page CSS rules for print styling
  • Device scale factor set to 2 for crisp rendering
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card