Skip to content
Advertisement

How to click and hold in Puppeteer

I am trying to click and hold using Puppeteer. I tried using page.click inside a while loop but it didn’t work.

let browserURL = `http://127.0.0.1:9222`;

let browser = await puppeteer.connect({ browserURL, defaultViewport: null });

const page = await browser.newPage();
while (pageContent.includes("hold")) {
  await page.click("div")
}

I also tried this:

await page.mouse.click(132, 103, { button: 'left' })

Any ideas how to do this?

Advertisement

Answer

There are a few tools to trigger a mouse hold in Puppeteer: page.click, mouse.click, mouse.down and mouse.up. page.hover can be useful for positioning the mouse over a selector and mouse.move can be useful for coordinate-based positioning and implementing clicking-and-dragging.

Then, there’s page.evaluate (and family), which lets you run browser code to trigger native mousedown and mouseup events on the target element. If you have difficulty clicking with the Puppeteer functions (for example, due to visibility issues), evaluate is a good next option to try.

Which approach you choose depends on your use case. If you use a .click() call (these are convenience wrappers on page.hover, mouse.move(), mouse.down() annd mouse.up()), you’ll want to set the delay property on the options object to simulate the hold, which the docs describe as

delay <number> Time to wait between mousedown and mouseup in milliseconds. Defaults to 0.

Here’s a proof of concept on the following button:

const hms = () => ("" + Date()).slice(16, 24);
const btnEl = document.querySelector("button");
btnEl.addEventListener("mousedown", e => {
  document.querySelector("ul").innerHTML +=
    `<li>mousedown at ${hms()}</li>`
  ;
});
btnEl.addEventListener("mouseup", e => {
  document.querySelector("ul").innerHTML +=
    `<li>mouseup at ${hms()}</li>`
  ;
});
<button>click and hold me</button>
<ul></ul>
const puppeteer = require("puppeteer");

let browser;
(async () => {
  const html = `
    <button>click and hold me</button>
    <ul></ul>
    <script>
      const hms = () => ("" + Date()).slice(16, 24);
      const btnEl = document.querySelector("button");
      btnEl.addEventListener("mousedown", e => {
        document.querySelector("ul").innerHTML +=
          `<li>mousedown at ${hms()}</li>`
        ;
      });
      btnEl.addEventListener("mouseup", e => {
        document.querySelector("ul").innerHTML +=
          `<li>mouseup at ${hms()}</li>`
        ;
      });
    </script>
  `;
  browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages();
  await page.setContent(html);
  await page.click("button", {delay: 5000});
  await page.waitForFunction(() => 
    document.querySelector("ul").innerText.includes("mouseup")
  );
  console.log(await page.$eval("ul", el => el.innerText));
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

Output is something like

mousedown at 12:53:23
mouseup   at 12:53:28

which shows that the mouse was held down on the button for 5 seconds.

Advertisement