The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Most wkhtmltopdf link failures come from confusing three separate problems: PDF annotations may be disabled, an internal fragment may not have a matching destination in the rendered document, or JavaScript may create the link after wkhtmltopdf has already captured the page. Header and footer links can also behave differently from links in the main HTML. Identify the link type and origin first, then inspect the generated PDF for an annotation before changing options.
First, identify what “not working” means
There are two fundamentally different PDF link types:
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
The Basic Guide to How to Read Music | $13.44 | Buy on Amazon |
| 2 |
|
The Flute Book: A Complete Guide for Students and Performers | $9.95 | Buy on Amazon |
| 3 |
|
Guide to Teachable Features in Popular Music | $20.00 | Buy on Amazon |
| 4 |
|
The Groove Schoolbook: The Complete Guide for the Working Drummer! | $17.99 | Buy on Amazon |
- External links: an anchor such as
<a href="https://example.com">Example</a>should open a remote URL. - Internal links: an anchor such as
<a href="#pricing">Pricing</a>should move to an element withid="pricing"(or a compatible named anchor) in the same PDF.
A viewer can also make a valid annotation appear broken. Test the PDF in a second viewer and determine whether the link annotation is missing entirely or whether it exists but points to the wrong destination. That distinction tells you whether to inspect wkhtmltopdf settings, source HTML, rendering timing, or the viewer.
Check the executable and link settings
The official wkhtmltopdf usage reference documents external and internal links as separate controls. In the documented build, both are enabled by default, but packaged binaries and historical patched or unpatched Qt builds can differ. Treat the defaults as a starting point, not proof of your deployed behavior.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
Inspect the exact binary used by your application
- Run
wkhtmltopdf --versionand record the complete output, including any patched-Qt wording. - Run
wkhtmltopdf --extended-help(orwkhtmltopdf --help) and confirm that--enable-external-links,--disable-external-links,--enable-internal-links, and--disable-internal-linksare available. - Reproduce the issue with a small local HTML file and the same executable, user account, and container or server image used in production.
For a command-line conversion, explicitly enable the kinds of links you need:
wkhtmltopdf --enable-external-links --enable-internal-links input.html output.pdf
If the options are unavailable, your build may not include the expected feature set. Upgrade or replace that specific build only after confirming your application’s compatibility requirements.
Library users need the corresponding settings
Bindings expose the same concepts under library-specific names. The documented settings are commonly called useExternalLinks and useLocalLinks. Set them on the page or conversion object in the binding you actually use, then verify the generated PDF rather than assuming the binding’s default matches the CLI.
Repair internal fragment links
An internal link works only when the destination survives rendering into the PDF. The source should contain a matching target:
Free tools Windows power users keep installed
One-click scans. No signup required.
<a href="#installation">Jump to installation</a>
<h2 id="installation">Installation</h2>
Check the target in the rendered page
- The
hreffragment and targetidmust match exactly, including case. - Do not rely on an element that is removed, replaced, or hidden before capture.
- If your framework emits a named anchor instead of an
id, inspect the final HTML that wkhtmltopdf receives. - Use a unique destination. Duplicate IDs make the result ambiguous.
Open the source URL in the same environment and use the browser’s DOM inspector to confirm that the destination exists after scripts and client-side routing have finished. A link that works interactively in a modern browser may fail if the older WebKit engine used by your wkhtmltopdf build does not execute the same code.
Wait for JavaScript-generated links and targets
wkhtmltopdf can execute JavaScript, but conversion timing matters. If a script inserts the anchor or destination after the initial page load, capture can occur too early.
Use a completion condition when possible
If the page can set window.status after it has finished building navigation, wait for that value:
wkhtmltopdf --enable-javascript
--window-status links-ready
page.html output.pdf
Your page must set the status itself, for example:
<script>
// Build the navigation and destination elements first.
window.status = 'links-ready';
</script>
Use a delay only when you cannot signal readiness
wkhtmltopdf --enable-javascript --javascript-delay 1500 page.html output.pdf
A fixed delay is a guess: too short leaves destinations out, while too long increases conversion time. Prefer a deterministic status or selector-based readiness mechanism in your surrounding automation when available, and keep the test page representative of production content.
Test header, footer, and table-of-contents links separately
Links in the main document are not necessarily processed through the same path as header and footer HTML. A historical report describes footer links aimed at anchors in the body being emitted as external links. That report is an edge-case lead, not evidence that every current build has the defect.
When the problem is limited to a header, footer, or table of contents:
- Create a minimal document with one body link and one header or footer link pointing to the same destination.
- Generate the PDF with the exact production version and build.
- Inspect each annotation’s action and destination in a PDF inspection tool or a viewer that exposes link properties.
- Record the version, operating system, patched-Qt status, command, and whether the destination is external or internal when filing or investigating the issue.
A practical workaround for a failing footer-to-body reference is to put the navigation inside the main HTML and style it to resemble a footer, but verify that the workaround does not alter pagination requirements.
Do not confuse link annotations with network requests
--enable-external-links and --enable-internal-links control whether PDF link annotations are written. They do not act as a network firewall. A report against version 0.12.5.0 found that disabling both link types removed annotations but did not stop an external image request made while the page loaded.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated 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 matchTherefore:
- Use link switches to control PDF navigation.
- Use network controls, a proxy, request filtering, or operating-system isolation to control outbound traffic.
- Do not assume that a PDF with no clickable links made no network requests during rendering.
Security: link flags are not a sandbox
wkhtmltopdf’s security guidance does not recommend rendering HTML you do not trust. The project discusses AppArmor confinement and warns that --disable-local-file-access alone may not prevent filesystem exposure if an attacker exploits a vulnerability in a prebuilt binary.
For untrusted input, isolate the conversion process with the operating-system and network boundaries appropriate to your environment: a restricted user, a disposable container or VM, limited filesystem mounts, egress controls, resource limits, and monitoring. Local-file access settings and PDF-link settings address different behaviors and should not be treated as interchangeable protections.
A repeatable troubleshooting workflow
- Classify the link: external URL or internal fragment.
- Classify its origin: main HTML, header, footer, or table of contents.
- Check the annotation: determine whether the PDF contains a clickable object at all.
- Check options: inspect the deployed binary’s help output and explicitly enable the required link types.
- Check the final DOM: verify the
hrefand matching destination exist after scripts run. - Check timing: use
--window-statusor adjust--javascript-delayfor dynamic pages. - Check the viewer: open the same PDF in another viewer to rule out viewer-specific navigation behavior.
- Capture reproduction details: save the command, input URL or file, wkhtmltopdf version, build, operating system, and a minimal HTML case.
Common symptoms, causes, and fixes
| Symptom | Likely cause | Action |
|---|---|---|
| No external links anywhere | External annotations disabled or unsupported in the deployed build | Inspect help output; use --enable-external-links; verify the PDF and build. |
| No internal links, external links work | Internal annotations disabled or destination missing | Enable internal links and verify matching id targets in rendered HTML. |
| Link text appears, but it is not clickable | The anchor was created too late or removed by JavaScript | Wait with --window-status or an appropriate delay; inspect the final DOM. |
| Footer link goes to the wrong place | Historical header/footer-to-body edge case or malformed target | Reproduce independently with the exact version; move the link into main HTML if necessary. |
| Disabling links did not stop image or script traffic | Annotation controls are not network controls | Apply request filtering and OS/network isolation. |
| Works locally but not in production | Different binary, patched-Qt build, fonts, filesystem, or timing | Compare version/build and run the minimal case in the production environment. |
Performance and reliability considerations
Every additional JavaScript wait increases conversion latency, and a delay that is adequate on a fast workstation can be inadequate under production load. A status-based completion signal is generally more predictable than an arbitrary sleep. Minimal reproduction files also reduce unrelated variables such as third-party scripts, redirects, missing fonts, and lazy-loaded content.
For repeatable output, pin the wkhtmltopdf executable and its build, log conversion failures, retain a failing input, and validate PDFs in an automated check that confirms expected annotations. Test external and internal links independently; a successful page load does not prove that either annotation type was emitted.
Or skip the browser setup
If you need a hosted capture rather than maintaining a wkhtmltopdf process, ScreenshotNeo is a website screenshot API and MCP server. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the result with X-Page-Verdict and X-Billed headers. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.
One GET request can return PNG, JPEG, WebP, or PDF:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for all 63 options, including full-page capture, CSS-selector elements, device presets, retina scale, PDF paper and page ranges, custom CSS and JavaScript, clicks, waits, blocking, headers, cookies, user agents, timezone, geolocation, resizing, caching, signed links, asynchronous webhooks, bulk capture, and the usage API.
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account.
Frequently Asked Questions
How can I tell whether a PDF link is missing or merely misdirected?
Use a PDF viewer or inspection utility that exposes annotations. If no annotation rectangle exists, investigate wkhtmltopdf options and build settings; if one exists, inspect its action and destination, then check the source target and viewer behavior.
Are internal links called local links in wkhtmltopdf libraries?
Often, yes. The CLI calls them internal links, while documented library settings commonly use the name useLocalLinks. Confirm the exact names in your binding.
Should I disable links when rendering untrusted HTML?
No. Link switches only affect PDF annotations. Untrusted HTML requires process, filesystem, and network isolation in addition to any wkhtmltopdf access controls.
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.
Recommended Free Tools

