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

Short answer: first identify the PDF renderer. Dompdf does not run ordinary browser JavaScript to build a page before layout; its JavaScript setting embeds scripts for execution by a PDF viewer. If your HTML must execute external or inline JavaScript before capture, use a renderer that documents page execution—such as wkhtmltopdf—then configure resource access and a readiness delay appropriate to the page.

This distinction prevents the most common failed fix: enabling a PDF JavaScript option and expecting a JavaScript-populated dashboard, chart, or API response to appear in the generated file.

Browser JavaScript and PDF JavaScript are different

There are two separate operations that developers often call “JavaScript support”:

  • Page execution: a browser engine loads the HTML, fetches external scripts, runs them, waits for asynchronous work, and then captures the resulting DOM and styles.
  • PDF-viewer scripting: JavaScript is stored inside the PDF and may run later when a compatible PDF application opens it.

Dompdf’s Options documentation explicitly notes that its JavaScript option is “PDF-based JavaScript to be executed by the PDF viewer, not browser-based JavaScript executed by Dompdf.” Therefore, switching that option on will not make a React application, chart library, or script that inserts text execute during Dompdf rendering. Dompdf is a PHP HTML/CSS renderer, not a general-purpose browser automation engine; its repository describes its supported rendering model at github.com/dompdf/dompdf.

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

If your source HTML is already fully populated on the server, Dompdf may still be suitable. If visible content is created only after JavaScript runs, choose a renderer with documented page execution or render the data into HTML on the server before handing it to Dompdf.

Choose the rendering approach before changing PHP options

Use Dompdf for server-rendered HTML

Use Dompdf when PHP can produce the final text, tables, images, and CSS without requiring browser JavaScript. This is usually the simplest deployment and avoids running an embedded browser. Do not treat isJavascriptEnabled as a switch for executing external page scripts.

Use a JavaScript-capable renderer for dynamic pages

wkhtmltopdf’s usage documentation describes JavaScript enabled by default, a --javascript-delay control, and an option to run an additional script after page load. Its PHP binding exposes corresponding loading and JavaScript controls in the object constructor documentation at php.net/manual/en/wkhtmltox-pdf-object.construct.php.

This is a possible path, not a blanket recommendation. The reviewed command-line documentation is on the project’s mutable master branch and does not establish the maintenance status of every binary, browser-engine age, or compatibility with your PHP wrapper. Record and verify the exact binary, wrapper, and PHP versions deployed in your environment.

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.

Consider server-side rendering instead

If JavaScript only formats values or displays data that PHP already knows, render those values in PHP and pass the resulting HTML to a non-browser PDF library. This reduces network, timing, and security variables. It does not help when the page depends on browser APIs, client-only authentication, or third-party scripts that must execute.

A minimal diagnostic page

Before debugging a production application, reduce the problem to one external script that changes visible text. Save this as js-check.html:

<!doctype html>
<html>
<body>
  <div id="status">Not executed</div>
  <script src="https://example.com/your-test.js"></script>
</body>
</html>

Have the script set document.getElementById('status').textContent to a known value. If a renderer outputs “Not executed,” the issue is renderer capability, script loading, or readiness—not a CSS detail in your application. Use a URL you control for the test; do not infer success from a script that has failed silently.

Generating a PDF with wkhtmltopdf

Command-line baseline

A basic invocation is:

wkhtmltopdf --enable-javascript --javascript-delay 2000 https://your-site.example/report.html report.pdf

--enable-javascript makes the intent explicit, although the command-line documentation says JavaScript is enabled by default. The documented default delay is 200 milliseconds; that is a configuration default, not a guarantee that an application will be ready in that time. A page that waits for an API, fonts, images, or a chart may require a longer delay or a readiness signal.

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

Run a post-load script

wkhtmltopdf also documents injecting an additional script after the page loads. The exact wrapper spelling varies, so check the installed binary’s help output and your PHP binding version. Use this only for a deterministic finalization action, such as adding a print class; it cannot repair an inaccessible external script.

Wait for readiness, not an arbitrary number

A fixed delay is a useful fallback, but it is less reliable than making the page expose a completion condition. A practical pattern is to have your application add a marker such as window.pdfReady = true after data and visual components finish. If your selected wrapper cannot wait for that marker directly, use a conservative delay and ensure the page’s requests have completed before the capture window closes. Test under the slowest realistic network and API response conditions.

PHP integration checklist

  1. Identify the actual engine. Record whether your package invokes Dompdf, wkhtmltopdf, or another binary. “PHP PDF library” is not specific enough to determine JavaScript behavior.
  2. Verify the executable. Log the binary path and version used by the web process, not only the version installed in your shell.
  3. Configure JavaScript deliberately. In wkhtmltopdf or its wrapper, confirm JavaScript has not been disabled and set a delay appropriate to your page.
  4. Make resources reachable. Check DNS, outbound firewall rules, TLS certificates, URL resolution, authentication, cookies, custom headers, and redirects from the renderer’s host.
  5. Capture diagnostics. Preserve stderr and wrapper warnings. A PDF can be produced even when a script, image, or stylesheet failed to load.
  6. Test the smallest page first. Prove one external script can change visible text, then add your framework, API calls, charts, and authentication one dependency at a time.

PHP wrappers often rename command-line switches. Map each wrapper option to the installed binary’s documentation rather than copying a setting from a different package.

External-resource failures and their fixes

Incorrect URL resolution

Relative script URLs depend on the document base URL. A local file may resolve /js/app.js differently from an HTTPS page. Prefer an explicit, reachable URL while diagnosing and inspect redirects.

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.

Authentication and cookies

Your browser session may have cookies or authorization headers that the rendering process does not possess. Supply the required cookies or headers through the wrapper’s documented loading options, or expose a short-lived, access-controlled export endpoint. Never put long-lived secrets in a public PDF URL.

Network and TLS restrictions

The renderer runs where PHP runs, often inside a container or queue worker with different DNS, proxy, firewall, and certificate settings. Test connectivity from that runtime. A script that loads on your laptop can fail on the server without producing an obvious application exception.

Local files

Local-file access is a security-sensitive capability. Enable it only when required, restrict the files available to the renderer, and do not grant broad access merely to make one stylesheet work.

Content-security and browser assumptions

Some applications require modern browser APIs, service workers, or JavaScript features unavailable in the engine bundled with a renderer. If a page depends on current Chromium behavior, an older WebKit-based tool may not reproduce it. Confirm compatibility with the exact renderer version you deploy.

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

Dompdf security and resource controls

Dompdf’s current Options source treats remote resource access as a security-sensitive setting and documents remote access as disabled by default in that source. Exact defaults can differ across historical releases, so check your installed version. Its security guidance recommends validating resource references and avoiding embedded script support for untrusted documents.

Apply the same principle to any JavaScript-capable renderer: accept only approved resource hosts, isolate rendering workers where possible, limit execution time and memory, and sanitize user-controlled HTML. Do not enable server-side embedded PHP execution as a workaround for browser JavaScript; PHP execution and page JavaScript are different problems.

Common symptoms and troubleshooting

Symptom Likely cause Fix
PDF contains the initial placeholder text Renderer does not execute browser JavaScript, or capture occurred before execution. Use a page-executing renderer, confirm JavaScript is enabled, and increase or redesign the readiness wait.
Dompdf option appears enabled but nothing changes Its option targets scripts run by the PDF viewer. Move rendering server-side or switch to a renderer that documents page execution.
External script works in a browser but not on the server DNS, firewall, TLS, authentication, cookies, or headers differ. Test from the renderer runtime and configure the required credentials or network access.
Charts are blank or partly drawn Asynchronous data or font/image loading finished after capture. Expose a page-ready marker, wait for all data and assets, and test slow responses.
Local stylesheet cannot be loaded Local-file access is disabled or the path is outside permitted directories. Use an approved HTTPS resource or narrowly configure local-file permissions.
Wrapper rejects a documented flag Wrapper and binary versions use different names or capabilities. Check the wrapper manual, binary help output, and deployed versions together.
PDF generation hangs A script, request, or redirect never completes. Set process timeouts, inspect network logs, and remove or bound long-running requests.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean screenshot or PDF of a URL rather than maintaining a browser-rendering stack, ScreenshotNeo provides a single HTTP request and an MCP server for AI agents. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

For API options, authentication, PDF parameters, asynchronous jobs, and the full 63-option surface, see the ScreenshotNeo documentation.

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

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets and custom viewports, retina scale, PDF paper and page controls, HTML/CSS-to-image, custom CSS and JavaScript, clicks, selector or network-idle waits, ad/tracker/request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, 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.

An MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. 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.

Performance, reliability, and cost decisions

  • Readiness: waiting longer increases reliability for slow pages but also increases per-job latency. Prefer an explicit application-ready condition where your renderer supports one.
  • Resource count: every external script, font, image, and API call adds another failure point. Bundle or serve stable assets where practical.
  • Isolation: browser-capable rendering consumes more CPU and memory than static HTML conversion. Use queue workers and enforce timeouts for untrusted or unpredictable pages.
  • Caching: cache immutable assets and generated PDFs only when their data and authorization rules permit it. Do not reuse a personalized PDF for another user.
  • Billing: with ScreenshotNeo, only clean shots are billed; failed loads, blank pages, bot checks, CAPTCHAs, timeouts, and cache hits are reported as non-billed outcomes.

Which path should you use?

Requirement Practical choice
PHP-generated HTML with no client-side rendering Dompdf or another static HTML/CSS renderer.
Existing page must execute JavaScript before capture A renderer that documents page execution, such as wkhtmltopdf, after version and compatibility checks.
Only a URL screenshot or PDF is needed ScreenshotNeo to avoid operating the browser setup.
Untrusted HTML or URLs Strict host/resource validation, sandboxing, timeouts, and least-privilege file access regardless of renderer.

Frequently Asked Questions

Does enabling Dompdf’s JavaScript option execute external scripts?

No. Dompdf documents that option as JavaScript for the resulting PDF viewer, not browser JavaScript executed during HTML rendering.

Is wkhtmltopdf’s 200 ms delay enough for every page?

No. Two hundred milliseconds is the documented default. API calls, fonts, images, and client-side applications may require a longer or condition-based readiness strategy.

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

Can I solve this by enabling PHP execution in the PDF library?

No. Server-side PHP execution and browser-side JavaScript execution are separate mechanisms; enabling embedded PHP for untrusted HTML also creates a serious security risk.

The Bottom Line

Use Dompdf only when the HTML is already complete or can be rendered server-side. For JavaScript-populated pages, use a renderer that truly executes page scripts, verify external-resource access, and wait for a real ready state. If you only need a URL capture, ScreenshotNeo removes the browser infrastructure and bills only clean shots.

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.