DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
browser automation

How to Wait for Google reCAPTCHA to Appear in Puppeteer (Without Brittle Sleeps)

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for the condition your test actually needs—not an arbitrary delay. For a visible reCAPTCHA widget, wait for its iframe; when frame creation is the signal, use Puppeteer’s frame wait. If you own the application, an app-controlled readiness hook or Google’s test keys is more reliable than depending on Google’s changing production markup.

await page.waitForSelector('iframe[src*="recaptcha"]', {
  timeout: 10_000,
});

Or, when your test needs the frame object:

const captchaFrame = await page.waitForFrame(
  frame => frame.url().includes('recaptcha'),
  { timeout: 10_000 },
);

These waits detect an observable state; they do not—and should not—attempt to solve or bypass an anti-abuse challenge.

Choose the state that means “reCAPTCHA is ready”

Google reCAPTCHA integrations differ. A v2 checkbox commonly creates a cross-origin iframe, while invisible v2 and v3 may execute scripts and callbacks without showing a checkbox at all. Start by defining what the test must observe:

  • Element presence or visibility: use page.waitForSelector() when a stable host-page element or expected iframe is the signal.
  • Frame creation: use page.waitForFrame() when the test needs to inspect or coordinate with a matching frame.
  • Application readiness: prefer a container, callback, network-independent test hook, or other element your own code controls.

Puppeteer’s Page API documents both wait methods: Page API documentation. A selector evaluated on the main document does not search inside a cross-origin iframe, so wait for the iframe first and then use the frame object only for operations the browser security model permits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
FIDO2 U2F Security Key Passkey Two-Factor Authentication (2FA) USB Key PIN+Touch (Non-Biometric) USB-A Type TrustKey T110
  • Security Key : Protect your online accounts against unauthorized access by using FIDO2 and U2F authentication with T110. It's the world's most protective security key that works with windows, Mac OS, Linux as well as Chrome, Firefox, Edge and many other major browsers.
  • Certified with the new FIDO2 standard, T110 provides the benefit of fast login and strong protection against phishing, account takeover as well as many other online attactks.
  • Works with : Bank of America, Github, Google, Microsoft, DUO, Twitter, Facebook, Dropbox, Apple, ebay, BINANCE, mor and more.
  • Fits USB-A port : Insert the T110 security key into the USB-A port of each service and log in conveniently with one touch
  • For the driver download and user guide, please visit TrustKey Solutions Home support page.

Wait for a visible widget with waitForSelector()

For a v2 checkbox-style integration, this is the smallest useful test:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();

try {
  await page.goto('https://your-owned-site.example/form', {
    waitUntil: 'domcontentloaded',
    timeout: 30_000,
  });

  const iframe = await page.waitForSelector(
    'iframe[src*="recaptcha"]',
    { visible: true, timeout: 10_000 },
  );

  console.log('Visible reCAPTCHA iframe:', await iframe.evaluate(el => el.src));
} finally {
  await browser.close();
}

visible: true asks Puppeteer to wait until the matching node is present and has a visible layout. Omit it when existence, rather than visibility, is the requirement. The timeout is a test boundary: if no match appears in 10 seconds, Puppeteer throws a timeout error that should be reported as a meaningful failure.

Make the selector fit your integration

iframe[src*="recaptcha"] is a practical example, not a universal contract. Google or an integration can change generated attributes, use a different host, or avoid a visible iframe entirely. If your page owns a stable wrapper, wait for that instead:

await page.waitForSelector('[data-testid="captcha-ready"]', {
  visible: true,
  timeout: 10_000,
});

A host-page marker is less coupled to third-party markup. Add it in the application’s test configuration or expose it from the callback that your form already uses.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for the frame with waitForFrame()

Use a frame predicate when creation of a reCAPTCHA frame is the event under test:

Rank #2
Sale
Thetis Nano-A FIDO2 Security Key Hardware Passkey Device with USB Type A, TOTP/HOTP, FIDO2.0 Two Factor Authentication 2FA MFA, Works with Windows/mac/iOS/Android/Linux/Gmail/Facebook/GitHub/Coinbase
  • Ultra-Compact FIDO2 Security Key - Plug-and-stay or carry on a keychain. This USB-A hardware security key offers portable, always-on protection for desktop and mobile use. (Item Size: 0.75 X 0.74 IN x 0.25 IN)
  • USB-A Hardware Key for All Devices - Works with USB-A ports on PC, Mac, Android, and other laptop/notebook device. Enables secure, cross-platform login with FIDO2.0 passkey support.
  • FIDO Certified Security Key - Meets FIDO and FIDO2 standards. Works with Google, Microsoft, GitHub, Dropbox, and more. Please check service compatibility before purchase.
  • Passwordless Login with Passkey - Supports passkey login via WebAuthn and CTAP2. Enjoy password-free sign-ins where supported. Not all websites or services currently support passkeys.
  • Advanced Multi-Factor Authentication - Offers 200 FIDO2 passkey slots and 50 OATH-TOTP slots. Strong, flexible 2FA/MFA support across various apps and authentication platforms.
const captchaFrame = await page.waitForFrame(
  frame => frame.url().includes('recaptcha'),
  { timeout: 10_000 },
);

console.log('Captcha frame appeared:', captchaFrame.url());

This expresses the condition directly and avoids racing a later lookup through page.frames(). Keep the predicate narrow enough for your page; a site can load more than one Google frame. If multiple frames are expected, collect them and identify the one associated with your form rather than assuming the first match.

Selector wait versus frame wait

Need Recommended wait Main caveat
Confirm a visible checkbox or host element page.waitForSelector() Generated third-party selectors can change.
Know that a matching iframe was created page.waitForFrame() A frame can exist without a visible challenge.
Confirm your application finished setup Owned callback, container, or test hook Requires a small test-facing integration signal.

Neither method guarantees that a challenge will appear. A route may use invisible v2 or v3, trigger the widget only after a user action, or be configured not to render it in the current environment.

Handle asynchronous script loading correctly

Loading the reCAPTCHA script and rendering the widget are separate events. Google’s loading guidance says functions must not be called until the script has finished loading and documents grecaptcha.ready() plus a v2 onload callback pattern. See Google’s “Loading reCAPTCHA” guide (updated 2025-05-08 UTC).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For an application you control, coordinate the page and the test around the application’s callback or container. Do not treat networkidle as “CAPTCHA ready”: analytics, long polls, ads, and other resources can keep the network busy, while a widget may be ready before the network becomes idle.

// In your owned page, expose a test-only marker from the integration callback.
window.onCaptchaRendered = () => {
  document.querySelector('#captcha-container')
    ?.setAttribute('data-captcha-ready', 'true');
};
// In Puppeteer, wait for that application-owned state.
await page.waitForSelector(
  '#captcha-container[data-captcha-ready="true"]',
  { timeout: 10_000 },
);

Keep such hooks out of production behavior or guard them with your normal test-environment configuration.

Rank #3
Kensington VeriMark NFC+ USB‑C Security Key, FIDO2/WebAuthn Hardware Authenticator for Passwordless Login, Works with Windows, macOS & Chrome OS, K64739WW
  • USB-C or tap via NFC for easy authentication on any compatible device. No drivers needed; optional Kensington software available for advanced management features.
  • Works across Windows, macOS, iOS, Android, ChromeOS, and supports Passkeys and Apple ID.
  • Slim, keychain-ready form for easy carry and on-the-go authentication
  • IP68-rated for dependable performance
  • FIDO CTAP 2.1 for enhanced security features (e.g. resident credentials, Passkey support) and backwards compatibility with CTAP 2. FIDO2 L2 certified security for phishing resistant protection against identity theft and unauthorized access.

Use Google’s supported test configuration for your own site

Production reCAPTCHA is an anti-abuse service, so a test should not depend on receiving a real challenge. Google’s reCAPTCHA FAQ advises separate keys for testing. For v2, Google provides test keys under which no CAPTCHA is shown and verification requests pass; the widget displays a warning so those keys are not mistaken for production credentials. For v3, create a separate testing key and interpret scores cautiously: Google warns that v3 scores may not be accurate because the service relies on real traffic.

With a v2 test key, your correct assertion may be that the form can submit and the server accepts the verification response—not that an iframe appears. If the purpose of a test is specifically to exercise a visible widget, use a controlled integration or staging configuration that renders one, then apply the selector or frame wait above.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a wait times out—and what to check

The route never renders a visible iframe

Invisible v2 and v3 commonly do not present a checkbox. Confirm the site’s version and trigger conditions. Wait for the callback, host container, or form state instead of increasing a sleep.

The widget is rendered only after an action

Perform the same authorized action a user would, then wait:

await page.click('button[type="submit"]');
await page.waitForSelector('iframe[src*="recaptcha"]', {
  visible: true,
  timeout: 10_000,
});

If submission intentionally opens the challenge, assert the challenge state before asserting the final server response.

Rank #4
FIDO2 U2F Security Key Passkey Two-Factor Authentication (2FA) USB Key PIN+Touch (Non-Biometric) USB-C Type TrustKey T120
  • Security Key : Protect your online accounts against unauthorized access by using FIDO2 and U2F authentication with T120. It's the world's most protective security key that works with windows, Mac OS, Linux as well as Chrome, Firefox, Edge and many other major browsers.
  • Certified with the new FIDO2 standard, T120 provides the benefit of fast login and strong protection against phishing, account takeover as well as many other online attactks.
  • Works with : Bank of America, Github, Google, Microsoft, DUO, Twitter, Facebook, Dropbox, Apple, ebay, BINANCE, mor and more.
  • Fits USB-C port : Insert the T120 security key into the USB-C port of each service and log in conveniently with one touch
  • For the driver download and user guide, please visit TrustKey Solutions Home support page.

The selector matches nothing

Inspect the DOM and frame list in a failing test. Check for a changed integration, a different URL, or a test key that deliberately suppresses the widget. A selector on the main page cannot query elements inside a cross-origin frame; wait for the frame and use its Frame object where appropriate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The script or callback is not ready

Verify that the script loaded, that the callback name is registered before the script requests it, and that your page calls grecaptcha.ready() or the documented v2 onload flow. A longer fixed delay masks this race and makes tests slower without making them deterministic.

Google shows an automated-query warning

Follow Google’s troubleshooting guidance for that message at “My computer is sending automated queries”. Do not present automated solving or bypass techniques as a Puppeteer fix. Keep browser automation limited to sites and environments you own or are authorized to test.

The wait is flaky in CI

  • Use a realistic but bounded timeout and record a screenshot, URL, console output, and frame URLs when it fails.
  • Wait for the application state that matters, not global network idleness.
  • Use a dedicated staging origin and Google test keys where possible.
  • Avoid parallel tests sharing mutable CAPTCHA configuration or session cookies.
  • Keep browser and Puppeteer versions consistent across local and CI runners.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Timeouts, retries, and assertions

Choose the timeout from the page’s documented behavior and CI conditions; 10 seconds is an example, not a guarantee. A timeout should identify which state was absent. Do not automatically retry a challenge wait until it “passes”: retries can hide a broken integration and can produce unnecessary traffic to an anti-abuse service.

try {
  await page.waitForFrame(
    frame => frame.url().includes('recaptcha'),
    { timeout: 10_000 },
  );
} catch (error) {
  const frames = page.frames().map(frame => frame.url());
  console.error('reCAPTCHA frame did not appear', { frames });
  throw error;
}

If your acceptance criterion is successful form verification, assert the server-side result or your application’s completion state. Frame appearance is only the right assertion when frame appearance itself is what the test promises.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If you need a clean image or PDF of a page rather than a test of your own CAPTCHA integration, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

Use it only for pages you are allowed to capture; it is not a CAPTCHA-solving service. The API call is documented at ScreenshotNeo’s documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every plan includes its capture options, including full-page and element shots, device and viewport controls, custom headers and cookies, waits, blocking rules, caching, PDFs, async jobs, bulk capture, and usage reporting. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Further reading

Frequently Asked Questions

Can I wait for a CAPTCHA by sleeping for five seconds?

You can, but a fixed sleep is nondeterministic. A state-based selector, frame, or application callback wait reports the condition your test actually needs and fails sooner when configuration is wrong.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does waiting for the iframe prove that reCAPTCHA passed?

No. It proves only that a matching frame was created (and, with a visible selector wait, that it is visible). Verification must be asserted through your application’s documented success state or server response.

Should production CAPTCHA keys be used in CI?

For an owned application, use separate Google test keys and a staging configuration. Google’s v2 test keys suppress the challenge and pass verification; v3 testing scores may be inaccurate.

The Bottom Line

Use waitForSelector() for a visible, stable element, waitForFrame() for frame creation, and an application-owned callback whenever you control the page. Treat a timeout as evidence about the integration—not an invitation to add a longer sleep or bypass an anti-abuse challenge.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.