Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Short answer: you cannot make inline JavaScript run inside Dompdf. Dompdf’s documentation states, “Reminder: Dompdf does not run JavaScript.” Build the final, JavaScript-generated HTML first, then pass that completed markup to Dompdf. If the PDF genuinely depends on browser execution, use a browser-backed renderer or service and plan for its separate runtime. Also distinguish scripts that run during conversion from JavaScript actions stored inside the finished PDF; they are different requirements.
First decide which kind of JavaScript you need
“Add inline JavaScript” can describe two unrelated goals:
- Run a script before or during rendering. For example, JavaScript fetches chart data, inserts totals, or changes the DOM before the PDF is produced.
- Embed a JavaScript action in the PDF file. This could run when a viewer opens the document or clicks a PDF control. Support depends on the PDF library and the target viewer.
The PHP libraries discussed here document HTML/CSS ingestion and PDF output, not a universal way to execute arbitrary page scripts or embed portable PDF actions. Confirm the exact library version and PDF viewer requirements before implementing the second case.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWhy inline scripts do not run in Dompdf
Dompdf is a PHP HTML/CSS renderer, not a web browser. Its tutorial, dated January 25, 2026, explicitly says it does not run JavaScript and expects fully populated HTML. A script such as <script>document.querySelector('#total').textContent = '42';</script> will not update the document while render() runs.
#1 Best Overall
The reliable pattern is therefore:
- Calculate values and perform dynamic work in PHP, or execute JavaScript in a real browser before conversion.
- Render a complete HTML string or server-side template.
- Give that final string to Dompdf.
- Render and stream or save the PDF.
Recommended Dompdf workflow: prepare HTML first
Install the library
Install Dompdf with Composer in your application:
composer require dompdf/dompdf
Use a supported PHP version for the Dompdf release you install, and review that release’s documentation for compatibility and configuration details.
Generate the dynamic values in PHP
<?php
require __DIR__ . '/vendor/autoload.php';
use DompdfDompdf;
use DompdfOptions;
$items = [
['name' => 'Keyboard', 'price' => 79.00, 'quantity' => 1],
['name' => 'Mouse', 'price' => 29.00, 'quantity' => 2],
];
$total = 0.0;
foreach ($items as $item) {
$total += $item['price'] * $item['quantity'];
}
function e(string $value): string {
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$rows = '';
foreach ($items as $item) {
$line = $item['price'] * $item['quantity'];
$rows .= '<tr>'
. '<td>' . e($item['name']) . '</td>'
. '<td>' . (int) $item['quantity'] . '</td>'
. '<td>$' . number_format($line, 2) . '</td>'
. '</tr>';
}
$html = '<!doctype html>
<html><head><meta charset="utf-8">
<style>body{font-family:DejaVu Sans,sans-serif}table{width:100%;border-collapse:collapse}td,th{border:1px solid #ccc;padding:8px}</style>
</head><body>
<h1>Invoice</h1>
<table><thead><tr><th>Item</th><th>Qty</th><th>Line total</th></tr></thead>
<tbody>' . $rows . '</tbody></table>
<p>Total: $' . number_format($total, 2) . '</p>
</body></html>';
$options = new Options();
$options->set('isRemoteEnabled', false);
$dompdf = new Dompdf($options);
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$dompdf->stream('invoice.pdf', ['Attachment' => true]);
There is no script tag in this example because PHP has already produced the value that the PDF needs. If you use a template engine, render the template to a string first, then call loadHtml() with that string.
Use JavaScript only during a browser pre-render step
If an existing page computes content in JavaScript, load that page in a real browser, wait until the application has finished its work, extract the resulting HTML, and then send the extracted markup to Dompdf. The browser step is responsible for JavaScript; Dompdf is responsible only for converting the completed HTML. Preserve the final DOM state rather than the original source that still contains placeholders.
Free tools Windows power users keep installed
One-click scans. No signup required.
mPDF: HTML input, but not a promise of page-script execution
mPDF accepts markup with WriteHTML() and writes a PDF with Output():
Rank #2
<?php
require __DIR__ . '/vendor/autoload.php';
$mpdf = new MpdfMpdf();
$html = '<h1>Report</h1><p>This text was completed by PHP before conversion.</p>';
$mpdf->WriteHTML($html);
$mpdf->Output('report.pdf', MpdfOutputDestination::DOWNLOAD);
Its project README describes CSS support as dated and recommends headless Chrome when you need state-of-the-art CSS support or want to mirror an existing page. That recommendation concerns browser rendering and CSS fidelity; it is not evidence that arbitrary page scripts execute inside mPDF. Treat JavaScript as a separate browser requirement.
mPDF’s manual warns against accepting outside HTML/CSS without careful vetting. Sanitize and constrain all user-controlled input before calling WriteHTML().
Choosing a renderer
| Requirement | PHP library such as Dompdf or mPDF | Browser-backed renderer |
|---|---|---|
| JavaScript execution | Do not assume it; Dompdf documents none. | Uses an external browser engine or service, so page scripts can be part of rendering. |
| CSS and page behavior | Implements a library-specific HTML/CSS subset; mPDF calls its CSS support dated. | Closer to what a current browser displays, subject to engine version and wait conditions. |
| Operations | Runs in PHP without a separate browser process. | Requires installing, patching, launching, and securing a browser engine or reaching a service. |
| PDF actions, accessibility and conformance | Check the exact package and version. | Check the selected service or automation stack; capabilities vary. |
wkhtmltopdf is a separate Qt WebKit-based approach. Its upstream project was archived in January 2023, so it should not be treated as a current default without accepting engine-age and maintenance risks. Comparisons of PHP PDF libraries and browser-delegating renderers are version snapshots, not universal benchmarks.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Security and data handling
Escape values, not markup by accident
Escape text inserted into templates with htmlspecialchars(). If users can supply markup, use an allowlist sanitizer and reject scripts, event-handler attributes, dangerous URLs, and unexpected CSS. Do not confuse browser sanitization with a safe server-side PDF pipeline.
Control remote resources
Images, fonts, stylesheets, and background requests can expose internal network locations or leak data. Disable remote loading unless it is required, allowlist hosts when it is required, and set explicit timeouts. Dompdf’s documented guidance also calls for validation, escaping, whitelisting, and caution with unknown remote resources.
Keep secrets out of HTML
Never place API keys, session cookies, or private tokens in markup sent to a renderer. Fetch protected data in PHP, validate it, and inject only the fields the document needs.
Common failures and precise fixes
The PDF shows placeholders
Cause: a script was expected to replace them, but the renderer never executes JavaScript. Fix: calculate the values in PHP, or pre-render the page in a browser and pass the resulting HTML to the PDF library.
The PDF is blank or missing images
Cause: invalid or empty HTML, inaccessible remote assets, relative paths, or blocked remote loading. Fix: log the final HTML, use absolute or correctly rooted asset paths, verify permissions, and configure remote access only for trusted resources.
Rank #4
Modern layout looks wrong
Cause: the library implements only part of browser CSS. Fix: simplify to supported CSS, use print-specific styles, or move to a maintained browser-backed renderer when pixel fidelity matters.
User content creates unexpected output
Cause: unsanitized HTML or CSS. Fix: apply an allowlist sanitizer before rendering, escape plain text, and reject external URLs and dangerous attributes.
Asynchronous data is absent in a browser workflow
Cause: capture happened before network requests or client rendering completed. Fix: wait for an application-specific ready marker or a completed request state, then verify the DOM before conversion. The exact waiting API is renderer-specific; do not assume a Dompdf setting can provide it.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsPerformance, reliability and cost decisions
- Prefer server-side preparation when data is already available in PHP. It avoids starting a browser and makes output deterministic.
- Reuse templates and CSS and avoid embedding unnecessarily large images or fonts.
- Measure memory and page count for large documents; split very large jobs when your library’s limits require it.
- Make browser jobs observable: record the URL, renderer version, wait condition, elapsed time, and failure reason without logging secrets.
- Pin versions and test representative pages. CSS, fonts, JavaScript frameworks, and browser engines change independently.
A PHP-only path usually has fewer moving parts. A browser-backed path can reproduce a JavaScript application more faithfully but adds an external runtime or service, patching, capacity planning, and network failure modes.
Or skip the browser setup
If your source is a public or reachable web page and you would rather use a managed browser capture, ScreenshotNeo provides a website screenshot API and MCP server. 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, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its API can return PNG, JPEG, WebP, or PDF, while its MCP tools let Claude, Cursor, or another MCP client call take_screenshot, get_page_info, and capture_pdf.
For API details, see the ScreenshotNeo documentation. A basic request is:
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 includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, click and wait conditions, request and resource blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, usage data, and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which can simplify migration.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start.
Implementation checklist
- Identify whether you need pre-conversion JavaScript or JavaScript actions inside the PDF.
- For Dompdf, finish all dynamic content before
loadHtml(). - For mPDF, treat
WriteHTML()as markup ingestion, not proof of script execution. - If a browser is required, choose a maintained engine or service and define an explicit readiness condition.
- Escape text, sanitize user markup, and control remote resources.
- Test fonts, images, page breaks, CSS, asynchronous content, and failure handling using the exact production versions.
FAQ
Can I put a <script> tag in Dompdf HTML?
You can include it as text in the source, but Dompdf will not execute it. Generate the resulting content before conversion.
Will mPDF execute JavaScript from an existing webpage?
Its documented API accepts HTML and CSS; the supplied documentation does not establish arbitrary webpage-script execution. Use a browser-backed renderer when scripts are essential.
Is JavaScript inside a PDF the same as JavaScript used to build a page?
No. A page script runs in a browser before rendering; a PDF action is an interactive feature inside the resulting file and requires separate library and viewer support.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →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.

