22

I ran into an issue where I nave a fairly simple Node process that captures a screenshot. Is it possible to change the innerText of an HTML element using Puppeteer, just before the screen capture is acquired?

I have had success with using Puppeteer to type text in authentication fields and with logging into a site, but I was wondering if there is a similar method that would let me change the text in a specific element (using id or class name).

Example of the screen capture code I'm using:

const puppeteer = require('puppeteer');
 (async () => {
    const browser = await puppeteer.launch()
    const page = await browser.newPage()
    await page.goto('https://google.com')
    await page.screenshot({path: 'google.png'})
    await browser.close()
 })()

In this example, I would be interested in knowing if I can change the text content of an element such as the div with the ID 'lga' ... adding a text string for example.

Is that possible with Puppeteer?

Otherwise, it works great. I just need to insert some text into the page I'm performing a screenshot of. I'm using the command-line only on a Ubuntu 16.04 machine, and Node version 9, Puppeteer version 1.0.0.

Grant Miller
  • 27,532
  • 16
  • 147
  • 165
tamak
  • 1,541
  • 2
  • 19
  • 39

3 Answers3

52

you can do that before screen

 await page.evaluate(() => {
    let dom = document.querySelector('#id');
    dom.innerHTML = "change to something"
 });
Cr.
  • 886
  • 7
  • 12
  • 1
    Can you delete an element as well? – user1584421 Jun 07 '18 at 21:05
  • 3
    @user1584421 yes,```dom.parentNode.removeChild(dom);``` . – Cr. Jun 11 '18 at 01:44
  • 1
    Can "change to something" be a variable passed in? How is that done? – Tom Mercer May 15 '20 at 22:52
  • @TomMercer, do you change parameter(s) in a loop? Then just assign new value before page.evaluate function and in it use it, maybe as a string literal template like `dom.innerHTML = \`${var}\`;` – Matt Sergej Rinc Apr 25 '21 at 23:36
  • 1
    @MattSergejRinc it doesn't work like that - the function that you pass in is executed by the browser that Puppeteer is running, not by your script, so it doesn't have access to variables that the evaluate function is closed over. You can pass in parameters to the evaluate function to get around this. I'll add an answer to explain in detail. – Tristan Reid Sep 02 '21 at 23:51
6

In addition to the excellent answer above, it is important to note that you can't access variables as you normally would expect in the evaluate function. In other words, this won't work:

 const selector = '#id'
 await page.evaluate(() => {
    let dom = document.querySelector(selector)
    dom.innerHTML = "change to something"
 });

You can solve this problem by passing variables to the evaluate function. For example:

 const selector = '#id'
 await page.evaluate((s) => {
    let dom = document.querySelector(s)
    dom.innerHTML = "change to something"
 }, selector);

In the above example I used s as the parameter, but passed in the value stored in selector. Those could be the same variable name, but I wanted to illustrate that the outer variable is not directly used.

If you need to pass in multiple values, use an array:

 const selector = '#id'
 const newInnerHTML = "change to something"

 await page.evaluate(([selector, newInnerHTML]) => {
    let dom = document.querySelector(selector)
    dom.innerHTML = newInnerHTML
 }, [selector, newInnerHTML]);
Tristan Reid
  • 5,844
  • 2
  • 26
  • 31
4

page.$eval()

You can use page.$eval() to change the innerText of an element before taking a screenshot:

await page.$eval('#example', element => element.innerText = 'Hello, world!');

await page.screenshot({
  path: 'google.png',
});
Grant Miller
  • 27,532
  • 16
  • 147
  • 165