Nenatik
Nenatik

Reputation: 79

How to fix "Node is either not visible or not an HTMLElement" error thrown by Puppeteer?

I am creating a bot for posting something every day on Instagram, and I want to use creator studio from Facebook. The script below works fine:

const puppeteer = require('puppeteer');

(async () => {
  var username  = require('./config')
  var password  = require('./config')
  const browser = await puppeteer.launch();
  const ig = await browser.newPage();
  await ig.setViewport({
    width: 1920,
    height: 1080
  })
  await ig.goto('https://business.facebook.com/creatorstudio/');
  await ig.click('.rwb8dzxj');
  await ig.waitForSelector('#email');
  await ig.type('#email', username.username);
  await ig.type('#pass', username.password);
  await ig.click('#loginbutton');
  await ig.waitForSelector('#media_manager_chrome_bar_instagram_icon');
  await ig.click('#media_manager_chrome_bar_instagram_icon');
  await ig.waitForSelector('[role=presentation]');
  await ig.click('[role=presentation]');
  await ig.screenshot({path: 'example.png'});
  await browser.close();
})().catch(err => {
  console.log(err.message);
})

but when I continue and add:

await ig.waitForSelector('[role=menuitem]');
await ig.click('[role=menuitem]'); 

I get this error:

"Node is either not visible or not an HTMLElement"

Upvotes: 3

Views: 6174

Answers (1)

0Valt
0Valt

Reputation: 10365

The error caused by the click and hover methods called on an ElementHandle can be mitigated by ensuring the element is "in view" separately from the method (despite the docs stating that the method "scrolls it into view if needed", seems like sometimes the element does not become visible).

Assuming the element is indeed attached to DOM - you can check that via isConnected property, try using something like this (the sample is in TypeScript) - scrollIntoView should make sure the element is centered on:

const safeHover = async <E extends ElementHandle<Element>>(
  elem: E
) => {

  await elem.evaluate((e) =>
    e.scrollIntoView({ block: "center", inline: "center" })
  );

  await elem.click();
};

Note that the sample uses elementHandle's click method, not Page's. Since you call waitForSelector before clicking, use the returned elementHandle:

//...
const pres = await ig.waitForSelector('[role=presentation]'); 
pres && await safeHover(pres);
//...

Also, these Q&As may prove useful:

  1. Puppeteer in NodeJS reports 'Error: Node is either not visible or not an HTMLElement'
  2. Puppeteer throws error with "Node not visible..."

Upvotes: 3

Related Questions