[baoyu-url-to-markdown] reCAPTCHA v3 badge (no challenge) is treated as a blocking interaction — pages with a passive badge can never be fetched

Author: andrewlluCreated Aug 18, 2026Updated Aug 18, 2026

Summary

browser/interaction-gates.ts treats any reCAPTCHA presence as a wait_for_interaction gate. Sites that load a reCAPTCHA v3 badge (the passive bottom-right badge injected site-wide by contact-form plugins such as Contact Form 7 / Avada Forms on WordPress) match the selectors even though there is no challenge for the user to solve. Result: headless mode aborts with generic requires manual interaction, and --wait-for interaction waits until --interaction-timeout because "the challenge" never disappears — the page can never be fetched.

Reproduce

  1. Any WordPress page whose theme/plugin loads reCAPTCHA v3 site-wide (badge iframe present, no checkbox / no challenge).
  2. baoyu-fetch <url> --headlessgeneric requires manual interaction. Re-run with --wait-for interaction to continue after completing it.
  3. baoyu-fetch <url> --wait-for interaction --interaction-timeout 120000Please complete the reCAPTCHA verification in the opened Chrome window…Timed out waiting for google_recaptcha interaction

The same build fetches other pages fine (e.g. a Wikipedia article → clean 69 KB markdown), so this is specific to the gate.

Cause

skills/baoyu-url-to-markdown/scripts/lib/browser/interaction-gates.ts @ 6b7a2e4:

  • L92–95 hasRecaptcha: '.g-recaptcha, textarea[name="g-recaptcha-response"], iframe[title*="reCAPTCHA"]' — the v3 badge iframe has title="reCAPTCHA".
  • L97–98 hasRecaptchaIframe: iframe[src*="google.com/recaptcha"], iframe[src*="recaptcha/api2"] — v3 also loads from google.com/recaptcha/api2/anchor….
  • L40–45: any of these (or the literal word "recaptcha" in page text) → wait_for_interaction, requiresVisibleBrowser: true. There is no CLI flag to bypass the gate.

Suggested fix

Only gate when a real challenge is present, e.g.:

  • Ignore the passive badge: exclude iframes inside .grecaptcha-badge, and iframes with src*="recaptcha/api2/anchor" + size=invisible.
  • Gate on .g-recaptcha (v2 checkbox), a visible iframe[src*="recaptcha/api2/bframe"] (the actual challenge popup), or "I'm not a robot" text.
  • Optionally add an escape hatch such as --ignore-interaction <kind> / --no-interaction-gate for false positives.

Happy to open a PR if you'd like.