ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

Follow publication

Use Puppeteer and Nodejs to take screenshots and PDFs — as a Service

Christian Kaatz
ITNEXT
Published in
4 min readJan 29, 2021

--

Photo by Bank Phrom on Unsplash

What is a bit more?

The API

//...
/**
* @api {get} /pdf obtain a pdf of a page
* @apiName TakeScreenshot
* @apiGroup PDF
* @apiVersion 1.0.0
*
* @apiParam {String} url a url to be looked up
* @apiParam {Number} [w] width of the viewport
* @apiParam {Number} [h] height of the viewport
* @apiParam {String} [d] device to use for the viewport - overwrites other v/h parameters
*
* @apiSuccess {File} pdf the generated pdf
* @apiError {Object} Errors returned errors
*/
//...
const { devices } = require('./util');

const screenshotSchema = {
title: 'Page screenshot',
description: 'Take screenshot of a page',
type: 'object',
properties: {
url: {
type: 'string',
format: 'uri',
pattern: '^(https?|http?)://',
minLength: 1,
maxLength: 255,
},
selector: {
type: 'string',
minLength: 1,
maxLength: 255,
},
},
required: ['url'],
};

const pdfSchema = {
title: 'PDF page print',
description: 'Take pdf of a page',
type: 'object',
properties: {
url: {
type: 'string',
format: 'uri',
pattern: '^(https?|http?)://',
minLength: 1,
maxLength: 255,
},
w: {
type: 'integer',
minimum: 1,
maximum: 12288,
},
h: {
type: 'integer',
minimum: 1,
maximum: 12288,
},
d: {
type: 'string',
enum: Object.keys(devices),
},
},
required: ['url'],
};

module.exports = { screenshotSchema, pdfSchema };
//...
router.get('/shot', async (req, res) => {
const validate = ajv.compile(screenshotSchema);
const result = await validate(req.query);
if (!result) {
const errors = await parseAJVErrors(validate.errors);
// return with the validation errors
return res.status(400).json({ errors });
}
const { url, selector } = req.query;
//use the params now

Testing

const test = require('ava');
const { shot: screenshot, pdf } = require('./capture');
const fs = require('fs');

test('create screenshots', async (t) => {
const screenshotBuffer = await screenshot({ url: 'https://www.google.com' });
t.assert(
screenshotBuffer.toString('binary').length > 1,
'Should have generated a screenshot',
);
});
test('create screenshot by selector', async (t) => {
const screenshotSelectorBuffer = await screenshot({
url: 'https://card-joy.web.app/v?img=c1&t=Merry%20Christmas!&p=topLeft',
selector: '#root > div > div > div > img',
});
t.assert(
screenshotSelectorBuffer.toString('binary').length > 1,
'Should have generated a screenshot',
);
});
test('create pdf', async (t) => {
const generated = await pdf({ url: 'https://www.google.com' });
t.assert(generated.length > 0, 'Should have generated a pdf');
});

Security

Deployment

$ docker run -it --rm -p 3000:3000 chrkaatz/the-snap
{
"name": "The Snap",
"description": "A simple service to obtain screenshots and PDFs from pages",
"repository": "https://github.com/chrkaatz/the-snap",
"logo": "https://github.com/chrkaatz/the-snap/raw/main/logo.png",
"keywords": ["node", "puppeteer", "screenshot", "api", "pdf"],
"buildpacks": [
{
"url": "heroku/nodejs"
},
{
"url": "https://buildpack-registry.s3.amazonaws.com/buildpacks/jontewks/puppeteer.tgz"
}
],
"env": {
"HUSKY": {
"description": "Disable git hooks managed by husky",
"value": "0"
}
}
}

Code

--

--

Published in ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

Written by Christian Kaatz

Dedicated Solution Engineer with focus on agile software development, team culture and evolutionary architectures.

Responses (1)

Write a response