How to pass a function in Puppeteers .evaluate() method? How to pass a function in Puppeteers .evaluate() method? google-chrome google-chrome

How to pass a function in Puppeteers .evaluate() method?


You cannot pass a function directly into page.evaluate(), but you can call another special method (page.exposeFunction), which expose your function as a global function (also available in as an attribute of your page window object), so you can call it when you are inside page.evaluate():

var myFunc = function() { console.log("lol"); };await page.exposeFunction("myFunc", myFunc);await page.evaluate(async () => {   await myFunc();   return true;});

Just remember that page.exposeFunction() will make your function return a Promise, then, you need to use async and await. This happens because your function will not be running inside your browser, but inside your nodejs application.

  1. exposeFunction() does not work after goto()
  2. Why can't I access 'window' in an exposeFunction() function with Puppeteer?
  3. How to use evaluateOnNewDocument and exposeFunction?
  4. exposeFunction remains in memory?
  5. Puppeteer: pass variable in .evaluate()
  6. Puppeteer evaluate function
  7. allow to pass a parameterized funciton as a string to page.evaluate
  8. Functions bound with page.exposeFunction() produce unhandled promise rejections
  9. exposed function queryseldtcor not working in puppeteer
  10. How can I dynamically inject functions to evaluate using Puppeteer?


Similar problems have been discussed in a puppeteer issue.

There are several way to deal with your problem. First rule is to keep it simple.

Evaluate the function

This is the fastest way to do things, you can just pass the function and execute it.

await page.evaluate(() => {  var myFunc = function(element) { element.innerHTML = "baz" };  var foo = document.querySelector('.bar');  myFunc(foo);  return true;});

Expose the function beforehand

You can expose the function beforehand using a page.evaluate, or a page.addScriptTag

// add it manually and expose to windowawait page.evaluate(() => {  window.myFunc = function(element) { element.innerHTML = "baz" };});// add some scriptsawait page.addScriptTag({path: "myFunc.js"});// Now I can evaluate as many times as I wantawait page.evaluate(() => {  var foo = document.querySelector('.bar');  myFunc(foo);  return true;});

Use ElementHandle

page.$(selector)

You can pass an element handle to .evaluate and make changes as you seem fit.

const bodyHandle = await page.$('body');const html = await page.evaluate(body => body.innerHTML, bodyHandle);

page.$eval

You can target one element and make changes as you want.

const html = await page.$eval('.awesomeSelector', e => {e.outerHTML = "whatever"});

The trick is to read the docs and keep it simple.


Pass function with parameter

// add it manually and expose to window

 await page.evaluate(() => {      window.myFunc = function(element) { element.innerHTML = "baz" };    });

// and then call function declared above

 await page.evaluate((param) => {         myFunc (param);    }, param);