Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
PHP cannot convert raw HTML directly to WebP with imagewebp(). The function accepts a GD image, not markup. A reliable pipeline has two stages: render the HTML and CSS with a browser-capable renderer, then open the resulting bitmap in PHP and encode it as WebP. GD can perform the second stage; it is not an HTML layout engine.
The conversion pipeline
A WebP file contains pixels. HTML contains structure, styles and possibly JavaScript. Before PHP can call imagewebp(), a renderer must resolve the page into pixels.
- Render: Use a browser-based service or a headless browser that supports the CSS and JavaScript your page needs. Save a PNG, JPEG or another raster result.
- Load: Open that raster file as a
GdImagewithimagecreatefrompng(),imagecreatefromjpeg()orimagecreatefromwebp(). - Encode: Pass the GD image to
imagewebp(), selecting a quality from 0 to 100, or-1for the documented default of 80. - Verify: Check that the output file exists and is non-empty. PHP documents that the function can return
trueeven when libgd fails to write the image.
Parsing is not rendering. DOMDocument creates a document tree; it does not calculate browser layout or paint pixels. PHP 8.4’s DomHTMLDocument::createFromString() follows the HTML living standard, while DOMDocument::loadHTML() uses HTML 4 parsing rules. Neither function is a screenshot engine.
Check WebP support before writing code
GD’s formats depend on how PHP was built. The PHP manual documents the --with-webp configure switch (from PHP 7.4.0), and gd_info() reports whether WebP support is available.
#1 Best Overall
<?php
$gd = gd_info();
if (empty($gd['WebP Support'])) {
throw new RuntimeException('This PHP GD build has no WebP support.');
}
printf("WebP support: %sn", $gd['WebP Support'] ? 'yes' : 'no');
Run this on the same PHP binary and deployment environment that will process production requests; CLI and web-server PHP installations can use different builds. See the GD installation documentation and gd_info() reference.
Convert a rendered PNG to WebP with PHP
The following script is complete for the encoding stage. It expects that a renderer has already produced rendered-page.png.
<?php
declare(strict_types=1);
$input = __DIR__ . '/rendered-page.png';
$output = __DIR__ . '/rendered-page.webp';
$quality = 82; // 0 = smallest/worst quality, 100 = largest/best quality
if (!is_file($input) || !is_readable($input)) {
throw new RuntimeException("Input image is missing or unreadable: $input");
}
$info = getimagesize($input);
if ($info === false) {
throw new RuntimeException('The input is not a recognized image.');
}
$image = match ($info['mime']) {
'image/png' => imagecreatefrompng($input),
'image/jpeg' => imagecreatefromjpeg($input),
'image/webp' => imagecreatefromwebp($input),
default => throw new RuntimeException('Use a PNG, JPEG or WebP input.'),
};
if (!$image instanceof GdImage) {
throw new RuntimeException('GD could not decode the input image.');
}
if (!imagewebp($image, $output, $quality)) {
imagedestroy($image);
throw new RuntimeException('GD reported an encoding failure.');
}
imagedestroy($image);
if (!is_file($output) || filesize($output) === 0) {
throw new RuntimeException('No usable WebP file was written.');
}
header('Content-Type: image/webp');
readfile($output);
imagewebp() writes to a filename, stream or (when the destination is omitted) the raw response stream. Its documented quality range is 0–100; -1 selects the default quality of 80. The function signature and caveat about trusting the boolean alone are documented in the PHP imagewebp() reference.
Preserve transparency when the source is PNG
GD normally retains an image’s alpha channel when decoding and encoding. If you create a new canvas while resizing or compositing, enable alpha blending deliberately and save the alpha channel before writing:
$canvas = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($canvas, false);
imagesavealpha($canvas, true);
$transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
imagefill($canvas, 0, 0, $transparent);
imagecopyresampled($canvas, $image, 0, 0, 0, 0,
$newWidth, $newHeight, imagesx($image), imagesy($image));
imagewebp($canvas, $output, 82);
For screenshots without transparency, a JPEG or PNG render can be encoded directly without creating a second canvas.
Rank #2
How to render the HTML before PHP
Choose a renderer according to the page rather than assuming that a DOM parser is sufficient.
- JavaScript execution: Pages that depend on client-side rendering, fonts, charts or lazy loading need a real browser engine and an explicit wait condition.
- CSS and layout fidelity: Check support for web fonts, flexbox, grid, pseudo-elements, media queries and print styles.
- Deployment: A local headless browser requires an operating-system package, sandbox configuration and memory; a service moves those responsibilities to an API.
- Throughput: Browser processes consume substantially more CPU and RAM than GD encoding. Reuse workers or queue jobs for batches, and avoid launching a new browser for every request.
- Isolation: Treat untrusted HTML, JavaScript, cookies and network requests as hostile. Use a sandbox, restrict outbound access and separate renderer credentials from your PHP application.
After rendering, pass the resulting file or stream to the GD script above. Do not feed HTML text to imagecreatefrompng(); it expects encoded image bytes.
Or skip the browser setup
ScreenshotNeo provides the rendering stage through one HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page and billing result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor and other MCP clients use take_screenshot, get_page_info and capture_pdf.
Request a WebP render, then give the response bytes to PHP or save them directly:
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. The same endpoint supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, 12 device presets or custom viewports, retina scale, PDF output, custom CSS and JavaScript, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed image links, asynchronous signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work to ease migration.
PHP request
<?php
$endpoint = 'https://api.screenshotneo.com/v1/shot';
$query = [
'access_key' => 'YOUR_API_KEY',
'url' => 'https://stripe.com',
];
$ch = curl_init($endpoint . '?' . http_build_query($query));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 90,
]);
$bytes = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($bytes === false || $status < 200 || $status >= 300) {
throw new RuntimeException($error ?: "Screenshot request failed with HTTP $status");
}
file_put_contents(__DIR__ . '/shot.webp', $bytes);
Python and Node.js alternatives
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)
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}`);
The Free plan includes 1,000 shots per month without a card. Paid plans start at $5 for 3,000 shots; Growth is $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000 and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Quality, size and performance decisions
Pick quality for the image type
- Photographic pages: Start around 75–85 and compare text edges and gradients at the display size.
- UI screenshots: Increase quality when small text, thin borders or icons show ringing; WebP is lossy unless your workflow explicitly requires lossless output.
- Transparent graphics: Verify alpha pixels after conversion, especially around anti-aliased edges.
Measure the resulting file and visual output on representative pages. A higher number is not automatically better if the file must be downloaded frequently.
Control resource use
- Resize in GD only when you need a fixed output dimension; otherwise request the desired viewport from the renderer.
- Use temporary files outside public directories and remove them after a successful response.
- For repeated URLs, cache by URL plus rendering options and a chosen expiration time. Do not cache private pages without including the relevant authentication context in the cache key.
- Queue long full-page captures rather than holding a web request open indefinitely.
Troubleshooting
“Call to undefined function imagewebp()”
GD is missing or the build lacks WebP support. Install/enable GD with WebP support, restart the relevant PHP service, and confirm gd_info()['WebP Support'] in that environment.
The output file is empty or corrupt
Check disk permissions, free space and the source image’s MIME type. Do not rely only on the return value; verify existence and non-zero size, then inspect the file with an image tool.
HTML appears blank or unstyled
The HTML was parsed but never browser-rendered, CSS or fonts were unavailable, or JavaScript had not finished. Use a browser-capable renderer, wait for a selector or network idle, and ensure required assets are reachable.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Content is cut off
A viewport screenshot captures only the viewport. Request a full-page render or set an explicit viewport and height. Long pages may need asynchronous processing and a memory limit review.
Rank #4
Cookies or authenticated content are missing
Provide the renderer’s cookies, headers or Authorization values, and keep credentials out of public URLs and logs. Confirm that the target application accepts those values in the same origin and path.
Different results between local and production
Compare browser version, installed fonts, timezone, geolocation, device scale and network access. Pin these settings where the renderer permits it, and record the options alongside each generated asset.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.FAQ
Can CSS alone be converted by GD?
No. CSS influences a layout only when a rendering engine applies it to HTML. GD starts with pixels.
Does WebP always make a screenshot smaller than PNG?
Not necessarily. Compare representative files at an acceptable quality; simple UI imagery can sometimes compress efficiently as PNG.
Should I use DOMDocument::loadHTML() as a sanitizer?
No. Its HTML 4 parsing behavior differs from modern browser parsing, and parsing is not a security boundary. Sanitize untrusted markup with a purpose-built policy and isolate rendering.
Can imagewebp() stream directly to the browser?
Yes. Omit the destination and send the appropriate Content-Type, but buffering to a checked file is safer when you need to detect write failures or cache the result.
Frequently Asked Questions
What is the minimum PHP requirement for WebP output?
The deployed GD build must include WebP support; verify it with gd_info() rather than relying on the PHP version alone.
Why does my HTML-to-WebP script ignore JavaScript?
GD and DOM APIs do not execute JavaScript. Render the page in a browser-capable engine first, then encode the resulting pixels.
The Bottom Line
Use a browser renderer for HTML and CSS, then use PHP GD’s imagewebp() for the pixel-to-WebP step. Verify GD capability and the written file, and choose rendering settings that match your page’s JavaScript, fonts, authentication and full-page requirements.
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.

