Generate PDF with selenium chrome driver Generate PDF with selenium chrome driver selenium selenium

Generate PDF with selenium chrome driver


This can indeed be done with Selenium and ChromeDriver (tested with Chrome version 85), but using the "print-to-pdf" option when starting Chrome from the webdriver is not the solution.

The thing to do is to use the command execution functionality of ChromeDriver:

https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/remote/RemoteWebDriver.html#execute-java.lang.String-java.util.Map-

There is a command called Page.printToPDF that provides PDF output functionality. A dictionary containing the item "data", with the resulting PDF in base-64-encoded format, is returned.

Unfortunately, I do not have a full Java example, but in this answer, there is a C# example (Selenium methods are named differently in C# compared to Java, but the principle should be the same):

https://stackoverflow.com/a/63970792/2416627

The Page.printToPDF command in Chrome is documented here:

https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF


UPDATE:we noticed that the original workaround was not always working properly, and we went for a Selenium + ChromeDriver:

public void generatePdf(Path inputPath, Path outputPath) throws Exception{    try    {        ChromeOptions options = new ChromeOptions();        options.addArguments("--headless", "--disable-gpu", "--run-all-compositor-stages-before-draw");        ChromeDriver chromeDriver = new ChromeDriver(options);        chromeDriver.get(inputPath.toString());        Map<String, Object> params = new HashMap();                String command = "Page.printToPDF";        Map<String, Object> output = chromeDriver.executeCdpCommand(command, params);        try        {            FileOutputStream fileOutputStream = new FileOutputStream(outputPath.toString());            byte[] byteArray = java.util.Base64.getDecoder().decode((String) output.get("data"));            fileOutputStream.write(byteArray);            fileOutputStream.close();        }        catch (IOException e)        {            e.printStackTrace();        }    }    catch (Exception e)    {        e.printStackTrace(System.err);        throw e;    }}

If this will be called frequently I suggest reusing the driver object because it takes a while to initialize.

Remember to close or quit the driver to avoid leaving Zombie chrome processes behind and also remember to install ChromeDriver in your machine.


Original Solution:

Not being able to get the desired outcome using ChromeDriver my workaround was to call the headless chrome in the command-line from my Java program.

This is working on Windows but just changing the contents of the paths used in the command variable should make it work in Linux too.

public void generatePdf(Path inputPath, Path outputPath) throws Exception {    try {                    String chromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";        String command = chromePath + " --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf=" + outputPath.toString() + " " + inputPath.toString();                        // Runs "chrome" Windows command        Process process = Runtime.getRuntime().exec(command);        process.waitFor(); // Waits for the command's execution to finish                 }catch (Exception e){                e.printStackTrace(System.err);        throw e;    }finally{                // Deletes files on exit        input.toFile().deleteOnExit();        output.toFile().deleteOnExit();    }}

Note: both input and output paths are temporary files created with NIO.


The code will help you save the page in PDF format on Selenium c#

using OpenQA.Selenium;using OpenQA.Selenium.Chrome;    protected void PDFconversion(ChromeDriver driver, string root, string rootTemp)    {        //Grid.Rows.Add(TxtBxName.Text, TxtBxAddress.Text);        try        {            IJavaScriptExecutor js = (IJavaScriptExecutor)driver;            Thread.Sleep(500);            js.ExecuteScript("setTimeout(function() { window.print(); }, 0);");            Thread.Sleep(500);            driver.SwitchTo().Window(driver.WindowHandles.Last());            Thread.Sleep(500);            string JSPath = "document.querySelector('body>print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('#destinationSettings').shadowRoot.querySelector('#destinationSelect').shadowRoot.querySelector('print-preview-settings-section:nth-child(9)>div>select>option:nth-child(3)')";            Thread.Sleep(500);            IWebElement PrintBtn = (IWebElement)js.ExecuteScript($"return {JSPath}");            Thread.Sleep(500);            PrintBtn.Click();            string JSPath1 = "document.querySelector('body>print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('print-preview-button-strip').shadowRoot.querySelector('cr-button.action-button')";            Thread.Sleep(1000);            IWebElement PrintBtn1 = (IWebElement)js.ExecuteScript($"return {JSPath1}");            PrintBtn1.Click();            Thread.Sleep(1000);            SendKeys.Send("{HOME}");            SendKeys.Send(rootTemp + "\\" + "result.pdf"); // Path            SendKeys.Send("{TAB}");            SendKeys.Send("{TAB}");            SendKeys.Send("{TAB}");            SendKeys.Send("{ENTER}");            Thread.Sleep(1000);               }        catch (Exception ex){}    }