Marco Afonso
Marco Afonso

Reputation: 316

Puppeteer throws error with "Node not visible..."

When I open this page with puppeteer, and try to click the element, it throws an Error when it is expected to be possible to click the element.

const puppeteer = require('puppeteer');
const url = "https://www.zapimoveis.com.br/venda/apartamentos/rj+rio-de-janeiro/";

async function run() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(url, {waitUntil: 'load'});

  const nextPageSelector = "#list > div.pagination > #proximaPagina";
  await page.waitForSelector(nextPageSelector, {visible: true})
  console.log("Found the button");
  await page.click(nextPageSelector)
  console.log('clicked');
}

run();

Upvotes: 1

Views: 3980

Answers (2)

lcrespilho
lcrespilho

Reputation: 907

Found the problem. When you page.click(selector) or ElementHandle.click(), Puppeteer scrolls to the element, find its center coordinates, and finaly clicks. It uses the function _clickablePoint at node_modules/puppeteer/lib/JSHandle.js to find the coordinates.

The problem with this website (zapimoveis) is that the scroll into the element's viewport is too slow, so Puppeteer can't find its (x,y) center.

One nice way you can click on this element is to use page.evaluate to click it using page javascript. But, there is a gambi's way that I prefer. :) Change the line await page.click(nextPageSelector) by these lines:

try { await page.click(nextPageSelector) } catch (error) {} // sacrifice click  :)
await page.waitFor(3000); // time for scrolling
await page.click(nextPageSelector); // this will work

Upvotes: 1

Jeremie Olivier
Jeremie Olivier

Reputation: 66

Here's a working version of your code.

const puppeteer = require('puppeteer');
const url = "https://www.zapimoveis.com.br/venda/apartamentos/rj+rio-de-janeiro/";

async function run() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(url);

  const nextPageSelector = "#list > div.pagination > #proximaPagina";
  console.log("Found the button");

  await page.evaluate(selector=>{
      return document.querySelector(selector).click();
  },nextPageSelector)
  console.log('clicked');
}

run();

I personally prefer to use page.evaluate, as page.click doesn't work for me neither in some cases and you can execute whatever js on the page directly.

The only thing to know is the syntax : - first param : function to execute - second param : the variable(s) to be passed to this function

Upvotes: 1

Related Questions