Puppeteer page.click doesn't work in headless mode

Viewed 2708

What's the problem

I try to click some element using Puppeteer, and I tried both page.click and page.evaluate on this task.

  • If in headless=false mode, both approaches work well.
  • If in headless=true mode, page.evaluate works, but page.click hangs forever.

What I did then, is page.waitForSelector explicitly for the element before page.click, see code below.

And looks like waitForSelector hangs forever too.

Could anyone help me to understand why it hangs in headless mode?

Env

chrome version is HeadlessChrome/80.0.3987.0
puppeteer version 2.1
macOS catalina 10.15.3

Code


const pptr = require('puppeteer');

console.log(pptr.version);

(async () => {
    var br = await pptr.launch({
        headless: true,
        defaultViewport: null,
        args: [
            '--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
            '--user-data-dir=/tmp/user_data/',
        ],
    });
    var page = await br.newPage();
    var url = 'https://www.lookfantastic.com/brands/aesop/view-all.list';
    var css = 'div.responsiveProductListPage_topPagination button[aria-label="next page" i]:not([disabled])';

    const chrome_version = await page.browser().version();
    console.log(`chrome version is ${chrome_version}`);

    await page.goto(url);
    await page.waitForSelector(css, { visible: true });  // when headless=true, hangs here.

    await Promise.all([
        page.click(css),
        //page.evaluate((css) => { document.querySelector(css).click(); }, css),
        page.waitForNavigation({waitUntil: 'networkidle0'}),
    ]);
    console.log('success');
    await new Promise(r => setTimeout(r, 1000));
    await br.close();
})();

2 Answers

Based on your comment, the screen in headless might not be of the right size for the element you are testing. Does this element is supposed to be shown on laptop sized screen (width > 1200px in your case)?

You can set the window size of Puppeteer with the option --window-size=width,height, for instance:

args: [
            '--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
            '--user-data-dir=/tmp/user_data/',
            '--window-size=1200,800',
        ],

I found that a more proper way of preventing this issue would be calling hover before click, like this:

await page.hover(selector)
await page.click(selector)

This way, the browser will scroll to the selector, ensuring it is visible and can be clicked, regardless of window size.

Related