Zoom auto join using puppeteer

112 views Asked by At

I'm trying to join the zoom meeting with puppeteer, but my code is unable to capture the type password element, can anyone please help?

This is my code

const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());


async function joinZoomMeeting(){
    let meetId = '773 2982 7579';
    let meetPassCode = 'cnm4Ac';
    let joineeName = 'Sj';

    const browser = await puppeteer.launch({
        headless: false,
        args: [
          "--disable-notifications",
          "--enable-automation",
          "--start-maximized",
        ],
        ignoreDefaultArgs: false,
      });

    const [page] = await browser.pages();

    await page.goto('https://app.zoom.us/wc/join')
    
    await page.waitForSelector('input[type="text"]');
    await page.type('input[type="text"]', meetId);

    // await page.waitForSelector('.btn-join btn btn-primary')
    const joinButton = await page.$('.btn-join')
    
    await joinButton.click()

    await page.waitForTimeout(5000);
    
    const passwordField = await page.$('#input-for-pwd');
    console.log(passwordField)
    // await page.type('input[type="password"]', meetPassCode);
    // await page.waitForSelector('input[type="text"]');
    // await page.tpe('input[type="text"]' , joineeName);
    // const passInput = await page.$('.preview-meeting-info-field-input')
    // console.log(passInput)
    // const passwordInputSelector = '#input-for-pwd';

    // // Type the password into the input field
    // await page.type(passwordInputSelector, meetPassCode);
    
}

joinZoomMeeting()

I've tried all the commented ways of capturing the element! But nothing worked!!

This is the element

<input id="input-for-pwd" type="password" class="preview-meeting-info-field-input" autocomplete="off" required="" aria-invalid="false" aria-describedby="error-for-pwd" value="">

Please let me know, how to fix this, I'm stuck at this point, the code is capturing the first type meeting Id element in the first page, but in the second page it is unable to capture the type password feild.

1

There are 1 answers

4
ggorlen On BEST ANSWER

The main issue here is that the page has an iframe with most of the app in it. You'll need to select the iframe first, then make queries inside of it.

As with many websites, there are quirks, so I had to use waitForFunction that dives into the iframe to verify the presence of an element because the normal waitForSelector was timing out.

const puppeteer = require("puppeteer"); // ^21.6.0

let browser;
(async () => {
  const meetId = "<your meeting id here>";
  const meetPassCode = "<your meeting password here>";
  const joineeName = "Sj";
  browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages();
  const ua =
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";
  await page.setUserAgent(ua);
  await page.goto("https://app.zoom.us/wc/join");
  const meetingInput = await page.waitForSelector('input[type="text"]');
  await meetingInput.type(meetId);
  const joinBtn = await page.waitForSelector(".btn-join");
  await joinBtn.click();
  await page.waitForFunction(`
    document.querySelector("#webclient")
      .contentDocument.querySelector("#input-for-pwd")
  `);
  const f = await page.waitForSelector("#webclient");
  const frame = await f.contentFrame();
  await frame.type("#input-for-pwd", meetPassCode);
  await frame.type("#input-for-name", joineeName);
  await frame.$$eval("button", els =>
    els.find(el => el.textContent.trim() === "Join").click()
  );
  await frame.waitForSelector(".join-dialog");
  await page.screenshot({path: "zoom.png"});
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

You can take more actions or block the script with a timeout or remove browser.close() if you want the window to stay open indefinitely.

Tips:

  • Avoid waitForTimeout. It's both slow and flakey.
  • waitForSelector returns its element (disclosure: I am the author of the blog post), so better to use it than query it again with page.$, which isn't generally necessary.