ScreenshotNeo

BlogHTML to image & PDF

How to Print Password-Protected Pages to PDF With wkhtmltopdf Cookies

Use wkhtmltopdf cookies, cookie jars, or HTTP authentication to render protected pages, then diagnose redirects, timing, and login-flow limits.

By the ScreenshotNeo team30 September 20269 min read

How to Print Password-Protected Pages to PDF With wkhtmltopdf Cookies

Direct answer: wkhtmltopdf supports three different kinds of protected access. For an existing web session, pass a cookie with --cookie name value or use --cookie-jar path. For server-level HTTP authentication, use --username and --password. These flags do not demonstrate support for submitting a normal website login form, completing MFA, solving CAPTCHA, or running a contemporary identity-provider flow. Identify the protection mechanism first, then choose the matching command.

wkhtmltopdf is a command-line HTML-to-PDF converter built around Qt WebKit. Its project usage documentation describes cookie options, HTTP authentication, custom headers, JavaScript controls, delays, and window-status waits. The exact behavior depends on the binary installed on your machine, so check its version and extended help before relying on an option.

1. Identify what “password-protected” means

People use that phrase for several unrelated mechanisms. A cookie is session state issued after authentication; it is not the account password. HTTP authentication is a protocol-level challenge handled separately from a website login form. A single-page application may also require JavaScript to exchange tokens before protected content appears.

Protection mechanism wkhtmltopdf approach What to expect
Known session cookie --cookie name value Repeat the option for each cookie. The project documentation says the value should be URL encoded.
Cookie state in a file --cookie-jar path The jar is read and written. The sources do not promise compatibility with every browser export format.
HTTP Basic or similar server challenge --username and --password The documented password is for HTTP authentication, not a form field on a web page.
Required request header --custom-header name value Use propagation only when the site requires the header on subresource requests.
Interactive login, MFA, CAPTCHA, or SSO No documented automatic workflow in these sources Use a browser automation step to establish state first, or choose a capture service that can load the page in a browser context.

Start by opening the target URL in a normal browser and observing the request. If the server immediately sends an HTTP authentication challenge, use the HTTP flags. If a successful browser session contains a cookie that authorizes the page, supply that cookie. If the page redirects to an identity provider or displays a login form, cookie flags alone will not perform that interaction.

2. Check the installed build before writing the command

wkhtmltopdf --version
wkhtmltopdf --extended-help | less

The project usage text describes conversion using patched Qt. The Debian Bookworm manpage describes a package that does not use patched Qt. Distribution builds can therefore differ in JavaScript, authentication, and rendering behavior. Match the command to the help output from the executable you will actually run. Keep a copy of the version output with your deployment notes so an upgrade does not silently change rendering.

Use --cookie when you already possess a valid cookie value for the destination host. The option is repeatable, which matters when a site uses separate cookies for the session, CSRF state, or tenant selection.

A session cookie supplies existing access state while wkhtmltopdf renders the protected page.
A session cookie supplies existing access state while wkhtmltopdf renders the protected page.
wkhtmltopdf \
  --cookie SESSION_COOKIE 'URL_ENCODED_VALUE' \
  'https://example.invalid/protected-page' \
  protected.pdf

Replace the placeholders with values appropriate for your environment. Quote both the URL and cookie value when shell characters could be interpreted by the shell. URL-encode the cookie value as required by the project usage documentation. Do not paste a real token into a public issue, tutorial, CI log, or shell history.

For multiple cookies, repeat the option:

wkhtmltopdf \
  --cookie SESSION_COOKIE 'URL_ENCODED_SESSION' \
  --cookie TENANT_ID 'URL_ENCODED_TENANT' \
  --cookie CSRF_TOKEN 'URL_ENCODED_CSRF' \
  'https://example.invalid/account/report' \
  report.pdf

Cookies are scoped by host, path, and expiration in the browser. Supplying a value on the command line does not make it valid for a different host or an expired session. If the result is a login page, inspect the redirect chain and cookie scope before changing PDF layout settings.

--cookie-jar tells wkhtmltopdf to read and write cookie state at the specified path.

wkhtmltopdf \
  --cookie-jar /secure/path/wkhtml-cookies.txt \
  'https://example.invalid/protected-page' \
  protected.pdf

The documented behavior is read-and-write persistence. The sources do not specify a browser-export workflow or guarantee that an arbitrary browser cookie database can be passed directly. Verify the file format accepted by your installed build. Treat the jar as a credential: restrict file permissions, keep it outside a web root, avoid committing it to source control, and delete or rotate it when the session expires.

A cookie jar is useful when a wrapper program performs an initial authenticated request and then invokes wkhtmltopdf with the same file. It is not, by itself, a login automation mechanism. If no valid cookie is present, the converter cannot invent one.

5. Handle HTTP authentication separately

When the web server challenges with HTTP authentication, use the dedicated flags:

wkhtmltopdf \
  --username 'HTTP_USER' \
  --password 'HTTP_PASSWORD' \
  'https://example.invalid/private/report' \
  report.pdf

The project’s settings documentation labels these fields as HTTP authentication credentials. Do not use them as though they were the username and password inputs of a normal HTML login form. Avoid placing real secrets directly in a shared machine’s process list or shell history; use the secret-handling facilities available in your operating system or wrapper.

6. Add a custom header only when the site requires one

Some protected endpoints expect a header rather than a cookie. The CLI documents --custom-header and --custom-header-propagation:

wkhtmltopdf \
  --custom-header 'X-Access-Token' 'REDACTED_VALUE' \
  'https://example.invalid/export' \
  export.pdf

Propagation applies configured headers to each resource request. That can be necessary for an application whose images, stylesheets, or API calls require the same header, but it can also expose a credential to embedded resources or another host. Confirm the site’s request requirements and keep the destination narrowly scoped. The documentation describes the propagation behavior; it does not establish that sending a credential header to every resource is safe.

7. Wait for JavaScript-rendered content

Authentication and rendering are separate concerns. A valid cookie can authorize the page while JavaScript still needs time to assemble the report. The usage documentation includes JavaScript controls, a fixed delay, and a window-status wait.

wkhtmltopdf \
  --enable-javascript \
  --javascript-delay 3000 \
  --cookie SESSION_COOKIE 'URL_ENCODED_VALUE' \
  'https://example.invalid/dashboard' \
  dashboard.pdf

If the application sets a known window status after rendering, a status-based wait can be more deterministic than guessing a delay:

wkhtmltopdf \
  --enable-javascript \
  --window-status report-ready \
  --cookie SESSION_COOKIE 'URL_ENCODED_VALUE' \
  'https://example.invalid/report' \
  report.pdf

These timing options affect when wkhtmltopdf captures the page. The cited sources do not establish compatibility with MFA, CAPTCHA, or every modern single-sign-on flow. A page that requires a browser to execute a login challenge may remain inaccessible even when JavaScript is enabled.

8. A repeatable diagnostic workflow

  1. Record the build. Save wkhtmltopdf --version and relevant --extended-help output.
  2. Classify the access method. Distinguish HTTP authentication, a session cookie, a custom header, and an interactive login.
  3. Try the smallest command. Start with one URL and one authentication mechanism. Add timing or headers only when the page requires them.
  4. Inspect the output. Open the PDF and verify that it contains the protected content rather than a sign-in page, access-denied page, or blank shell.
  5. Check redirects. A redirect to login usually indicates missing, expired, wrongly scoped, or incorrectly encoded state. This is a troubleshooting inference, so confirm it using the site’s network traces.
  6. Separate access from layout. Solve authentication first; then adjust page size, margins, JavaScript delay, or print styling.

9. Troubleshooting common failures

Symptom Likely cause Fix
PDF contains the login form Cookie missing, expired, scoped to another host/path, or malformed Obtain a fresh session cookie, URL-encode its value, confirm the destination host, and repeat --cookie for every required cookie.
HTTP 401 or authentication prompt The server expects HTTP authentication Use --username and --password; do not treat a form password as an HTTP credential.
Styles or images are missing Subresource requests need a header or cookie Test --custom-header and, only when required, --custom-header-propagation. Check whether resources are on another host.
Blank or partially rendered report JavaScript has not finished when capture occurs Enable JavaScript and use --javascript-delay or --window-status. Verify that the application actually reaches the expected state.
Works locally but fails in CI Different binary, Qt build, environment, cookie file permissions, or expired session Log the version, use an isolated cookie jar, check file permissions, and compare extended-help output between environments.
Cookies appear in logs Secrets were passed through verbose shell or process logging Remove debug logging, rotate exposed sessions, and supply secrets through a protected wrapper or secret store.

10. Security and operational notes

  • Session cookies and cookie jars are bearer credentials. Anyone who obtains a valid one may gain the same access as the session.
  • Use a dedicated account or short-lived session when the site supports it. Limit the target URL and avoid sending credentials to unrelated hosts.
  • Do not publish real cookies, passwords, authorization headers, or cookie-jar files in examples.
  • Be careful with --custom-header-propagation; a header intended for one origin may be copied to embedded requests.
  • Keep authentication diagnostics separate from PDF output. A successful conversion can still capture sensitive data, so protect the resulting file and its temporary directory.

11. Performance, reliability, and cost considerations

Rendering time is usually dominated by page load, JavaScript, network requests, and any deliberate delay. A fixed delay that is too short produces incomplete PDFs; one that is too long wastes worker time. Window-status signaling can reduce guesswork when the application supports it. Cookie jars avoid repeating an interactive setup, but they do not remove session expiration or server-side authorization checks.

Hosted capture can remove common overlays before producing the final image or PDF.
Hosted capture can remove common overlays before producing the final image or PDF.

For batch jobs, isolate each conversion, set an external timeout, retain the command and binary version for reproducibility, and retry only failures that are plausibly transient. Repeating a conversion will not repair an invalid cookie or an unsupported MFA flow. wkhtmltopdf itself has no documented pricing in the cited material; your costs come from the machines, network, storage, and any surrounding automation.

Or skip the browser setup

ScreenshotNeo provides a hosted capture API and MCP server when you need a rendered page without maintaining a wkhtmltopdf browser setup. It accepts a URL and returns a PNG, JPEG, WebP, or PDF. For a protected page, pass the authentication details supported by your application through the API’s custom headers, cookies, user agent, or Authorization options.

See the ScreenshotNeo API documentation for the complete option list. A minimal request looks like this:

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(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. One thousand screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Can I pass my website username and password to wkhtmltopdf?

Only when those credentials are for HTTP authentication. The documented --username and --password flags do not show how to submit a normal HTML login form.

No. A cookie represents session state issued by the site. It can expire, be restricted to a host or path, or be revoked independently of the account password.

The documentation says the jar is read and written, but the cited sources do not guarantee compatibility with any browser’s database or export format. Confirm the format accepted by your build.

Why does the PDF show a blank application shell?

The page may depend on JavaScript or an API request that has not completed. Enable JavaScript and use a suitable delay or window-status condition, then verify that authentication is also sent to the API request.

Which build should I install?

Build details matter. Compare your executable’s version and help output with the documentation for that package; the project usage text and Debian Bookworm manpage describe different Qt packaging.