Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Wkhtmltoimage I386 Laravel Package

h4cc/wkhtmltoimage-i386

Static i386 binaries of wkhtmltoimage from the wkhtmltopdf project, installable via Composer. Creates the binary in vendor/h4cc/wkhtmltoimage-i386/bin and symlinks it into vendor/bin for easy command-line use.

View on GitHub
Deep Wiki
Context7

Getting Started

This package ships no PHP code — it is a Composer-installed static wkhtmltoimage binary (Qt WebKit 0.12.4, i386). Treat it as a system dependency, not a library.

  1. Confirm your architecture first. The -i386 build only runs on 32-bit Linux, or 64-bit Linux with 32-bit compat libraries (glibc:i386, libstdc++:6:i386, etc.). Almost all modern servers are x86_64; if file vendor/bin/wkhtmltoimage-i386 reports ELF 32-bit, don't assume it runs. Prefer h4cc/wkhtmltoimage-amd64 on 64-bit hosts, or skip both and install wkhtmltopdf from your distro.
  2. Install:
    composer require h4cc/wkhtmltoimage-i386:^0.12.4
    
    The binary lands at vendor/h4cc/wkhtmltoimage-i386/bin/wkhtmltoimage-i386, with a symlink in vendor/bin/.
  3. Smoke-test the binary directly before writing any PHP:
    vendor/bin/wkhtmltoimage-i386 --version
    vendor/bin/wkhtmltoimage-i386 --width 800 https://example.com /tmp/example.png
    
    If this fails, nothing in Laravel will work — fix the runtime first.
  4. First use case: a "preview image" endpoint — render a Blade view to HTML, convert it to PNG, cache it, and serve it. The simplest reliable path is to wrap it with barryvdh/laravel-snappy (which provides the Knp\Snappy\Image API) rather than shelling out by hand:
    // config/snappy.php
    'image' => [
        'binary'  => base_path('vendor/h4cc/wkhtmltoimage-i386/bin/wkhtmltoimage-i386'),
        'options' => ['width' => 1200, 'format' => 'png'],
    ],
    
    $image = App::make('snappy.image');
    $image->generate(view('reports.invoice', $data)->render(), storage_path("app/previews/{$id}.png"));
    

Implementation Patterns

Render-then-convert, always. wkhtmltoimage has no way to run Laravel templates; render the Blade view to a string (or a temp .html file) first:

$html = view('reports.dashboard', $payload)->render();
$tmp  = tempnam(sys_get_temp_dir(), 'wk').'.html';
file_put_contents($tmp, $html);

$proc = Process::fromShellCommandline(
    escapeshellarg(config('snappy.image.binary')).
    ' --width 1200 --format png --quality 90 --quiet --javascript-delay 500'.
    ' - '.escapeshellarg($out)
);
$proc->setTimeout(30)->run();

if (!$proc->isSuccessful()) {
    throw new RuntimeException($proc->getErrorOutput());
}

Wrap it in a dedicated service. Inject options from config so tests can stub the wrapper, and so swapping to Chrome headless later is a one-class change:

final class HtmlToImage
{
    public function __construct(private array $options) {}

    public function fromHtml(string $html): string { /* process, return raw bytes */ }

    public function toStorage(string $html, string $path): string { /* write to Storage::disk('public') */ }
}

Always queue it. Conversion takes 1–5 seconds and pins CPU. Use a ShouldBeQueued job with a unique key derived from sha1($html.$options); cache the resulting path so repeated requests are served from disk, not from the binary.

Options that matter day-to-day:

Need Flag
Screenshot width / height --width 1200, --height 800, --crop-h 800, --crop-w 1200
Fixed viewport zoom --zoom 0.8
Wait for JS chart libs --javascript-delay 1000
Ignore 404 assets --load-error-handling ignore
JPEG quality --format jpg --quality 90
Suppress noise --quiet
Allow local assets (default in 0.12.4) --enable-local-file-access

Integration with Laravel storage. Write to storage/app/public/previews/x.png, symlink via php artisan storage:link, and serve with Storage::disk('public')->url(...). For private previews, stream through a controller with a signed route.

Assets and fonts. Inline CSS and use data: URIs for images where possible. If you reference file:// paths or public_path(), pass the absolute path and ensure your PHP process can read it. Fonts must be installed system-wide (fonts-liberation, fonts-dejavu) — otherwise text renders as tofu boxes.

Gotchas and Tips

  • The i386 trap. A missing 32-bit loader produces the misleading No such file or directory error even though the file exists. Debug with file <binary> and ldd <binary>; install libc6:i386 libstdc++6:i386 (Debian/Ubuntu) or use the -amd64 package. Don't try this on Alpine/musl — it's glibc-linked.
  • It's frozen at 0.12.4 (Jan 2018). Qt WebKit in this version has known, unpatched CVEs and mediocre modern CSS support (no CSS grid, no flexbox quirks, no modern JS). For any new project, prefer headless Chrome (spatie/browsershot) or mpdf for PDFs; keep this only for legacy compatibility.
  • Security — never feed it untrusted HTML verbatim. wkhtmltoimage will happily fetch file:///etc/passwd, hit http://169.254.169.254, and download arbitrary URLs. Disable with --disable-local-file-access --disable-javascript for user-generated content, sandbox the process (dedicated user, no network if possible), and never pass raw user HTML without sanitising.
  • Exit code 0 lies. wkhtmltoimage often prints warnings to stderr while returning success. Check that the output file exists and has non-zero size; also treat empty PNGs as failures.
  • Hangs are common. Slow remote assets or a JS setInterval keep the renderer alive forever. Always set a Process timeout (15–30s) and pass --javascript-delay; consider --no-stop-slow-scripts only if you actually need it.
  • The vendor/bin symlink isn't guaranteed if the consumer overrides Composer's bin-dir. Reference the full path under vendor/h4cc/... in config whenever possible.
  • Headless servers. Usually fine, but minimal containers can fail without an X server; xvfb-run -a around the binary is the classic workaround, and missing font packages are the next most common cause of empty/garbled output.
  • Extension point is limited. The only "extension" is the CLI: write a wrapper around the process invocation, centralise flags in config/snappy.php, and keep a thin interface so you can migrate to Chrome headless without touching call sites.
  • Alternatives to name in a review: h4cc/wkhtmltoimage-amd64 (same age), distro wkhtmltopdf package (patched builds), browsershot (Chrome, faster, better CSS), or a hosted screenshot API for serverless/Vapor deployments where 32-bit binaries cannot run at all.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums