A 406 response means that a server could not provide a representation acceptable under the request’s Accept headers; it does not tell you whether the failing request was for the page, a stylesheet, an image, or another resource. An empty or incomplete PDF can also result from inaccessible local files, failed remote assets, redirects, or the particular wkhtmltopdf build that pdfkit invokes. Start by capturing the renderer’s verbose output and exact command, then change one part of the request or rendering setup at a time.
What a 406 tells you—and what it does not
The HTTP/1.1 status-code specification hosted by W3C defines 406 as a response where the resource can produce only representations whose characteristics are not acceptable under the request’s Accept headers. That describes a negotiation failure, not its cause in your particular conversion. The request that failed might be for the main HTML page, a redirected URL, a stylesheet, an image, or another asset requested while the page is rendered.
Do not assume that changing the page request’s Accept header will fix the problem. First identify the URL returning 406 and compare the request made by wkhtmltopdf with one that succeeds. If a referenced asset is the failing request, changing headers on the main request may not help.
Capture the failure before changing settings
pdfkit is a Python wrapper around the wkhtmltopdf executable. Its README recommends enabling verbose output and, when behavior is unexpected, inspecting the command it generated and running that command directly. This separates a wrapper issue from behavior in the renderer, input, or deployment environment.
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 →#1 Best Overall
- Turn on verbose output. Pass
verbose=Trueto your conversion so you can preserve the renderer’s stderr messages. The README notes that quiet mode is normally enabled. - Record the conversion details. Save the requested page URL or input file, the complete stderr output, any failed asset URLs, the HTTP status and redirect chain if available, the operating system, the
pdfkitversion, the output ofwkhtmltopdf --version, and the resolved executable path. - Inspect the generated command. Create a
pdfkit.PDFKitobject for the same input and options, then inspect itscommand(). Run that command in the same environment. If it fails identically, investigate the input, renderer, and environment rather than assuming Python itself is the cause. - Compare the executable paths. A Python process can use a different binary from the one you invoke in a shell.
pdfkit.configuration()accepts an explicitwkhtmltopdfbinary path, so check that both tests use the intended executable.
For a URL input, a minimal diagnostic conversion looks like this:
import pdfkit
url = "https://example.com/page"
pdfkit.from_url(url, "output.pdf", verbose=True)
Replace the example URL with the failing page and keep the verbose output with the test results. If you already have a conversion call, add verbose=True to that call instead of changing several other options at once.
Diagnose a 406 response
Find the exact request that receives the status
Use the renderer’s output and, where available, server or proxy logs to identify the URL associated with the 406. Check whether it is the original page, a redirected destination, or a subresource. A browser successfully displaying a page is useful comparison evidence, but it does not prove that the renderer makes the same requests: headers, cookies, authentication, redirects, or asset access can differ.
Compare the failing renderer request with a known successful request to the same URL. Keep the URL and route the same while comparing, and note any redirect before deciding which request to change. If only one image or stylesheet is rejected, test that asset directly as well as the top-level page.
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 reinstallRank #2
Add only required headers or cookies
wkhtmltopdf documents custom-header and cookie options, and pdfkit exposes repeatable custom-header and cookie options. Use them only when you have established that the endpoint requires a particular header or authentication cookie. Verify whether the headers need to be applied to resource requests too; a page may load while its protected assets do not.
Do not treat a guessed User-Agent or Accept value as a general 406 repair. The response definition points to negotiation, but the correct acceptable representation and the server’s policy depend on the endpoint. Confirm the required request behavior with the service configuration or logs before changing it.
Diagnose empty or incomplete PDFs
Separate page content from assets
Check whether the HTML itself is present and whether CSS, images, fonts, or other referenced media load successfully. Remote assets may need different authentication, cookies, proxy access, or redirect handling from the main document. A conversion can therefore produce a PDF while omitting some of the page’s visible content.
Use --load-error-handling and --load-media-error-handling only as diagnostic or tolerance controls for failed page and media loads. Allowing the conversion to continue does not make an inaccessible asset available; it can simply leave that content missing. Keep the error output and inspect the resulting PDF before treating a completed conversion as a correct one.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Check local-file paths and access policy
If your HTML comes from a local file or string and refers to local images, stylesheets, or other files, verify that those paths resolve in the renderer’s context and that its local-file access policy permits them. The wkhtmltopdf usage reference documents local-file access controls and an allow-list option, --allow. Check the deployed executable’s own --extended-help or documentation for the supported behavior; do not assume every packaged build handles the option identically.
A Windows 10 report for wkhtmltopdf 0.12.6 described blocked local image access and an about:blank ProtocolUnknownError; the reporter said conversion worked after removing local image references. Treat that as a clue to test local assets, not proof that they explain every empty PDF.
Compare input forms and execution contexts
Change one axis at a time. Try the same content as a URL, a file, or a string where applicable; compare local assets with remote ones; compare the renderer’s request with a successful browser or HTTP-client request; and compare authenticated and unauthenticated access only when that route requires authentication. Also compare a direct shell invocation with the pdfkit call.
This method makes a useful distinction: if the same command fails outside Python, focus on the renderer, its inputs, or the runtime environment. If the shell command succeeds but the Python call does not, compare the actual generated command, options, working context, and executable path.
Check the installed wkhtmltopdf build
Record the exact wkhtmltopdf version, platform, package source, and binary path—not just the Python package version. The pdfkit repository marks the library deprecated and warns that some Debian and Ubuntu packaged builds lack patched-Qt functionality, including features such as headers, footers, outlines, and tables of contents. That warning can explain feature differences; it does not establish that replacing a build will fix every 406 or blank PDF.
A separate issue report describes a 403 on an SSL-enabled nginx reverse-proxy path in a stated wkhtmltopdf 0.12.6 patched-Qt / Ubuntu Focal environment, while local rendering worked. The report is unresolved, so it is a symptom pattern rather than a confirmed root cause. If your setup resembles it, inspect redirects, proxy logs, requested routes, and certificate or renderer errors before changing SSL settings. Do not switch to HTTP or disable SSL checks as a presumed safe fix.
Troubleshooting checklist
| Symptom | What to inspect | Next step |
|---|---|---|
| 406 during conversion | The exact URL and request returning 406, including redirects and subresources | Compare the renderer’s request with a successful request; add only confirmed required headers or cookies. |
| PDF is blank or missing styled content | Verbose output, failed CSS or media requests, and whether page HTML is available | Test the relevant asset separately and check its access, authentication, and redirect behavior. |
| Local images or styles disappear | Resolved paths and the renderer’s local-file access policy | Verify the deployed build’s access controls and use its documented allow-list behavior if needed. |
| CLI and Python results differ | The generated command(), options, executable path, and execution context |
Run the generated command directly and ensure both tests use the intended binary. |
| Behavior changes across machines | Operating system, package source, exact renderer build, and pdfkit version |
Compare environments before attributing the issue to the wrapper or changing builds. |
Avoid treating a successful process exit as proof that the PDF is complete. Review the file and correlate missing content with the renderer’s page-load and media-load messages.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If the task is to capture a web page rather than debug a particular pdfkit conversion, ScreenshotNeo offers a screenshot API and MCP server. A single GET request returns an image; the product also supports PDF output. This is an alternative capture workflow, not a repair for your existing wkhtmltopdf installation.
Best Value
Example request (replace the target URL and access key):
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 request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to try 1,000 screenshots a month with no card.
Frequently Asked Questions
Does a 406 prove that the main page URL is the problem?
No. The rejected request could be for a redirected destination or a page asset such as a stylesheet or image. Identify the exact URL returning 406.
Will allowing failed media loads make a blank PDF complete?
No. Those options can affect how the renderer handles a failed load; they do not make inaccessible or incorrect source content available.
Is replacing wkhtmltopdf a guaranteed fix for pdfkit errors?
No. Build differences can affect some features, but the available documentation does not establish a replacement as a universal fix for 406 responses or empty PDFs.
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.




