Images not appearing in wkhtmltopdf-generated PDFs is one of the most common issues developers encounter. Whether local images fail to load, remote images time out, base64 images render blank, or SVGs display incorrectly, the root causes trace back to wkhtmltopdf's security model, path resolution quirks, and the limitations of its abandoned rendering engine. This article documents the eight most common image rendering failures, explains their technical causes, and provides working solutions.
The Problem
wkhtmltopdf converts HTML to PDF using a headless WebKit rendering engine. When images fail to appear, the resulting PDF contains blank spaces, broken image placeholders, or nothing at all where images should be. The HTML may render correctly in a browser, but the same content produces missing images when processed by wkhtmltopdf.
This problem has plagued developers for years. A search through GitHub issues, Stack Overflow questions, and community forums reveals thousands of reports, many without satisfactory resolutions. The issue became permanent when wkhtmltopdf was archived on January 2, 2023, meaning these problems will never receive official fixes.
Error Messages and Symptoms
Depending on the specific cause, developers may see these warnings in the console output:
Warning: Blocked access to file /path/to/image.png
Failed to load file:///path/to/image.png (ignore)
QSslSocket: cannot resolve TLSv1_1_client_method
Warning: SSL error ignored
Exit with code 1 due to network error: ContentNotFoundError
In many cases, wkhtmltopdf produces no error at all. The PDF generates successfully, but images simply do not appear. The HTML displays correctly in Chrome, Firefox, and Edge, yet wkhtmltopdf outputs blank rectangles where images should render.
Who Is Affected
This issue affects developers across multiple scenarios:
- Local development environments: Images load in the browser but not in generated PDFs
- Docker containers: Paths that work on host machines fail inside containers
- Linux servers: Different path resolution and permission models than Windows
- Cloud deployments: Network restrictions, HTTPS certificate validation, and containerized environments
- CI/CD pipelines: Isolated build environments with restricted filesystem access
- Applications using wkhtmltopdf wrappers: DinkToPdf, TuesPechkin, Rotativa, Snappy, wicked_pdf, and PDFKit all inherit these issues
Eight Common Causes of Missing Images
1. Local File Access Blocked (Security Restriction)
Starting with version 0.12.6 (June 2020), wkhtmltopdf disabled local file access by default. This security change addressed CVE-2020-21365, a directory traversal vulnerability that could expose sensitive files. However, it also broke countless applications that referenced local images.
Symptoms:
Warning: Blocked access to file /var/www/app/images/logo.png
The Fix:
Add the --enable-local-file-access flag:
wkhtmltopdf --enable-local-file-access input.html output.pdf
For PHP Snappy:
$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
$snappy->setOption('enable-local-file-access', true);
For Ruby wicked_pdf:
WickedPdf.new.pdf_from_string(html, enable_local_file_access: true)
Limitations:
The flag placement matters. wkhtmltopdf's argument parser requires global options like --enable-local-file-access to appear before input files:
# Correct
wkhtmltopdf --enable-local-file-access input.html output.pdf
# Incorrect (may fail silently)
wkhtmltopdf input.html --enable-local-file-access output.pdf
Even with the flag enabled, some users report continued failures. The flag does not exist in wkhtmltopdf versions prior to 0.12.6, causing older code to error with "unrecognized option."
2. Relative Path Resolution Failures
wkhtmltopdf interprets relative paths differently than web browsers. When processing HTML from a string or stdin, wkhtmltopdf has no base URL context, causing relative paths to resolve against unexpected directories.
Symptoms:
Images work when HTML is loaded from a file but fail when passed as a string. The path /images/logo.png resolves to the filesystem root rather than the web root.
Example failure:
<!-- This path is ambiguous to wkhtmltopdf -->
<img src="/images/logo.png">
When wkhtmltopdf processes this from stdin:
cat input.html | wkhtmltopdf --enable-local-file-access - output.pdf
The path /images/logo.png becomes file:///images/logo.png, looking for /images/logo.png at the filesystem root.
Solutions:
Use absolute filesystem paths:
<img src="file:///var/www/myapp/public/images/logo.png">
Or use the --allow flag to specify the base directory:
wkhtmltopdf --enable-local-file-access --allow /var/www/myapp/ input.html output.pdf
Or use full HTTP URLs:
<img src="http://localhost:3000/images/logo.png">
3. Docker Container Path Issues
Docker containers present unique challenges. Paths that work on the host machine may not exist inside the container. Volume mounts, user permissions, and network isolation all contribute to image loading failures.
Symptoms:
Application works locally on Windows or macOS but images disappear when deployed to a Docker container. No error messages appear, but the PDF contains blank spaces.
Common causes:
- Volume not mounted: The image directory exists on the host but is not accessible to the container
- Permission denied: Container user lacks read access to mounted directories
-
Different filesystem paths:
/Users/developer/project/imageson macOS becomes/app/imagesin the container
Solutions:
Mount the images directory correctly in docker-compose.yml:
services:
app:
volumes:
- ./images:/app/images:ro
Ensure the wkhtmltopdf container can access the files:
FROM surnet/alpine-wkhtmltopdf:3.16.2-0.12.6-small
RUN chmod -R 755 /app/images
Use absolute container paths in HTML:
<img src="file:///app/images/logo.png">
Or serve images via HTTP from another container:
<img src="http://nginx/images/logo.png">
4. HTTPS and SSL Certificate Problems
wkhtmltopdf's SSL implementation is outdated. It cannot handle modern TLS configurations, causing HTTPS images to fail silently or produce SSL warnings.
Symptoms:
Warning: SSL error ignored
Failed to load https://cdn.example.com/image.png
QSslSocket: cannot resolve TLSv1_1_client_method
Images load from HTTP URLs but not HTTPS. The same HTTPS URL works in curl and browsers.
Root cause:
wkhtmltopdf links against an old version of Qt's SSL libraries. Many CDNs and image hosts require TLS 1.2 or 1.3, which wkhtmltopdf's Qt WebKit may not properly negotiate.
Workarounds:
Ignore SSL errors (security risk):
wkhtmltopdf --no-stop-slow-scripts --ssl-crt-path /etc/ssl/certs/ input.html output.pdf
Switch HTTPS URLs to HTTP (only for non-sensitive content):
$html = str_replace('https://', 'http://', $html);
Download images and embed as base64:
// Download image, convert to base64, embed inline
var imageBytes = httpClient.GetByteArrayAsync(url).Result;
var base64 = Convert.ToBase64String(imageBytes);
var dataUri = $"data:image/png;base64,{base64}";
html = html.Replace(url, dataUri);
5. Base64 Image Rendering Failures
Base64 data URIs should bypass network and filesystem issues entirely. Yet developers frequently report base64 images not rendering in wkhtmltopdf, particularly for background images and certain formats.
Symptoms:
Images embedded as base64 render in browsers but appear blank in the PDF. No error messages in wkhtmltopdf output.
Known issues:
-
Background images: Base64-encoded CSS background images often fail where
<img>tags succeed - BMP format: Base64 BMP images may not render even when PNG and JPG work
- Large images: Base64 strings exceeding certain lengths can cause silent failures
- SVG with embedded base64: SVGs containing base64 image data may render blank
Example of broken CSS background:
/* This often fails in wkhtmltopdf */
.logo {
background-image: url(data:image/png;base64,iVBORw0KGgo...);
width: 200px;
height: 100px;
}
Workarounds:
Use <img> tags instead of CSS backgrounds:
<img src="data:image/png;base64,iVBORw0KGgo..." style="width: 200px; height: 100px;">
Convert BMP to PNG before base64 encoding.
For large images, consider external HTTP references or local file paths.
6. SVG Rendering Issues
wkhtmltopdf uses Qt's SVG renderer, which has significant limitations. SVGs that render correctly in browsers may appear blank, distorted, or missing elements in wkhtmltopdf output.
Symptoms:
- SVG images not appearing at all
- SVG paths missing or partially rendered
- SVGs squashed or incorrectly sized
- Images embedded inside SVGs not visible
Known Qt SVG limitations:
- Complex clip-paths may not render
- Opacity properties sometimes ignored
- External references inside SVGs fail
- Certain filters and effects unsupported
- CSS conflicts with HTML attributes
Example failures:
<!-- IMG tag with SVG src may not render -->
<img src="logo.svg" width="100" height="50">
<!-- Inline SVG with clip-path may render incorrectly -->
<svg>
<defs>
<clipPath id="clip">
<circle cx="50" cy="50" r="50"/>
</clipPath>
</defs>
<image clip-path="url(#clip)" href="photo.jpg"/>
</svg>
Workarounds:
Use SVG as CSS background with explicit dimensions:
<span style="display:inline-block; width:100px; height:50px; background:url(logo.svg) no-repeat;"></span>
Convert SVGs to PNG before PDF generation:
# Using Inkscape
inkscape --export-type=png --export-filename=logo.png logo.svg
Embed SVG inline with explicit viewBox and dimensions:
<svg viewBox="0 0 100 50" width="100" height="50">
<!-- SVG content -->
</svg>
7. Background Images Not Rendering
CSS background images frequently fail to appear in wkhtmltopdf output, even when foreground images render correctly. This affects gradients, patterns, and image backgrounds.
Symptoms:
Background images show in HTML preview but disappear in PDF. Background colors work, but background-image does not.
Causes:
- Print media mode: wkhtmltopdf renders in print mode by default, which suppresses backgrounds
-
CSS shorthand issues: The
backgroundshorthand may not work; individual properties may be required -
Local file access: Background image paths subject to same security restrictions as
<img>tags
Solutions:
Enable background printing:
wkhtmltopdf --print-media-type --no-background input.html output.pdf
# Or explicitly enable backgrounds
wkhtmltopdf --background input.html output.pdf
Use individual CSS properties instead of shorthand:
/* Instead of: background: url(image.png) no-repeat center; */
background-image: url(image.png);
background-repeat: no-repeat;
background-position: center;
Use print media query to ensure backgrounds render:
@media print {
.header {
background-image: url(header-bg.png) !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
8. Network Timeout and Racing Conditions
When wkhtmltopdf fetches images over HTTP, network latency can cause images to be skipped. The tool may not wait long enough for slow CDNs or high-latency connections.
Symptoms:
Images load inconsistently. Sometimes they appear, sometimes they do not. The same HTML produces different results on different runs.
Root cause:
wkhtmltopdf has timeouts for network requests. If an image response is not received in time, wkhtmltopdf proceeds without it. This is non-deterministic when dealing with variable network conditions.
Solutions:
Increase JavaScript delay (also affects image loading):
wkhtmltopdf --javascript-delay 2000 input.html output.pdf
Use the --load-media-error-handling and --load-error-handling options:
wkhtmltopdf --load-error-handling abort --load-media-error-handling abort input.html output.pdf
Pre-fetch all images before PDF generation and embed as base64.
Evidence from the Developer Community
These issues have accumulated thousands of reports across developer platforms.
Timeline
| Date | Event | Source |
|---|---|---|
| 2015-03-23 | "Images don't appear on the pdf" | Laracasts forum |
| 2016-03-15 | "Images are not rendering properly" | GitHub Issue #2834 |
| 2018-04-16 | "Images randomly not loading" | GitHub Issue #3879 |
| 2018-11-02 | "Images not showing up using PDFKit and WkHTMLtoPDF" | DEV Community |
| 2020-06-01 | Version 0.12.6 disables local file access by default | Release notes |
| 2020-09-21 | "Image not render" with relative paths | GitHub Issue #4832 |
| 2021-01-17 | "Image not displayed - WKHTMLTOPDF" | Google Groups |
| 2023-01-02 | wkhtmltopdf repository archived | GitHub |
| 2023-01-06 | "Images missing in PDF" - Frappe community solution | Frappe Forum |
Community Reports
"I was able to get the style sheets to work using absolute URLs, but have not been able to get the images to show."
— Stack Overflow, 12 years of views"The image gets rendered properly in the .html file, but when converting to pdf using wkhtmltopdf, the image is not shown in the pdf file (just a blank line instead). There are no errors in the cmd output."
— GitHub Issue #4723"When PDF files are generated the images in header are not shown. Cause: Frappe framework uses a library called wkhtmltopdf to generate PDF files."
— Frappe Forum, 2023
Root Cause Analysis
wkhtmltopdf's image rendering problems stem from architectural limitations:
Abandoned Qt WebKit engine: The rendering engine has not been updated since 2015. Modern image formats, network protocols, and CSS features are unsupported.
Security-first breaking changes: The 0.12.6 security update broke existing applications without clear migration paths. Documentation was sparse.
Inconsistent path resolution: No standardized approach to handling relative paths, leading to unpredictable behavior across environments.
Outdated SSL/TLS stack: The Qt libraries linked by wkhtmltopdf cannot negotiate modern TLS connections required by most CDNs.
No maintainer support: With the project archived, these issues will never receive fixes. Workarounds are the only option.
A Different Approach: IronPDF
For applications where image rendering reliability is critical, IronPDF provides an alternative based on embedded Chromium rather than Qt WebKit. This architectural difference eliminates the image rendering issues documented above.
Why IronPDF Handles Images Correctly
IronPDF uses the same rendering engine as Google Chrome. Images that display in Chrome will display in IronPDF-generated PDFs:
- Local file access: Works without special flags; no security-related breaking changes
- Path resolution: Consistent with browser behavior; relative paths work as expected
- HTTPS support: Modern TLS 1.2/1.3 with proper certificate validation
-
Base64 images: Full support for data URIs in both
<img>tags and CSS backgrounds - SVG rendering: Chromium's SVG implementation handles complex paths, clip-paths, and embedded images
- Background images: Print media emulation with proper background rendering
- Network handling: Chromium's robust network stack with configurable timeouts
Code Example: Reliable Image Rendering
using IronPdf;
public class ReliableImagePdf
{
public void GeneratePdfWithImages()
{
var renderer = new ChromePdfRenderer();
// Chromium handles all image types correctly
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
.hero {
background-image: url('https://example.com/hero.jpg');
background-size: cover;
height: 300px;
}
.logo-container {
background: url(data:image/svg+xml;base64,PHN2ZyB4bW...) no-repeat;
width: 150px;
height: 50px;
}
</style>
</head>
<body>
<!-- HTTPS images load correctly -->
<img src='https://cdn.example.com/photo.jpg' alt='Photo'>
<!-- Local images work without special flags -->
<img src='file:///var/www/app/images/local.png' alt='Local'>
<!-- Base64 images render in all contexts -->
<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEU...' alt='Inline'>
<!-- SVGs render completely -->
<img src='logo.svg' alt='SVG Logo'>
<!-- CSS backgrounds work -->
<div class='hero'>
<div class='logo-container'></div>
</div>
</body>
</html>";
using (var pdf = renderer.RenderHtmlAsPdf(html))
{
pdf.SaveAs("images-working.pdf");
}
}
}
Code Example: Docker Deployment
IronPDF includes all dependencies, eliminating container configuration issues:
using IronPdf;
public class DockerPdfGenerator
{
public byte[] GenerateInvoicePdf(string htmlContent)
{
// No additional flags or configuration needed
var renderer = new ChromePdfRenderer();
// Works identically on Windows, Linux, macOS, and Docker
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
// Images from any source render correctly
using (var pdf = renderer.RenderHtmlAsPdf(htmlContent))
{
return pdf.BinaryData;
}
}
}
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/publish .
# No wkhtmltopdf installation, no libwkhtmltox.so, no permission issues
ENTRYPOINT ["dotnet", "MyApp.dll"]
API Reference
For image handling and rendering configuration:
- ChromePdfRenderer - Main rendering class
- HTML to PDF Tutorial - Getting started guide
- Docker and Linux Deployment - Container configuration
- Rendering Options - Full configuration reference
Migration Considerations
Licensing
IronPDF is commercial software with per-developer licensing. A free trial is available for evaluation. The cost should be weighed against developer time spent debugging wkhtmltopdf image issues that will never be fixed upstream.
API Differences
Migration from wkhtmltopdf requires code changes:
| wkhtmltopdf | IronPDF Equivalent |
|---|---|
--enable-local-file-access |
Not needed; works by default |
--allow /path/ |
Not needed; paths resolve correctly |
--javascript-delay 2000 |
RenderingOptions.RenderDelay = 2000 |
--background |
Backgrounds render by default |
| External binary installation | NuGet package includes all dependencies |
What You Gain
- Images render consistently across all environments
- No security flag configuration required
- Modern TLS support for HTTPS resources
- Full SVG rendering with Chromium's engine
- CSS background images work correctly
- Base64 data URIs in all contexts
- No version-specific path resolution bugs
What to Consider
- Commercial licensing cost
- Larger deployment size (embedded Chromium)
- Different rendering output (Chromium vs WebKit)
- Learning curve for new API
Conclusion
Image rendering failures in wkhtmltopdf trace back to its abandoned Qt WebKit engine, security model changes, and inconsistent path resolution. With the project archived since January 2023, these issues are permanent. Developers can apply workarounds for specific scenarios, but the underlying problems will never receive fixes. For applications where reliable image rendering matters, migrating to a maintained solution with modern browser engine support eliminates these issues entirely.
Jacob Mellor is CTO at Iron Software and has spent 25+ years developing commercial software, including IronPDF.
References
- Wkhtmltopdf not rendering images - Stack Overflow{:rel="nofollow"} - Original Stack Overflow discussion
- Image not render - Issue #4832{:rel="nofollow"} - Relative path rendering failure
- Images not showing up using PDFKit and WkHTMLtoPDF - DEV Community{:rel="nofollow"} - Base64 workaround solution
- wkhtmltopdf not loading any images - Issue #1883{:rel="nofollow"} - Early reports of image failures
- Images randomly not loading - Issue #3879{:rel="nofollow"} - Network timing issues
- --enable-local-file-access still showing blocked access - Issue #5210{:rel="nofollow"} - Security flag failures
- Base64-encoded Background Image Does Not Render - Issue #2552{:rel="nofollow"} - CSS background image failures
- SVG Image not rendering properly - Issue #1975{:rel="nofollow"} - SVG rendering limitations
- Loading CSS or images with HTTPS - Issue #4462{:rel="nofollow"} - SSL/TLS failures
- wkhtmltopdf background-image not working - Issue #2054{:rel="nofollow"} - Background image rendering
- Not render images and css in docker container - Issue #20{:rel="nofollow"} - Docker deployment issues
- Solution - Images missing in PDF - Frappe Forum{:rel="nofollow"} - Community workaround
- wkhtmltopdf Enable Local File Access Guide{:rel="nofollow"} - Security flag documentation
- wkhtmltopdf GitHub Repository - Archived{:rel="nofollow"} - Project archived January 2, 2023
For IronPDF documentation and tutorials, visit ironpdf.com.
Top comments (0)