How to Capture a Website Behind a Login with wkhtmltoimage
Pass wkhtmltoimage a valid session cookie or HTTP credentials to capture an authenticated page. Learn the workflow, limits, security precautions, and alternatives.
Yes: wkhtmltoimage can capture a page behind a login if you give it request credentials it understands, such as a valid session cookie or HTTP Basic authentication credentials. It does not perform an interactive sign-in flow. Its documented options do not describe completing a login form, MFA challenge, or SSO sequence. First obtain an authorized session cookie through the site’s normal login flow, then pass that cookie to the capture command and verify the resulting image.
wkhtmltoimage is a headless HTML-to-image renderer based on Qt WebKit. Its upstream repository was archived on January 2, 2023, and the changelog lists version 0.12.6 on June 11, 2020. Older WebKit behavior may not work with modern sites. Project repository and status; project changelog.
1. Sign in and obtain a valid session cookie
Sign in through the website’s supported login process using an approved method, then obtain a valid session cookie for the account and page you are authorized to access. A common web login flow has the server issue a session-ID cookie after successful credentials; see MDN’s guide to HTTP cookies.
The way to obtain the cookie depends on the site and your authorization. Confirm its domain and path cover the target URL, and check whether it expires or is rotated. A redirect to a login page, a JavaScript challenge, MFA, SSO, or additional API requests may require a real browser session that wkhtmltoimage cannot create by itself.
Treat the cookie like a password. Do not put a live token in a public example, a shared script, a shell command that enters shell history, or logs. Use a protected, access-controlled file or secret-handling mechanism appropriate to your environment; remove temporary credential files when finished.
2. Pass the cookie to wkhtmltoimage
The Debian bookworm manual documents --cookie name value and --cookie-jar path. Use the exact syntax supported by your installed build: distributions can package different versions. Check wkhtmltoimage --help or its installed manual before running the command.
Pass a cookie directly
wkhtmltoimage --cookie SESSION_ID 'REPLACE_WITH_SESSION_VALUE' 'https://example.com/account/report' account-report.png
Replace the cookie name, value, authorized target URL, and output filename. This form is concise, but the cookie value is a command-line argument and may be visible in shell history or process inspection. Avoid it for a live credential on shared or production systems.
Use a cookie jar
wkhtmltoimage --cookie-jar /secure/path/cookies.txt 'https://example.com/account/report' account-report.png
The jar must contain cookies in a format accepted by your installed build. The manual documents the option but does not prescribe a secure storage method. Keep the file private, restrict access, avoid committing it to source control, and delete or rotate it when no longer needed. If the site redirects across domains, confirm the cookie’s scope and whether the jar supplies it to the destination.
3. HTTP authentication and custom headers
If the server uses HTTP authentication rather than a web login form, the manual documents --username and --password. These options do not mean the tool can submit an arbitrary site’s login form.
wkhtmltoimage --username 'REPLACE_WITH_USER' --password 'REPLACE_WITH_PASSWORD' 'https://example.com/private/report' report.png
As with a cookie passed inline, command arguments can leak through history or process inspection. Prefer a protected execution environment and avoid printing secrets in diagnostics. The manual also documents custom headers:
wkhtmltoimage --custom-header 'Authorization' 'Bearer REPLACE_WITH_TOKEN' 'https://example.com/private/report' report.png
Use only an authorization header format the target server accepts. --custom-header-propagation passes custom headers to resource requests as well as the main page; that can expose credentials to additional hosts referenced by the page. Enable propagation only when required and when those requests are trusted.
4. Wait for JavaScript and shape the output
For pages that render content with JavaScript, the manual documents JavaScript enable/disable controls, a delay, and a window-status wait. These options provide readiness hints; they do not guarantee that all network activity or dynamic rendering has completed.
wkhtmltoimage \
--enable-javascript \
--javascript-delay 2000 \
--width 1440 \
--height 1000 \
--cookie SESSION_ID 'REPLACE_WITH_SESSION_VALUE' \
'https://example.com/account/report' \
account-report.png
The example waits two seconds and sets the viewport dimensions. Choose dimensions and delay based on the page, then inspect the image. If the page exposes a readiness status through window.status, use the documented wait option instead of guessing a delay:
wkhtmltoimage --window-status 'REPLACE_WITH_READY_STATUS' --cookie SESSION_ID 'REPLACE_WITH_SESSION_VALUE' 'https://example.com/account/report' account-report.png
The target page must actually set the status value for this to help. Consult the installed manual for output format, quality, zoom, crop, and viewport options supported by your version. The selected output dimensions and page layout affect the result; no single width or delay suits every site.
5. Check that the capture is the page you intended
- Open the generated image and confirm it shows the authenticated account and expected content.
- Check for a login redirect, access-denied page, bot check, empty shell, missing images, or content that appeared after capture.
- If it is wrong, confirm cookie name, value, scope, expiry, and redirect behavior before changing timing options.
- Repeat only with an authorized session, and keep the credential out of shared logs and artifacts.
A successful process exit or image file does not prove the capture is authenticated. The renderer can produce an image of a login page or incomplete page just as readily as the intended destination.
What wkhtmltoimage can and cannot do for login-protected pages
| Need | What to try | Limit |
|---|---|---|
| Existing web session | Supply a valid cookie or cookie jar. | Cookie scope, expiry, redirects, and site policy determine whether it works. |
| HTTP Basic-style authentication | Use documented username and password options. | This is HTTP authentication, not submission of a site’s login form. |
| Custom token header | Use a documented custom header. | Header format and authorization are server-specific; propagation can send it on resource requests too. |
| Interactive form, MFA, or SSO | Complete the supported login flow in a browser and supply a valid session if permitted. | The documented inputs do not automate that interactive flow. |
| Modern JavaScript-heavy page | Try the JavaScript and readiness options, then inspect the output. | Qt WebKit is old; current browser behavior may be required. |
Security and local-file access
Capture only pages you are authorized to access. Session cookies and authorization headers are credentials: scope access to them, avoid exposing them in command history or logs, and do not store them in an image artifact or repository. If the page needs local files, the manual documents --disable-local-file-access and narrowly scoped --allow access. Prefer limiting local access to the exact needed directory rather than granting broad filesystem access.
Troubleshooting
| Symptom | Likely cause | What to check or change |
|---|---|---|
| The image shows the login screen. | Cookie is missing, expired, scoped to another host/path, or lost on redirect; the site may require interactive sign-in. | Obtain a fresh authorized cookie, verify its scope and destination host, and inspect redirect behavior. If an interactive flow is required, use a browser-based workflow. |
| The page is blank or mostly empty. | Rendering has not completed, JavaScript is incompatible, or resources failed. | Try a documented delay or window-status wait, inspect JavaScript/resource errors where available, and compare with a current browser. |
| Some images or styles are missing. | Resources are delayed, blocked, cross-origin, or require credentials the capture did not send. | Check the page’s resource URLs and authentication needs. Only enable custom-header propagation if required and safe for all requested hosts. |
| The command rejects an option. | Installed version or package build uses different options. | Check that executable’s own help/manual and follow its exact syntax. |
| HTTP authentication still redirects to a form. | The site uses application-level login rather than HTTP authentication. | Use its normal sign-in flow to obtain a session cookie; username/password flags do not submit the form. |
| Cookie works in a browser but not in the capture. | The site depends on browser behavior, extra requests, modern JavaScript, or anti-bot checks. | Verify the authorized session and page state in a current browser. If needed, move to a current browser automation or screenshot workflow. |
| The capture is cut off or laid out differently. | Viewport, crop, zoom, or page CSS changes the rendered image. | Adjust documented dimensions or crop settings and inspect the resulting image at the intended size. |
| Local resources fail to load. | Local-file access is disabled or restricted. | Use the documented local-file controls and grant access only to the specific required path. |
Performance, reliability, and cost considerations
A fixed JavaScript delay adds waiting time to each capture, while too short a delay risks incomplete content. A window-status wait can be more targeted when the page provides a reliable signal, but neither option ensures every request is finished. Large pages, remote resources, and rendering complexity affect duration and output size.
For repeatable jobs, record the renderer version, target URL, viewport, output format, timing options, and whether the image showed the expected state. Recheck after site changes. The upstream project is archived, and its latest listed release is from 2020, so compatibility with current authentication and browser features is uncertain. The wkhtmltoimage binary itself has no per-capture fee established by the cited sources; hosting, maintenance, and engineering time still have costs.
Alternative for modern browser requirements
Chrome’s official headless command-line documentation describes taking screenshots and documents capture timeouts. A current browser-based workflow is a reasonable category to consider when the page depends on modern browser behavior or interactive login. A timeout is only a timing limit; it does not prove that the intended content finished loading. See Chrome Headless command-line reference.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request takes a URL and returns an image or PDF. For example, this captures a public page as WebP:
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 API documentation for authentication and options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. ScreenshotNeo can capture pages by URL, but this example does not establish that it can authenticate to a particular private site; check the documented options against your access requirements.
Sign up for 1,000 free screenshots a month, with no card.
FAQ
Can wkhtmltoimage log in with MFA?
Its documented cookie and HTTP-authentication options supply request credentials; they do not document completing an MFA challenge. Complete an authorized login with the site’s supported flow and use a valid session cookie if the site permits it.
Does passing a cookie guarantee access?
No. The site may reject an expired or out-of-scope cookie, redirect to another host, require additional state, or block the renderer. Inspect the captured image to confirm the page state.
Should I use wkhtmltoimage for a new screenshot workflow?
It may suit pages that work with its older WebKit renderer and supplied request credentials. For modern browser features or interactive sign-in, assess a current browser-based workflow and verify the result against the target site.


