Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use JavaScript when the HTML is already visible in a browser; use a headless browser when PHP must render the page on a server. In the browser, html2canvas reconstructs a selected element as a canvas, then the Canvas API exports it as image/jpeg. In PHP, Spatie Browsershot drives Puppeteer and headless Chrome to render HTML or a URL before saving an image. PHP’s imagejpeg() only encodes an existing GD image—it does not lay out HTML or execute JavaScript.

Choose the rendering method first

Requirement Best fit Why
A visitor clicks a button and downloads one element JavaScript plus html2canvas No server browser is required; capture runs in the user’s browser.
PHP must generate and store an image Browsershot with Puppeteer and headless Chrome A real browser engine can run page JavaScript and reproduce browser layout more closely.
You already have a GD image resource imagejpeg() It encodes an existing image at a chosen quality.
You need a document, not browser pixels dompdf PDF output dompdf is an HTML-to-PDF renderer; its JavaScript option does not execute JavaScript like a browser.

These approaches are not interchangeable. html2canvas recreates a representation from DOM properties it understands, so unsupported CSS can differ from the pixels on screen. Browsershot has the operational cost of Node, Puppeteer, Chrome, fonts, permissions and network access, but is the appropriate PHP-side option when browser behavior matters.

Generate a JPEG in browser JavaScript

1. Load html2canvas

Install or load the html2canvas version approved for your application. The library accepts a DOM element and returns a Promise for a canvas. It does not take a literal screenshot of the operating-system window; it builds an image from the DOM.

2. Capture an element and download it

async function downloadJpeg(element) {
  const canvas = await html2canvas(element, {
    scale: window.devicePixelRatio,
    backgroundColor: '#ffffff'
  });

  canvas.toBlob((blob) => {
    if (!blob) {
      console.error('JPEG export failed');
      return;
    }
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'capture.jpg';
    link.click();
    URL.revokeObjectURL(url);
  }, 'image/jpeg', 0.92);
}

downloadJpeg(document.querySelector('#capture'));

The second argument to toBlob() selects JPEG; the quality value is a number from 0 to 1, where higher values generally retain more detail and produce larger files. toBlob() avoids constructing a large base64 data URL in memory. Check that the callback receives a non-null Blob before creating the download.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for content before capturing

Run the capture only after web fonts, images and application data have finished loading. For image-heavy pages, await each image’s decode() where available, or listen for its load event. If a framework renders the target asynchronously, call downloadJpeg() after the render state is complete.

Control size, crop and unwanted controls

  • Resolution: Set an explicit scale. Device-pixel-ratio scaling can make output sharper on high-DPI displays, while larger scales consume more memory.
  • Crop: Pass x, y, width and height when only a region is needed.
  • Exclude UI: Add data-html2canvas-ignore to buttons, toolbars or other elements that should not appear.
  • Background: JPEG has no alpha channel. Set an intentional background, as in the example, or use PNG/WebP when transparency must survive.

Capture the full page or a specific element

Pass the element you actually need rather than document.body. A focused target reduces memory use and prevents navigation controls from entering the image. Full-page captures require dimensions large enough for the complete content and can fail or become expensive on very tall documents.

Browser-side limitations you must plan for

Cross-origin images and canvas security

An image loaded from another origin can taint the canvas. Once tainted, reading or exporting pixels may throw a security error. html2canvas documents a proxy option for remote content, but that proxy must be implemented and secured by you; the library cannot bypass browser cross-origin policy. Configure the remote server’s CORS headers where possible, or serve assets from the same origin.

Iframes

Same-origin iframes can be rendered recursively. Cross-origin frames cannot be inspected because browser security prevents access to their document. A sandboxed frame without allow-same-origin has the same practical restriction.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

CSS and browser differences

Test representative layouts: filters, complex effects, pseudo-elements, embedded fonts and newer CSS may not be supported identically. The result is a DOM reconstruction, not a guarantee of pixel parity with Chrome, Safari or Firefox.

Generate a JPEG on the server with PHP and Browsershot

Why use a headless browser

Choose Browsershot when the server must render a URL or arbitrary HTML, page JavaScript must run, or the output should reflect browser layout without depending on a visitor’s device. Browsershot controls Puppeteer, which controls headless Chrome.

Minimal PHP example

<?php
use SpatieBrowsershotBrowsershot;

Browsershot::html('<h1>Hello world</h1>')
    ->save('/path/to/capture.jpg');

Install and configure the Browsershot version, Node.js, Puppeteer and Chrome according to that version’s documentation. Confirm the executable path, filesystem permissions, installed fonts and outbound resource access in the deployment environment. The exact image-format controls and runtime switches vary by installed version, so verify them before standardizing production code.

Render a URL or application HTML

For a URL, use the corresponding Browsershot URL method in your installed release; for generated markup, pass the complete HTML string. Make authentication, cookies, headers and private network access explicit. Never assume a server can reach resources that are available only from a developer workstation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What PHP’s imagejpeg() can and cannot do

<?php
$image = imagecreatetruecolor(1200, 630);
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white);

header('Content-Type: image/jpeg');
imagejpeg($image, null, 90);
imagedestroy($image);

imagejpeg() creates a JPEG from a GD image. It accepts a GD image, an optional filename or stream, and a quality from 0 to 100; if quality is omitted, the underlying JPEG library’s default is used (approximately 75). Omitting the filename writes the image to the response, so send the Content-Type: image/jpeg header first.

To convert HTML, you still need a renderer such as a browser. GD cannot parse HTML, apply CSS layout or execute JavaScript. A typical pipeline is therefore: render HTML with Browsershot, then use an image operation only if you need additional GD processing.

Why dompdf is not a browser screenshot solution

dompdf is designed to render HTML into PDF. Its documented JavaScript setting does not make it parse JavaScript like a web browser, and its GD-related PDF backend does not establish arbitrary HTML-to-JPEG output. Use it when PDF is the intended deliverable and its CSS and scripting limitations are acceptable. Do not enable embedded PHP for untrusted documents; that option can create a system-exploitation risk.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One request returns PNG, JPEG, WebP or PDF, while its capture pipeline accepts consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets before the shot. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a JPEG, call the API as shown in the ScreenshotNeo documentation:

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
curl -G "https://api.screenshotneo.com/v1/shot" 
  -d access_key=YOUR_API_KEY 
  --data-urlencode url=https://stripe.com 
  -o shot.webp

Change the output extension and requested format parameters as documented when you need JPEG rather than WebP. ScreenshotNeo also supports full-page and selector captures, device presets or custom viewports, retina scale, custom CSS and JavaScript, click and wait conditions, blocked requests, headers, cookies, user agents, timezone, geolocation, resizing, chosen cache TTLs, signed links, asynchronous webhooks, bulk capture and a usage API. Every feature is on every plan. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to start.

Equivalent Python and Node.js calls

If your application is not PHP, the same endpoint works directly:

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(`Screenshot failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting checklist

The JPEG is blank or missing content

  • Wait for fonts, images and asynchronous rendering before capture.
  • Check that the selector exists and has non-zero dimensions.
  • For Browsershot, verify Chrome, fonts, permissions, executable paths and network access.

Export throws a security or tainted-canvas error

Find cross-origin images, fonts or frames. Serve them with appropriate CORS headers, move them to the same origin, or implement a carefully controlled proxy. Cross-origin iframes remain inaccessible to browser JavaScript.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The result looks different from the page

Review html2canvas’s supported CSS features, reduce the capture to a known target, and test the exact browsers you support. Use Browsershot when executing page JavaScript or browser-level layout fidelity is required.

The file is too large or memory usage spikes

Capture an element instead of the entire body, reduce scale and dimensions, and prefer toBlob() over a base64 data URL. Lower JPEG quality only after checking that text and fine details remain readable.

Transparency disappeared

That is expected for JPEG. Set a background before serialization or choose PNG/WebP if transparent pixels are required.

Frequently Asked Questions

Can I convert HTML to JPEG with PHP alone?

Not with PHP’s GD encoder alone. PHP needs an HTML renderer, such as a configured headless browser, before imagejpeg() can encode the rendered pixels.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does html2canvas capture an exact screenshot?

No. It reconstructs an image from DOM information and may differ where CSS, fonts, cross-origin resources or frames are unsupported.

Which option should generate images without a visitor’s browser?

Use Browsershot with Puppeteer and headless Chrome, or call a screenshot API such as ScreenshotNeo.

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.