I am fairly new to React and I am developing an app which will take actual screenshots of a web page and the app can draw and add doodles on top of the screenshot taken. I i
Your React.js application runs on the client-side (in the browser). Puppeteer cannot run inside that environment as you cannot start a full browser inside the browser.
What you need is a server which does that for you. You could ether offer a HTTP endpoint (option 1) or expose your puppeteer Websocket (option 2):
For this option, you setup a server which handles the incoming request and runs the task (making a screenshot) for you:
server.js
const puppeteer = require('puppeteer');
const express = require('express');
const app = express();
app.get('/screenshot', async (req, res) => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(req.query.url); // URL is given by the "user" (your client-side application)
const screenshotBuffer = await page.screenshot();
// Respond with the image
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': screenshotBuffer.length
});
res.end(screenshotBuffer);
await browser.close();
})
app.listen(4000);
Start the application with node server.js and you can now pass the URL to your server and get a screenshot back from your server: http://localhost:4000/screenshot?url=https://example.com/
The response from the server could then be used as as the source of an image element in your application.
You could also control the browser (which runs on the server) from the client-side by by exposing the Websocket.
For that you need to expose the Websocket of your server like this:
server.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const browserWSEndpoint = browser.wsEndpoint();
browser.disconnect(); // Disconnect from the browser, but don't close it
console.log(browserWSEndpoint); // Communicate the Websocket URL to the client-side
// example output: ws://127.0.0.1:55620/devtools/browser/e62ec4c8-1f05-42a1-86ce-7b8dd3403f91
})();
Now you can control the browser (running on the server) form the client-side with a puppeteer bundle for the client. In this scenario you could now connect to the browser via puppeteer.connect and make a screenshot that way.
I would strongly recommend using option 1, as in option 2 you are fully exposing your running browser to the client. Even with option 1, you still need to handle user input validation, timeouts, navigation errors, etc.