javascriptgoogle-chromegoogle-chrome-headless

Alter the default header/footer when printing to PDF


I'm trying to use Google Chrome as a replacement of PhantomJS to render HTML into PDF. So far it's been working well for me. The only issue I have that I have not found any way to translate the following PhantomJS code:

page.paperSize = {
  footer: {
    contents: phantom.callback(function(pageNum, numPages) {
      return "Power by MyWebsite. Created on "+formatDate(new Date())+"<span style='float:right'>" + pageNum + " / " + numPages + "</span>";
    })
  }
}

Format date is the same function as in question How to format a JavaScript date

However I have not found a way to replicate this behavior in Google Chrome in headless. I am using Chrome remote interface (CDP) from https://github.com/cyrus-and/chrome-remote-interface

This is an outline of my chrome remote interface code:

return new Promise(async function (resolve, reject) {
    const url = "<MyURL here>";
    const [tab] = await Cdp.List()
    const client = await Cdp({ host: '127.0.0.1', target: tab });
    await Promise.all([
       Network.enable(),
       Page.enable()
    ]);

    Page.loadEventFired(function () { 
         setTimeout(function () {
             resolve(Page.printToPDF({displayHeaderFooter:true}))); //https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
         }, 3000);
    });
    await Page.navigate({ url }); 
};

I'm getting the PDF just fine but can only get the default Chrome headers and footers. Any way to modify them?

Note: I realise that I can use JavaScript in my page to append elements to the bottom of each page, but I'd prefer to alter the footer that is appended by the browser when exporting/printing as I've found it's much more reliable to get placed correctly and without causing any strange re-flowing of other divs in the page.


Solution

  • This is an update/answer to the question. As of Chromium 64 it is possible using the headerTemplate and footerTemplate parameters to printToPDF

    Using chrome remote interface here's example code that should work:

    (async function() {
      try {
        const [tab] = await Cdp.List();
        const client = await Cdp({ host: '127.0.0.1', target: tab });
        await Promise.all([
          client.Network.enable(),
          client.Page.enable(),
        ]);
    
        const url = "<MyURL here>";
        await client.Page.navigate({ url });
    
        await new Promise((resolve) => {
          client.Page.loadEventFired(async () => {
            const pdf = await client.Page.printToPDF({
              displayHeaderFooter: true,
              footerTemplate: "<span class='pageNumber'> of <span class='totalPages'></span></span>",
            });
            resolve(pdf.data);
          });
        });
      } catch (error) {
        console.error('Error generating PDF:', error);
      }
    })();