node.jstypescriptweb-scrapingplaywright

How to run a JavaScript function with playwright inside an iframe?


I am scraping data from a website, and at certain moments, it is necessary to solve a reCAPTCHA v2.

I am using the 2Captcha service to solve these CAPTCHAs. Upon receiving the API response, which is a string, I need to insert this value into the element that references the CAPTCHA:

textarea[name="g-recaptcha-response"]

The problem is that this element is inside an "iframe" which prevents me from executing page.evaluate directly in Playwright.

I tried the following code:

  let captchaKey: string;

  await solver
      .recaptcha({
          pageurl: page.url(),
          googlekey: src,
          invisible: 1,
      })
      .then(async (res) => {
          captchaKey = res.data;

          const frameLocator = page.frameLocator('table iframe[title="reCAPTCHA"]');
          const frame = frameLocator.first();

          const frames = await page.frames();
          const captchaFrame = frames[1];

          await captchaFrame.evaluate(() => {
              const captchaInput = document.querySelector(
                  'textarea[name="g-recaptcha-response"]'
              ) as HTMLTextAreaElement;

              captchaInput.value = captchaKey;
          }, captchaKey);

          await frame.locator('#recaptcha-anchor > div.recaptcha-checkbox-border').click();
      })
      .catch((err) => {
          console.log(err);
      });

However, I receive the following error: "Property 'evaluate' does not exist in type 'FrameLocator'.ts(2339)"


Solution

  • You can use .locator(':root').evaluate().

    await captchaFrame.locator(':root').evaluate((root, args) => {
      const captchaInput = document.querySelector(
        'textarea[name="g-recaptcha-response"]'
      ) as HTMLTextAreaElement;
    
      captchaInput.value = args.captchaKey;
    }, {captchaKey});