What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Short answer: wkhtmltopdf can put the current section name in a repeated header or footer with [section] (and [subsection]), and it can print global numbers with [page] and [topage]. It does not document a numeric “page 2 of this section” value, nor a JavaScript API that reports the final PDF page boundaries. If you need numbering that restarts at every section, split sections into separately controlled documents or paginate in the application that generates the HTML, then validate the resulting PDF with the exact wkhtmltopdf build used in production.
First decide which counter you actually need
Many “section counter” requests combine three different values. Choosing the right one prevents a fragile implementation.
| Requirement | Supported approach | What to expect |
|---|---|---|
| Display a section or subsection name | [section] or [subsection] in a header/footer, or the matching class in an HTML header/footer |
A text label supplied by wkhtmltopdf |
| Display the document page and total | [page] and [topage] |
Global printed-page values, such as “Page 4 of 18” |
| Display “page 2 of this section” and reset at each heading | No documented built-in placeholder | Requires explicit document boundaries or application-side pagination; a DOM scan is not authoritative |
The library settings reference lists pageOffset and pagesCount, but does not describe either setting as a reset-at-section mechanism. Treat them as controls for object/page counting, not as proof that arbitrary headings can restart a counter.
Show the current section in a repeated footer
Use a text substitution for the simplest case
For a label and ordinary page number, let wkhtmltopdf perform the substitution:
#1 Best Overall
wkhtmltopdf
--footer-left '[section]'
--footer-right 'Page [page] of [topage]'
input.html output.pdf
The documented substitutions include [page] (current printed page), [frompage] (first page in the current print operation), [topage] (last page), [section], [subsection], [title], [doctitle], [sitepage], and [sitepages]. Keep the square-bracket spelling exactly as shown.
Use an HTML header or footer when you need layout or styling
An HTML header/footer receives the substitution values in its own URL query string. The documented pattern parses that query string and fills elements whose class names match supported keys. Save this as footer.html:
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<style>
body { margin: 0; font: 9pt sans-serif; color: #555; }
.row { display: flex; justify-content: space-between; }
</style>
<script>
function subst() {
var vars = {};
var pairs = window.location.search.substring(1).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=', 2);
vars[pair[0]] = decodeURIComponent(pair[1] || '');
}
['page', 'topage', 'section', 'subsection'].forEach(function (key) {
var nodes = document.getElementsByClassName(key);
for (var j = 0; j < nodes.length; j++) {
nodes[j].textContent = vars[key] || '';
}
});
}
</script>
</head>
<body onload='subst()'>
<div class='row'>
<span class='section'></span>
<span>Page <span class='page'></span> of <span class='topage'></span></span>
</div>
</body>
</html>
Attach it with:
wkhtmltopdf --footer-html footer.html input.html output.pdf
You can add a subsection element in the same way. This script only inserts values that wkhtmltopdf has already supplied; it does not discover where the PDF’s physical pages begin or end.
Use JavaScript timing switches correctly
JavaScript is enabled by default in the documented command-line interface. Timing options matter when your source page or header/footer fills content asynchronously:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →--disable-javascriptturns JavaScript off. Do not use it when your header/footer depends onsubst()or when the source page builds content in JavaScript.--javascript-delay <msec>adds a wait after loading; the documented default is 200 milliseconds.--run-script <js>executes additional JavaScript after loading and may be specified repeatedly.--window-status <windowStatus>waits untilwindow.statusreaches the requested value.
A delay is only a time budget. It does not prove that every asynchronous request, font, image, or widget has finished. When you control the page, setting a deliberate status value after your own work completes is generally easier to reason about than guessing a delay, but the generated PDF still needs inspection.
Rank #2
Why a numeric counter cannot reliably reset at an arbitrary heading
wkhtmltopdf’s documented placeholders expose section names and global page values, not a “current section page” integer. The renderer lays the document out as one long WebKit page and then cuts that layout into PDF pages. The manual warns that this process can split lines and images; patched Qt’s page-break-inside support can reduce some problems but does not expose final page boundaries to page JavaScript.
Consequently, code that scans headings, measures element offsets, or increments a counter while the DOM loads is estimating pagination in the source layout. It cannot know with certainty how a font substitution, margin, paper size, image load, or line wrap will alter the final cuts. Such a counter may appear correct for one document and fail after a small content or build change.
Practical ways to restart numbering
Separate sections into independently rendered objects
If your publishing pipeline already treats each section as a separate wkhtmltopdf object or input document, keep that boundary explicit. Render each section with its own local numbering context, then combine the outputs with the PDF workflow you already use. Investigate the object-level pagesCount behavior and global pageOffset in the settings reference for your binding, but do not assume either setting automatically produces a reset footer inside one flowing HTML object.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsThis approach is strongest when section boundaries are editorial facts: a chapter, invoice, or report part can have its own HTML, assets, and validation fixture. It also makes it possible to restart a counter in the generating application rather than in browser JavaScript.
Paginate in the generating application
For a single source document that must show “section page X of Y,” calculate the section page map before generating HTML. Insert explicit page-break boundaries or render one object per section, and pass the resulting values to the template. Your application owns the definition of a section, while wkhtmltopdf remains responsible for rendering.
Do not calculate the map from character counts or a single hard-coded pixel height. Use the same fonts, paper dimensions, margins, zoom, and asset versions as production, and regard the result as a layout contract that must be regression-tested.
Use a custom JavaScript estimate only when you can tolerate drift
A script that finds headings and compares their vertical offsets can be useful for a controlled preview, but it is not an authoritative PDF counter. If you choose this route, label it as layout-dependent, test representative long and short sections, and reject the output when pagination differs from the expected map rather than silently publishing an incorrect footer.
Free tools Windows power users keep installed
One-click scans. No signup required.
Validate against the actual binary and layout
Build differences matter. The manual distinguishes features that depend on patched Qt, and operating-system packages can ship different wkhtmltopdf builds. Record the exact executable and version used by your deployment, then test with the same binary locally or in CI.
- Freeze paper size, orientation, margins, zoom, fonts, and image assets.
- Test a section that ends near a page boundary, one that spans many pages, and one containing large images or tables.
- Generate the PDF after every change to CSS, font files, content, or wkhtmltopdf build.
- Inspect both the visible labels and the actual page breaks; do not validate only the source DOM.
- Keep a rendered PDF fixture or page-count assertion so an upgrade cannot silently change numbering.
Troubleshooting
The section name is blank
- Confirm that the footer uses
--footer-htmlor a documented text substitution, not a normal source-page element. - Verify the class is exactly
sectionorsubsection. - Check that JavaScript has not been disabled and that the footer script runs on body load.
- Run the same command with the production binary; a build difference can change available features.
The page number never changes
- Ensure the element has class
pageand that the footer is actually attached to the command. - Do not hard-code a value in the HTML; wkhtmltopdf supplies the number through the footer URL query.
- Remember that
[page]is a global printed-page number, not a section-relative value.
The footer shows stale or empty asynchronous data
- Increase
--javascript-delayonly after measuring how long the page needs. - Prefer a controlled
window.statussignal when your own script knows that data and layout are ready. - Check that the source page and footer are not waiting on blocked requests or unavailable local assets.
A custom reset counter is wrong after a CSS change
That is the expected failure mode of DOM-based pagination. Recheck fonts, margins, paper settings, image dimensions, and page-break rules, then regenerate with the production binary. If the value must be correct, move the boundary and counter calculation into explicit objects or the generating application.
Performance and reliability considerations
Simple text substitutions add almost no rendering work. HTML footers and JavaScript add a separate document load and script execution, so keep the footer small, local, and free of unnecessary network requests. A long arbitrary delay slows every conversion; a status-based wait can reduce wasted time, but only when the page reliably sets the status.
Rank #4
For repeatable output, pin the wkhtmltopdf executable, Qt build, fonts, CSS, and input assets. Treat page counts as content-sensitive: changing a heading, image, table row, or font can move a boundary. Global [page]/[topage] numbering is therefore the dependable choice when a reset is not a hard requirement.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOr skip the browser setup
If what you actually need is a clean image of a webpage rather than a paginated PDF with section-relative numbering, ScreenshotNeo provides a single screenshot request. Its cookie/consent handling accepts the banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled.
For a direct request, see the ScreenshotNeo API documentation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same call in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And 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}`);
- Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers identify the page verdict and whether it was billed.
- An MCP server exposes
take_screenshot,get_page_info, andcapture_pdfto Claude, Cursor, and other MCP clients. - The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.
Create a free ScreenshotNeo account to try it without a card.
FAQ
Can a footer script read the source document’s headings?
The HTML header/footer is a separate document. Its documented input is the query-string data wkhtmltopdf supplies, so it should not be treated as a live view of the source page DOM.
Does pageOffset restart numbering at every heading?
The settings reference lists it as a global page offset. It does not document heading-level reset behavior.
Best Value
What should be included in a regression test?
Include boundary cases: a heading at the bottom of a page, a section spanning several pages, large images, tables, and the exact production fonts and wkhtmltopdf build.
Frequently Asked Questions
Can a footer script read the source document’s headings?
The HTML header/footer is a separate document. Its documented input is the query-string data wkhtmltopdf supplies, not a live view of the source page DOM.
Does pageOffset restart numbering at every heading?
The settings reference lists pageOffset as a global page offset; it does not document heading-level reset behavior.
What should be included in a regression test?
Test a heading at a page boundary, a multi-page section, large images, tables, and the exact production fonts and wkhtmltopdf build.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




