ScreenshotNeo

BlogHTML to image & PDF

How to Fix Text and Fonts Cut Off at Page Ends in wkhtmltopdf 0.12.6

Diagnose and fix page-end clipping in wkhtmltopdf 0.12.6 by checking pagination, margins, shrinking, fonts and renderer limits.

By the ScreenshotNeo team1 October 20267 min read

Short answer: wkhtmltopdf 0.12.6 has no universal switch that prevents text or fonts being cut off at a page end. Identify the defect first (a line split between pages, footer overlap, physical edge clipping, or unexpected whitespace), then test page geometry, header/footer spacing, smart shrinking, and fonts in the runtime that actually creates the PDF. CSS break hints can reduce some splits, but WebKit pagination can still divide lines and images. If a minimal case remains wrong after controlled tests, compare a newer renderer.

wkhtmltopdf 0.12.6 is the stable series released June 11, 2020. Its WebKit engine lays out a long document and cuts it into pages, so pagination is inherently imperfect. Output also depends on installed fonts and the host’s fontconfig/freetype setup (downloads and runtime notes; CLI manual).

1. Classify the page-end defect

What you see Likely area to inspect
A line or row continues on the next page WebKit pagination, block size, page-break-inside
Bottom text is hidden under a footer Footer height/spacing and bottom margin
Glyphs are cut exactly at the physical edge Paper size, dimensions, margins, zoom, overflow
Only wrapping or font metrics differ Installed font, fontconfig, freetype, fallback fonts
A large blank strip appears Smart shrinking, dimensions, margins, or forced breaks

Save the exact command, wkhtmltopdf --version output (including “patched Qt”), operating-system/container image, and a minimal HTML file that still reproduces the problem. This is the information requested by the project’s support guidance.

2. Build a minimal reproducible case

<!doctype html>
<meta charset='utf-8'>
<style>
  @page { size: A4; margin: 18mm 16mm 24mm; }
  html, body { margin: 0; padding: 0; }
  body { font-family: Arial, sans-serif; font-size: 11pt; line-height: 1.35; }
  h1 { margin: 0 0 8mm; }
  p { margin: 0 0 4mm; }
  .keep { page-break-inside: avoid; }
</style>
<h1>Page-end reproduction</h1>
<div class='keep'>
  <p>Replace this paragraph with the smallest block that clips or splits.</p>
</div>
wkhtmltopdf --version
wkhtmltopdf --log-level info repro.html repro.pdf

Render with headers and footers disabled first. Add real CSS and content back one change at a time. A minimal file tells you whether the fault is renderer geometry or application markup.

A footer can occupy more vertical space than expected. Header spacing is the gap between the header and document content; footer spacing is the gap above the footer. Reserve that space in the corresponding page margin. The settings reference documents these controls.

wkhtmltopdf \
  --page-size A4 \
  --margin-top 18mm \
  --margin-bottom 24mm \
  --header-spacing 4 \
  --footer-spacing 4 \
  --header-html header.html \
  --footer-html footer.html \
  input.html output.pdf

As a diagnostic, remove --header-html and --footer-html. If clipping disappears, measure the rendered header/footer and increase the matching margin. Zero margins do not provide usable footer space or remove the physical page boundary.

4. Check paper size, dimensions, zoom and overflow

Use one page model at a time. Prefer a named paper size such as A4 or Letter. If you use custom dimensions, verify units and orientation. Viewport width affects CSS layout; it does not enlarge the physical PDF page.

wkhtmltopdf \
  --page-size A4 \
  --orientation Portrait \
  --viewport-size 1280x900 \
  --zoom 1 \
  --margin-left 16mm --margin-right 16mm \
  --margin-top 18mm --margin-bottom 24mm \
  input.html output.pdf

Inspect wide elements for fixed widths, negative margins, transforms, and overflow:hidden. For a suspected physical crop, temporarily remove those rules and render a border around the page content.

5. Test smart shrinking as a controlled variable

Smart shrinking is enabled by default. It changes scale to fit content and can alter both font size and whitespace. Compare enabled and disabled runs while keeping every other option identical; disabling it is a diagnostic, not a guaranteed repair.

wkhtmltopdf input.html shrinking-on.pdf
wkhtmltopdf --disable-smart-shrinking input.html shrinking-off.pdf

Compare font scale, page count, bottom clearance and right-edge clipping across the whole document. Keep the setting that produces acceptable, repeatable geometry for your target documents.

6. Handle split lines, tables and blocks

The WebKit engine can split lines and images when it cuts the long layout into pages. On patched-Qt builds, break hints may help somewhat:

.keep-together {
  page-break-inside: avoid;
  break-inside: avoid;
}
table, tr, img, pre, blockquote { page-break-inside: avoid; }
.page-break { page-break-before: always; }

Apply this selectively. A large block that cannot fit in the remaining space will move to the next page, increasing whitespace; an oversized block can still be split. For tables, repeat headers with <thead>, avoid enormous cells, and test rows containing images or long unbroken strings.

7. Verify fonts inside the production runtime

Font substitution changes glyph metrics and line wrapping. Check the container or host that runs wkhtmltopdf, not only your workstation. The official downloads page identifies installed fonts plus fontconfig and freetype as runtime dependencies.

fc-match Arial
fc-list | head
ldconfig -p | grep -E 'fontconfig|freetype'
fc-cache -f -v

Use a known installed face for a comparison render. If the intended webfont is required, install it in the image, refresh the font cache, and make sure the CSS actually loads it before capture. A missing font is a plausible cause of changed wrapping, not proof that every clipping report is font-related.

8. A repeatable diagnostic matrix

  1. Record version, patched-Qt status, OS/container, command and minimal input.
  2. Render without headers/footers.
  3. Set explicit paper size, margins, viewport and zoom.
  4. Compare smart shrinking on and off.
  5. Test a known installed font and inspect fontconfig.
  6. Add selective break hints to split tables and blocks.
  7. Restore production CSS one change at a time and compare page count and bottom clearance.

9. Troubleshooting common errors

Symptom/error Cause to test Fix
Unknown long argument Option unavailable in your build or misspelled Check wkhtmltopdf --extended-help; use documented flags for that build.
Footer overlaps body Footer plus spacing exceeds bottom margin Increase --margin-bottom, reduce footer spacing/height, or remove the footer to confirm.
Text split across pages WebKit pagination Shorten the block, use selective page-break-inside: avoid, or insert a deliberate break.
Text clipped at edge Content exceeds paper box or overflow hides it Check paper size, margins, zoom, fixed widths, transforms and overflow.
Unexpected blank area Smart shrinking or forced keep-together moved a block Compare shrinking modes and remove the hint from oversized blocks.
Different wraps in Docker Font fallback or missing fontconfig/freetype Install the same fonts in the image, refresh cache, and retest with fc-match.
JavaScript content missing Page not ready when rendered Use a deterministic wait or a renderer suited to dynamic pages; verify with a minimal script case.

10. When to change renderers

If controlled geometry, font and break tests still fail, compare representative documents with a maintained renderer. The project status page names WeasyPrint or Prince for controlled HTML reports and Puppeteer for dynamic JavaScript pages. Evaluate CSS/JavaScript compatibility, pagination, deployment burden and licensing; the cited sources provide no neutral benchmark or drop-in guarantee.

11. Performance, reliability and cost considerations

  • Keep a small regression fixture and render it in CI on the same OS/container image as production.
  • Pin the wkhtmltopdf build and fonts; upgrades can change line metrics and page breaks.
  • Use explicit timeouts in the calling process and capture stderr logs.
  • Cache stable assets and avoid unnecessary remote fonts; network timing can change layout.
  • Measure page count, file size and render duration on representative documents. No source establishes a universal speed or success rate.

12. Or skip the browser setup

If your goal is a clean screenshot or PDF of a web page rather than maintaining a wkhtmltopdf runtime, ScreenshotNeo provides a single GET request. It can accept cookie/consent banners, remove more than 60 known consent platforms plus newsletter popups and chat widgets, and each step can be disabled. Only clean shots are billed: bot checks/CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, with the result described by X-Page-Verdict and X-Billed headers. It also offers an MCP server for AI agents and PDF options.

See the ScreenshotNeo API docs for all options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Free usage is 1,000 shots per month with no card; paid plans start at $5 for 3,000. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. Create a free ScreenshotNeo account.

FAQ

Does --disable-smart-shrinking fix clipping?

No. It is a useful comparison, but it changes scale and can create new whitespace or clipping.

Should I set every margin to zero?

No. Headers and footers need reserved space, and zero margins do not remove the physical page boundary.

Is a missing font always the cause?

No. It can change metrics and wrapping; verify it in the actual runtime before drawing that conclusion.

Can CSS guarantee that no line splits?

No. Break hints may help on patched builds, but WebKit pagination can still split content.

What should I include in a bug report?

Version and patched-Qt status, OS/container, exact command, minimal HTML/CSS, and the resulting PDF or reproducible symptoms.