How to make Puppeteer work with a ReactJS application on the client-side
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):
Option 1: Provide a HTTP endpoint
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.
Option 2: Exposing the puppeteer Websocket to the client
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.