Comparing Buffers

I would like to compare two images in memory as opposed to relying on reading and writing from the file system.

I might be going about this the wrong way and if so I'd appreciate some sort of hint/help.

I've created a repo showcasing what I'm seeing:

const puppeteer = require('puppeteer')
const pixelmatch = require('pixelmatch')
const PNG = require('pngjs').PNG
const fs = require('fs')

function getTime(startTime) {
  return - startTime

async function takeScreenshot(page, options) {
  const startTime =
  await page.goto(
      waitUntil: 'networkidle2'
  const totalTime = getTime(startTime)

  await page.setViewport({
    height: options.height,
    width: options.width
  const data = await page.screenshot({
    path: options.path || null,
    fullPage: true

  return {
    data: data,
    time: totalTime

async function takeScreenshots(stagingOptions, prodOptions) {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  const staging = await takeScreenshot(page, stagingOptions)
  const prod = await takeScreenshot(page, prodOptions)

  await browser.close();

  return [

const run = async function () {
  try {
    const height = 900
    const width = 640
    const diff = new PNG({width, height})
    const stagingOptions = {
      path: 'stagingScreenshot.png',
      url: '',
    const prodOptions = {
      path: 'prodScreenshot.png',
      url: '',
    const [stagingScreenshot, prodScreenshot] = await takeScreenshots(stagingOptions, prodOptions)
    const allocationSize = height * width * 4
    const stagingBuff = Buffer.alloc(allocationSize)
    const prodBuff = Buffer.alloc(allocationSize)

    const numDiffPixels = pixelmatch(stagingBuff, prodBuff,, width, height, { threshold: 0.1 })
    fs.writeFileSync('diff.png', PNG.sync.write(diff))
    console.log('Results', JSON.stringify({
      diffScore: numDiffPixels / (height * width)
  } catch (error) {


The result diff image looks like red static. enter image description here

Both images have the same dimensions 1101 x 2614.

stagingScreenshot.png: enter image description here

prodScreenshot.png: enter image description here

Side note: One thing that threw me off was when I was reading the pixelmatch/index.js file, it says...

if (img1.length !== width * height * 4) throw new Error('Image data size does not match width/height.')

I don't understand why width and height are being multiplied by 4.



A few things to fix here:

const diff = new PNG({width, height})

This is not right because when you send the width and the height to takeScreenshot, you are using them to set the viewPort. But as you are taking a fullscreen screnshot, the result will be and image bigger than that.

So you should create the diff based on one of the screenshots. Something like this:

const [stagingScreenshot, prodScreenshot] = await takeScreenshots(stagingOptions, prodOptions)
const prodPng =
const stgPng =
const diff = new PNG({width: prodPng.width, height: prodPng.height})

const numDiffPixels = pixelmatch(,,, prodPng.width, prodPng.height, { threshold: 0.1 })