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

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: a Java HTML-to-PDF converter usually does not execute JavaScript just because its input is an HTML String. If the script must change the page before printing, first load the HTML in a browser engine such as headless Chrome, wait for the required DOM changes, extract the resulting markup, and then pass that markup to the PDF converter. With iText pdfHTML, this means Selenium WebDriver followed by HtmlConverter.convertToPdf(...).

Why a String-to-PDF call does not run JavaScript

An HTML string is markup, not a browser session. A converter can parse elements and styles and lay them out on PDF pages, but it does not necessarily provide the JavaScript runtime, browser event loop, or DOM APIs that a script expects. Passing <script> content to a converter therefore does not make the script execute.

iText’s pdfHTML documentation explicitly describes the solution as preprocessing HTML, CSS, and JavaScript in a browser engine before converting the result. OpenHTMLtoPDF’s project documentation says it does not run JavaScript, and the Flying Saucer guide likewise says JavaScript is not supported. These are reasonable options for static markup, but not substitutes for a browser when the page depends on script execution.

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

The reliable model is two-stage rendering: use a browser to produce the desired DOM, then give the post-script HTML to the PDF renderer. The browser stage handles JavaScript; the PDF stage handles pagination and PDF output. Neither stage automatically guarantees that every browser-rendered visual detail will survive conversion, so check the PDF renderer’s supported CSS and resource handling too.

Use Selenium and headless Chrome with iText pdfHTML

The following example keeps the source in a Java string, opens it in Chrome using a Base64 data URL, waits until the script changes the DOM, extracts the resulting document HTML, and converts it to a PDF. It includes a bounded wait rather than assuming that navigation completion means asynchronous work is finished.

import com.itextpdf.html2pdf.HtmlConverter;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;

public class HtmlStringToPdf {
    public static void main(String[] args) throws Exception {
        String html = "<!doctype html>"
                + "<html><head><meta charset='utf-8'>"
                + "<title>Example</title></head>"
                + "<body><div id='test'>Before</div>"
                + "<script>"
                + "document.getElementById('test').textContent = 'After';"
                + "</script></body></html>";

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        WebDriver driver = new ChromeDriver(options);

        try {
            String encoded = Base64.getEncoder().encodeToString(
                    html.getBytes(StandardCharsets.UTF_8));
            driver.get("data:text/html;charset=utf-8;base64," + encoded);

            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
            wait.until(d -> "After".equals(d.findElement(
                    org.openqa.selenium.By.id("test")).getText()));

            String evaluatedHtml = (String) ((JavascriptExecutor) driver)
                    .executeScript("return document.documentElement.outerHTML;");

            try (FileOutputStream out = new FileOutputStream("output.pdf")) {
                HtmlConverter.convertToPdf(evaluatedHtml, out);
            }
        } finally {
            driver.quit();
        }
    }
}

This is an illustrative complete flow; add the Selenium, ChromeDriver, and pdfHTML dependencies to your project using the versions approved for your environment. Keep the browser and driver versions compatible, and ensure the Chrome binary is installed where the Java process runs. The iText API shown is HtmlConverter.convertToPdf(String html, OutputStream pdfStream).

Make the browser capture the right state

Load-time scripts

Inline scripts that run while the document loads may have completed by the time Selenium’s navigation returns, but asynchronous fetches, timers, and client-side rendering can continue afterward. Wait for an observable condition that represents the content you need, such as the presence of a chart element or a changed text value. An explicit condition is more reliable than a fixed sleep because it can finish as soon as the page is ready and fail clearly if the condition never occurs.

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

Scripts that require interaction

A script registered for a click, form submission, or other user action will not necessarily run on its own. Use WebDriver to perform that action before extracting HTML. Likewise, if the page needs a logged-in session or a particular application state, establish it in the browser before capture. The extracted DOM reflects the state you actually reached, not the state you intended to reach.

What to extract

The example returns document.documentElement.outerHTML, which includes the document element itself. The iText Knowledge Base example uses document.documentElement.innerHTML, which returns the contents inside that element. Either may suit a particular document, but returning the full element generally preserves the <html> wrapper. If your markup relies on a doctype or particular document metadata, verify the output and adjust your extraction strategy accordingly.

Relative assets and base URI

Extracted HTML can contain relative references to images, stylesheets, or fonts. Those references need a base location at conversion time; otherwise the converter may not know where to resolve them. Configure iText’s ConverterProperties.setBaseUri(...) with the appropriate base URI when converting. If you use a data URL for the browser input, that data URL is not a useful filesystem or website base for your assets. Use a controlled local endpoint, a suitable base URI, or absolute asset URLs as appropriate.

Choose between browser preprocessing and a static renderer

Need Browser preprocessing with pdfHTML OpenHTMLtoPDF or Flying Saucer directly
Execute JavaScript before PDF generation Yes, in the browser stage; then convert the evaluated HTML. No, according to their project documentation.
Convert HTML held in Java Yes; pdfHTML accepts a string for conversion after preprocessing. Suitable for static markup, subject to the chosen library’s input API.
Operational components Requires a browser binary, WebDriver, and browser lifecycle management. Fewer components when the markup is static.
Best fit Client-side templating, DOM mutations, or script-generated content. Controlled documents whose content is already present in markup.

There is no neutral benchmark in the cited project documentation establishing a universal speed, memory, or JavaScript-compatibility winner. Measure representative documents in your deployment environment before choosing on performance grounds. The documented feature-support baseline for iText pdfHTML is 6.3.3 with iText Core 9.7.0; verify current versions and signatures when building or upgrading. OpenHTMLtoPDF’s repository metadata describes a 1.0.11-SNAPSHOT head and lists 1.0.10 as a 2021 release, which is project metadata rather than a performance measurement.

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

Handle large, private, or asset-heavy HTML safely

A Base64 data URL avoids the character-escaping problems of concatenating raw HTML into a URL, but it is still a poor transport for arbitrarily large documents: browser URL limits and memory overhead can become practical constraints. For large documents, or content that should not be embedded into a navigable URL, serve it through a controlled local endpoint or use a temporary file that the browser can load. Apply access controls and clean up temporary content when finished.

  • Wait for the actual ready condition. A page load event is not proof that a remote API call, chart, or lazy-rendered section has finished.
  • Preserve resource access. The browser and PDF converter may resolve assets separately; ensure both can reach what they need.
  • Close resources in all paths. The finally block closes WebDriver even if waiting or conversion fails. For a long-running service, manage browser instances deliberately rather than leaking Chrome processes.
  • Validate the result. Test that generated text and images are present and that page breaks, fonts, and CSS are acceptable in the PDF renderer.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common failures

The PDF contains the original text, not the JavaScript result

Check that the script actually ran and that extraction happens afterward. Add an explicit wait on the resulting DOM value, and confirm you pass the extracted HTML—not the original string—to HtmlConverter.convertToPdf.

The wait times out

The selector or condition may be wrong, the code may depend on an interaction, a script may have thrown an error, or a network request may have failed. Inspect the page state in WebDriver, wait on the precise expected content, and perform any required clicks or form actions before extraction.

Images, CSS, or fonts disappear

Relative URLs may no longer resolve after extraction. Set the converter’s base URI with ConverterProperties.setBaseUri(...), verify that the process can access the assets, and test whether the assets are supported by the PDF conversion stage.

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.

Navigation fails for a long HTML string

The encoded data URL may exceed practical browser limits. Move the document to a controlled local endpoint or temporary file rather than continually expanding the URL.

Chrome does not start or remains running

Confirm Chrome/Chromium and the matching driver are available to the Java process, inspect the process environment and permissions, and ensure driver.quit() runs from a finally block. A stuck browser is a lifecycle issue, not a JavaScript capability of the PDF converter.

Or skip the browser setup

If your actual need is capturing a live website URL as an image or PDF rather than converting an arbitrary Java HTML string, ScreenshotNeo is a website screenshot API and MCP server. It does not replace the browser-plus-pdfHTML workflow for a String you need to process inside Java; it provides a hosted capture route for URL-based pages.

For example, this one-call cURL request captures a URL to an image file:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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 request options. ScreenshotNeo accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

Sign up free for 1,000 screenshots a month with no card.

Frequently Asked Questions

Does putting a script inside an HTML String make iText pdfHTML execute it?

No. The string input is markup for conversion, not a JavaScript execution environment; preprocess it in a browser if its script must run.

Can I use OpenHTMLtoPDF or Flying Saucer for script-generated charts?

Not to execute the chart’s JavaScript. Generate the chart in a browser first, then supply suitable resulting content to a renderer.

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.

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.