Custom Font Fails to Render in Puppeteer on Firebase Cloud Functions

Using Puppeteer in Firebase Functions to scrape a webpage and apply a custom font. Style injection executes without error, yet the default font is used. Example code:

const captureScreenshot = async (link) => {
  let bot;
  try {
    bot = await puppeteer.launch({
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
      executablePath: process.env.CHROME_PATH,
      headless: true
    });
    const page = await bot.newPage();
    await page.setUserAgent('Mozilla/5.0 (TestBot)');
    await page.goto(link, { waitUntil: 'networkidle2' });
    const fs = require('fs');
    const fontData = fs.readFileSync('./assets/CustomFont.ttf').toString('base64');
    await page.addStyleTag({
      content: `
        @font-face {
          font-family: 'CustomFont';
          src: url('data:font/ttf;base64,${fontData}') format('truetype');
        }
        body { font-family: 'CustomFont', sans-serif !important; }
      `
    });
    await page.screenshot({ path: 'screen.png', fullPage: true });
  } catch (error) {
    console.error(error);
  } finally {
    if (bot) await bot.close();
  }
};

In my experience, timing proves to be an important factor when working with custom fonts in Puppeteer on Firebase Cloud Functions. The issue could be related to when the font-face style is injected relative to the page rendering. I have encountered situations where the injection occurs after the initial page layout, resulting in no font update. A potential approach is to inject the custom font style before loading the page content or trigger a reload after applying the style to allow the browser engine to correctly apply the custom font.

In my experience with similar situations using Puppeteer in a cloud functions context, it helps to ensure that the custom font injection is fully recognized by the browser before the screenshot is taken. I encountered a case where a delay was needed after injecting the style tag to allow the browser to apply the font correctly. Although it might seem that the font data is being correctly passed in, sometimes the rendering engine misses it due to timing. I eventually resolved the issue by explicitly waiting for a short moment after the style is applied before proceeding with the capture.

i had a similar truble. instead of addin a style tag, i intercepted the font request and returned the base64 data. this forced puppetter to load the custom asset properlly. might be worth a try if delays dont work for you

My experience with this issue led me to experiment with a slightly different approach. I adjusted the CSS declaration by adding font-display: swap to the @font-face description, which encouraged the browser to apply the font as soon as it was ready. Additionally, I triggered a minor DOM update immediately after injecting the style tag using page.evaluate. This forced a reflow of the page, ensuring that the new CSS was applied correctly. This method helped mitigate the timing issues encountered during the initial page rendering in Firebase Cloud Functions.

I recently encountered a similar challenge with injecting a custom font in Puppeteer on cloud functions. The breakthrough came after I determined that the timing of when the font is applied is paramount. I had to adjust the workflow by introducing a brief wait after the font styles were added, which allowed the rendering engine to pick up the changes. I also experimented with triggering a minor reflow by modifying a non-intrusive element on the page, ensuring the browser recalculated styles. This approach ultimately ensured that the font loaded and rendered properly before the screenshot was taken.