Note: I am asking here a adapted version of this this closed question.
When using Puppeteer, it's easy to produce screenshots. It's even their first example, and it works fine on my web app:
const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6']; //iPhone 5/SE does not work
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://web.replayer.app', {
waitUntil: 'networkidle2',
});
await page.screenshot({ path: 'replayer-app.png' });
await browser.close();
})();
This produces a nice screenshot, but without device frame.
If I try to use one of the device names, that do produce a visual device frame in Google Chrome, like iPhone5/SE, I get
C:\Users\masu\Documents\node_modules\puppeteer\lib\cjs\puppeteer\common\Page.js:1500
this.setViewport(options.viewport),
^
TypeError: Cannot read properties of undefined (reading 'viewport')
at Page.emulate (C:\Users\masu\Documents\node_modules\puppeteer\lib\cjs\puppeteer\common\Page.js:1500:38)
at C:\Users\masu\Documents\puppeteer-question.js:7:14
at processTicksAndRejections (node:internal/process/task_queues:96:5)
However, since it's a web app, I would like to have the screen shot a device frame around it.
How to use and capture a screenshot from an emulated device with a viewport?
What is the cause of the issue?
I. You get this error because you are emulating the desired device with the wrong name. Even if DevTools UI names it "iPhone 5/SE" in reality DevTools Protocol only knows either "iPhone 5" or "iPhone SE" (you can give a try to give any false strings here, like "iPhone 2000", you will end up with the very same error msg). The available and valid device names are listed in DeviceDescriptors.ts on Github.
II. Since the referenced question was asked the situation is still the same: you cannot do a screenshot of the page with the device frames in puppeteer. Simply because those frames are part of the DevTools UI while Puppeteer is a high-level API to control Chrome over the DevTools Protocol: one is related to its frontend the other to its backend functionalities.
How you can proceed?
images('iPhone_5_portrait.png').draw(images('wikipedia.png').size(320), 130, 220).save('output.jpg')
.