Puppeteer deployed to Heroku (Ubuntu) does not download PDF using Times New Roman font

I'm developing an app that needs to use Puppeteer to view a webpage and download it as a PDF for the end user. I'm using express.js as a server. The problem I'm having is that when developing locally on Windows, my PDF downloads look just like the source web page they're based off of, but when I deploy the app to Heroku which uses a Ubuntu based environment, the font is changed from Times New Roman to sans-serif.

Here is a snippet of my Puppeteer print pdf code:

async function printPdf(url) {
  const browser = await puppeteer.launch({
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
    ],
  })
  const page = await browser.newPage()
  await page.goto(url, {waitUntil: 'networkidle0'})

  const pdf = await page.pdf({ format: 'A4' })
  await browser.close()

  return pdf
}

When I'm developing locally in Windows 10, the PDF downloads correctly:

localhost: source view on firefox that PDF references: enter image description here

localhost: resulting PDF download, which correctly uses Times New Roman font: enter image description here

My project is deployed to a free dynos using the Heroku-20 Stack, which is "based on Ubuntu 20.04". I've never used Linux, and am worried that may be the source of the problem.

When deployed, the web app correctly displays the font in firefox: enter image description here

But the PDF download uses font-family: sans-serif: enter image description here

How can I ensure my app deployed in a Linux environment downloads a PDF using the Times New Roman font?


Microsoft fonts are not available on Ubuntu out of the box. You can install the ttf-mscorefonts-installer package to get Times New Roman, Arial, and other pre-Calibri Microsoft fonts.

On Heroku, you do that via the Apt buildpack:

  1. First, add the buildpack to your app:

    heroku buildpacks:add --index 1 heroku-community/apt
    
  2. Then, add an Aptfile listing the packages you wish to install. The Apt buildpack doesn't do dependency resolution so you may have to include a few dependencies manually.

    Something like this should do it:

    cabextract
    ttf-mscorefonts-installer
    wget
    xfonts-utils
    
  3. Finally, commit your Aptfile and redeploy.


as per the Heroku Support team:

The library ttf-mscorefonts-installer has a post-install script (that installs the fonts) that's not running because we use dpkg -x (extract) not dpkg -i (install) in the apt buildpack. The installer is being downloaded and unpacked, but nothing of value is actually happening. There are two workarounds either:

  • download the font manually and add it to the repo and have Puppeteer call upon it, or
  • use a different font, perhaps one already provided by the Ubuntu (fc-list in a dyno shows installed fonts) or is more easily downloadable and installable.

for my specific use-case, the issue was resolved by adding the font to my build and linking it via CSS. I found this blogpost helpful: 3 quick ways to add fonts to your React app