Browser Use में कस्टम टूल से कैप्चा कैसे हल करें

browser use captcha - How to Solve CAPTCHAs in Browser Use With a Custom Tool

अपने ब्राउज़र पर Browser Use में कैप्चा हल करने के लिए, एक कस्टम टूल रजिस्टर करें जो पेज से widget की sitekey पढ़े, CapSkip से token माँगे और उसे फॉर्म में लिख दे, फिर एजेंट को उसके सिस्टम मैसेज में बताएँ कि यह टूल मौजूद है। लोकल Chromium पर Browser Use में कैप्चा संभालने के लिए इतना काफ़ी है, सिवाय दो सीमाओं के, जो दोनों डिफ़ॉल्ट रूप से 180 सेकंड की हैं और जिन्हें बढ़ाना पड़ता है, क्योंकि reCAPTCHA का solve इन दोनों से ज़्यादा लंबा चल सकता है। सिस्टम मैसेज वाला हिस्सा वैकल्पिक नहीं है। Browser Use का डिफ़ॉल्ट सिस्टम प्रॉम्प्ट मॉडल से कहता है कि कैप्चा अपने आप हल हो जाते हैं, जो Browser Use के क्लाउड ब्राउज़रों पर सच है और लोकल Chromium पर गलत, इसलिए इस हिस्से के बिना एजेंट ऐसे solve का इंतज़ार करता रहता है जो कभी आता ही नहीं। यह गाइड Browser Use के लिए कैप्चा टूल को स्टेप-दर-स्टेप बनाती है, और इसे Browser Use 0.13.10 पर जाँचा गया है।

आपको क्या चाहिए

  • किसी Windows मशीन पर चलता हुआ CapSkip। नीचे दिया गया टूल reCAPTCHA v2 को संभालता है, invisible और Enterprise widgets समेत, और Cloudflare Turnstile widget को भी।
  • Python 3.11 या उसके बाद का संस्करण, जिसकी Browser Use को ज़रूरत है, साथ में browser-use और capskip पैकेज का 1.3.0 या उसके बाद का वर्ज़न। Browser Use मशीन पर मिलने वाले Chrome या Chromium को चलाता है।
  • आप एजेंट को जो भी chat मॉडल दें, उसकी API key; Claude के लिए उसे ANTHROPIC_API_KEY के रूप में सेट करें। सैंपल ChatAnthropic के ज़रिए Claude Opus 5.5 इस्तेमाल करते हैं, adaptive thinking चालू करके, और यह argument मायने रखता है: इसके बिना Browser Use 0.13.10 मॉडल की tool choice को force करता है, जिसे Claude Opus 5.5 और Sonnet 5.5 ठुकरा देते हैं, इसलिए हर स्टेप फेल हो जाता है।
  • सॉल्वर के लिए एक पता। Local मोड में CapSkip केवल उसी डिवाइस के लिए 127.0.0.1 पर जवाब देता है; Server मोड में वह आपके नेटवर्क पते या पब्लिक IP पर सुनता है, ताकि किसी दूसरी मशीन पर चल रहा एजेंट API के ज़रिए उसे कॉल कर सके। दोनों यहाँ सेट किए जाते हैं: कनेक्शन सेटिंग्स.
# Quoted, so cmd.exe does not read >= as a redirect
pip install browser-use "capskip>=1.3.0"

Browser Use लोकल ब्राउज़र पर कैप्चा को नज़रअंदाज़ क्यों करता है?

क्योंकि उसे ऐसा करने को कहा गया है। Browser Use अपनी डिफ़ॉल्ट सेटिंग्स में जो सिस्टम प्रॉम्प्ट इस्तेमाल करता है, उसके ब्राउज़र नियमों में यह लाइन है: "CAPTCHAs are automatically solved by the browser" (यानी ब्राउज़र कैप्चा अपने आप हल कर देता है), और उसके बाद निर्देश है कि उन्हें हाथ से हल करने की कोशिश न की जाए। यह Browser Use के क्लाउड ब्राउज़रों का वर्णन है, जो कैप्चा अपनी ही प्रॉक्सी में हल करते हैं और library को इसकी सूचना देते हैं। library में इसी से जुड़ा एक watchdog है, जो BrowserProfile की captcha_solver सेटिंग से चालू होता है (डिफ़ॉल्ट रूप से चालू), और जब कोई क्लाउड ब्राउज़र हल कर रहा हो, तब एजेंट को रोक देता है। यह सिर्फ़ उन्हीं events को सुनता है जो ये क्लाउड ब्राउज़र भेजते हैं।

आपकी अपनी मशीन के Chromium पर ऐसा कोई event कभी नहीं आता। एजेंट widget देखता है, नियमों पर भरोसा करता है, और इंतज़ार करता है, स्क्रॉल करता है या कोई दूसरा रास्ता आज़माता है, जब तक उसके स्टेप ख़त्म नहीं हो जाते। जब कोई रन इस तरह ख़त्म होता है, तो Browser Use अपने क्लाउड ब्राउज़रों पर जाने का सुझाव देता है। अगर आप ब्राउज़र को अपने ही हार्डवेयर पर रखना चाहते हैं, तो विकल्प यह है कि एजेंट को ऐसा टूल दें जो widget को सचमुच हल करे, और उसे दिए गए नियम को सुधार दें।

स्टेप 1: एक solve_captcha टूल रजिस्टर करें

कस्टम टूल async functions होते हैं, जिन्हें किसी Tools instance पर tools.action decorator से रजिस्टर किया जाता है। Browser Use कुछ ख़ास parameters नाम से inject करता है: browser_session आपको लाइव session देता है और page_url मौजूदा पेज का पता। टूल को JavaScript के दो छोटे टुकड़े चाहिए, एक widget ढूँढने के लिए और एक token भरने के लिए।

FIND = """() => {
  const w = document.querySelector(
    '.g-recaptcha[data-sitekey], .cf-turnstile[data-sitekey]');
  if (!w) return null;
  return {
    kind: w.classList.contains('cf-turnstile') ? 'turnstile' : 'recaptcha',
    sitekey: w.dataset.sitekey,
    invisible: w.dataset.size === 'invisible' || w.tagName !== 'DIV',
    enterprise: !!document.querySelector(
      'script[src*="recaptcha/enterprise.js"]'),
    callback: w.dataset.callback || null,
  };
}"""

FILL = """(kind, token, callback) => {
  const name = kind === 'turnstile' ? 'cf-turnstile-response'
                                    : 'g-recaptcha-response';
  const fields = document.querySelectorAll(`[name="${name}"]`);
  fields.forEach(f => { f.value = token; });
  if (callback && typeof window[callback] === 'function') {
    window[callback](token);
  }
  return fields.length;
}"""

दोनों arrow functions के रूप में लिखे गए हैं, क्योंकि page object का evaluate method इसके अलावा कुछ भी स्वीकार नहीं करता। यह अतिरिक्त arguments को JSON के रूप में पास करता है, और हमेशा एक स्ट्रिंग लौटाता है: object, JSON-encoded होकर लौटता है, number अपने अंकों के रूप में, और null एक खाली स्ट्रिंग के रूप में। FILL, token को widget के बनाए response फ़ील्ड में लिखता है, और अगर widget ने data-callback में किसी function का नाम दिया है तो उसे कॉल करता है, क्योंकि कुछ फॉर्म फ़ील्ड पढ़ने के बजाय उस callback का इंतज़ार करते हैं।

FIND दो ऐसी चीज़ें भी पढ़ता है जिन पर solve निर्भर करता है। किसी button से बँधा widget, data-size attribute के बिना भी invisible होता है, इसलिए कोई भी g-recaptcha element जो div नहीं है, invisible माना जाता है। और जो पेज Google की enterprise.js script लोड करता है, उसे reCAPTCHA Enterprise के रूप में हल किया जाता है, क्योंकि Enterprise widgets भी standard widgets वाला ही markup इस्तेमाल करते हैं।

@tools.action(
    "Solve the reCAPTCHA v2 or Cloudflare Turnstile widget on the current "
    "page. Call it after the other fields are filled, then submit the form "
    "unless the page has already moved on."
)
async def solve_captcha(browser_session: BrowserSession, page_url: str):
    page = await browser_session.must_get_current_page()
    raw = await page.evaluate(FIND)
    widget = json.loads(raw) if raw else None
    if not widget:
        return ActionResult(error="No reCAPTCHA or Turnstile widget found.")

    try:
        if widget["kind"] == "turnstile":
            result = await solver.turnstile(widget["sitekey"], page_url)
        else:
            extra = {"invisible": 1} if widget["invisible"] else {}
            result = await solver.recaptcha(
                widget["sitekey"], page_url,
                enterprise=int(widget["enterprise"]), **extra)
    except CapSkipError as exc:
        return ActionResult(error=f"CapSkip did not solve it: {exc!r}")

    filled = await page.evaluate(
        FILL, widget["kind"], result["code"], widget["callback"])
    if filled == "0":
        return ActionResult(error="Solved, but no response field to fill.")
    return ActionResult(
        extracted_content=f"Solved the {widget['kind']} CAPTCHA on {page_url} "
                          "and filled in the token. Submit the form now, "
                          "unless the page has already moved on.",
    )

description स्ट्रिंग ही वह चीज़ है जिसे मॉडल यह तय करते समय पढ़ता है कि कौन सा action ले, इसलिए उसमें यह भी लिखा है कि टूल कब कॉल करना है, और यह भी कि वह क्या करता है। सफलता का संदेश सिर्फ़ extracted_content में जाता है। जब कोई ActionResult, long_term_memory भी सेट करता है, तो Browser Use मॉडल को memory दिखाता है और content हटा देता है, इसलिए content में रखा गया "Submit the form now" जैसा निर्देश कभी पहुँचता ही नहीं। हर नाकामी exception के बजाय एक ActionResult के रूप में लौटती है, जिसमें ऐसा error होता है जिसे मॉडल पढ़कर उस पर प्रतिक्रिया दे सके।

यहाँ synchronous CapSkip क्लाइंट नहीं, AsyncCapSkip इस्तेमाल करें। Browser Use ब्राउज़र connection को उसी event loop पर चलाता है जिस पर आपका टूल चलता है, और एक blocking solve, जितनी देर solve चले, उतनी देर सब कुछ जाम कर देगा। Python में AsyncCapSkip कोई alias नहीं, बल्कि सचमुच का asyncio क्लाइंट है।

स्टेप 2: एजेंट को बताएँ कि टूल मौजूद है

टूल्स को एजेंट को पास करें और उसके सिस्टम मैसेज में एक पैराग्राफ़ जोड़ें। extend_system_message डिफ़ॉल्ट प्रॉम्प्ट के बाद जोड़ा जाता है, इसलिए वह उस नियम के बाद आता है जिसे उसे सुधारना है।

EXTRA = (
    "This browser does not solve CAPTCHAs on its own, whatever the rules "
    "above say. When a page shows a reCAPTCHA or Turnstile widget, fill in "
    "the other fields, call solve_captcha, then submit the form unless the "
    "page has already moved on. Never click the CAPTCHA checkbox or "
    "challenge yourself."
)

agent = Agent(
    task="Sign up at https://example.com/signup with YOUR_EMAIL.",
    llm=ChatAnthropic(model="claude-opus-5-5", thinking={"type": "adaptive"}),
    tools=tools,
    extend_system_message=EXTRA,
    step_timeout=420,
)

उस पैराग्राफ़ में क्रम मायने रखता है। reCAPTCHA token सिर्फ़ करीब दो मिनट तक वैध रहता है, जैसा reCAPTCHA token expiration की गाइड में बताया गया है, और मॉडल के हर स्टेप में कुछ सेकंड लगते हैं। पहले हल करना और फिर लंबा फॉर्म भरना token को सबमिट से पहले expire होने दे सकता है, इसलिए एजेंट से सबसे आख़िर में हल करने को कहा गया है। मॉडल तीनों काम एक ही स्टेप में कर सकता है, टाइप करना, हल करना और सबमिट पर क्लिक करना, और Browser Use एक स्टेप के actions क्रम से चलाता है। पेज के आगे बढ़ जाने के बारे में जो वाक्यांश है, वह invisible widgets के लिए है। उनका callback आमतौर पर फॉर्म खुद सबमिट कर देता है, इसलिए जब तक FILL उसे कॉल करता है, पेज पहले ही आगे बढ़ चुका होता है, और दूसरा क्लिक बस फेल ही होगा।

ChatAnthropic पर thinking argument सिर्फ़ सजावट नहीं है। Browser Use, Claude से उसका अगला action एक tool call के ज़रिए माँगता है, और वर्ज़न 0.13.10 में, thinking के बिना, वह उस tool choice को force करता है। Claude Opus 5.5 और Sonnet 5.5 force की गई tool choice को 400 के साथ ठुकरा देते हैं, इसलिए एजेंट हर स्टेप पर फेल होगा। adaptive thinking चालू होने पर Browser Use मॉडल को टूल चुनने देता है, और रिक्वेस्ट पास हो जाती है।

स्टेप 3: 180 सेकंड की दोनों सीमाएँ बढ़ाएँ

Browser Use में कैप्चा का solve दो अलग-अलग घड़ियों के भीतर पूरा होना चाहिए, और दोनों का डिफ़ॉल्ट 180 सेकंड है।

  • प्रति-action सीमा। हर action एक timeout में लिपटा होता है जो BROWSER_USE_ACTION_TIMEOUT_S एनवायरनमेंट वेरिएबल से पढ़ा जाता है, और एजेंट कभी अपनी कोई वैल्यू पास नहीं करता। इसे सिर्फ़ एक बार पढ़ा जाता है, जब Browser Use पहली बार अपना tools module लोड करता है, और Agent या Tools का कोई भी import यही करता है, इसलिए उसके बाद इसे सेट करने का कोई असर नहीं होता।
  • स्टेप का timeout। Agent का step_timeout पूरे स्टेप को कवर करता है: पेज की state तैयार करना, मॉडल कॉल, जिसके लिए Browser Use खुद मॉडल के हिसाब से 90 सेकंड तक देता है, और स्टेप का हर action।

दूसरी तरफ़, SDK किसी reCAPTCHA के लिए 300 सेकंड (recaptchaTimeout) तक poll करता है, और CapSkip की अपनी reCAPTCHA सेटिंग्स किसी task को thread के इंतज़ार के लिए 250 सेकंड तक और हल करने के लिए 250 सेकंड और देती हैं। ज़्यादातर solve इससे बहुत पहले पूरे हो जाते हैं, लेकिन queue या कोई धीमी प्रॉक्सी किसी solve को 180 सेकंड के पार ले जा सकती है। दोनों सीमाएँ डिफ़ॉल्ट पर हों, तो स्टेप का timeout पहले चलता है, क्योंकि स्टेप action से पहले शुरू हुआ था, और एजेंट रिपोर्ट करता है कि स्टेप 180 सेकंड बाद timeout हो गया। सिर्फ़ step_timeout बढ़ाएँ, तो action की सीमा हावी हो जाती है: वह poll के बीच में ही solve को रद्द कर देती है और रिपोर्ट करती है कि ब्राउज़र शायद जवाब नहीं दे रहा, और साथ में एक dead CDP WebSocket का नाम लेती है। यहाँ यह संदेश गुमराह करने वाला है। ब्राउज़र ठीक है; solve बस सीमा से ज़्यादा देर चला। दोनों सीमाएँ SDK की सीमा से ऊपर सेट करें।

import os

# Before anything imports Agent or Tools from browser_use.
os.environ.setdefault("BROWSER_USE_ACTION_TIMEOUT_S", "330")

from browser_use import Agent  # noqa: E402

# Up to 300 s of SDK polling (a few more for the last poll), one
# model call (90 s for Claude) and the page state, with room to spare.
agent = Agent(task="...", llm=llm, tools=tools,
              extend_system_message=EXTRA, step_timeout=420)

timeout हुआ स्टेप एजेंट की लगातार नाकामियों में भी गिना जाता है, और लगातार पाँच नाकामियाँ एजेंट को रोक देती हैं, इसलिए बहुत तंग सीमा की कीमत एक दोबारा कोशिश से ज़्यादा होती है।

सर्वर पर CapSkip चलाना

टूल आपकी Python प्रोसेस में, एजेंट के साथ ही चलता है। मायने यह रखता है कि वह प्रोसेस कहाँ चलती है, यह नहीं कि ब्राउज़र कहाँ है: session का cdp_url किसी दूसरी मशीन के Chrome की ओर इशारा करे, तब भी solve आपकी script से ही CapSkip तक जाता है। जब तक script और CapSkip एक ही Windows PC पर हों, 127.0.0.1 सही है। जब एजेंट किसी VPS, CI runner या किसी दूसरी मशीन पर scheduled job में चला जाता है, तो loopback गलत मशीन की ओर इशारा करता है और टूल अपने error के रूप में एक NetworkException लौटाता है। CapSkip को Server मोड पर कर दें और वह आपके नेटवर्क पते या पब्लिक IP पर सुनने लगता है, ताकि एजेंट उसी API के ज़रिए उसे कॉल कर सके। जब रास्ता इंटरनेट से होकर जाए तो स्टैटिक पब्लिक IP इस्तेमाल करें, API key validation चालू करें, और Windows Firewall नियम से पोर्ट को सीमित रखें। सॉल्वर आपकी अपनी Windows मशीन पर ही रहता है, और एजेंट चाहे कितने भी कैप्चा से टकराए, solve बिना मीटर वाले ही रहते हैं।

SDK एनवायरनमेंट वेरिएबल खुद नहीं पढ़ता। CAPSKIP_HOST, CAPSKIP_PORT और CAPSKIP_API_KEY को अपने कोड में पढ़ें और उन्हें AsyncCapSkip को पास करें, जैसा पूरा उदाहरण करता है।

पूरा चलने वाला उदाहरण

# pip install browser-use "capskip>=1.3.0"
import asyncio
import json
import os

# Browser Use reads this once, when its tools load, so set it first.
os.environ.setdefault("BROWSER_USE_ACTION_TIMEOUT_S", "330")

from browser_use import ActionResult, Agent, BrowserSession, ChatAnthropic, Tools
from capskip import AsyncCapSkip, CapSkipError

solver = AsyncCapSkip(
    apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
    host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.getenv("CAPSKIP_PORT", "8080")),
)
tools = Tools()

FIND = """() => {
  const w = document.querySelector(
    '.g-recaptcha[data-sitekey], .cf-turnstile[data-sitekey]');
  if (!w) return null;
  return {
    kind: w.classList.contains('cf-turnstile') ? 'turnstile' : 'recaptcha',
    sitekey: w.dataset.sitekey,
    invisible: w.dataset.size === 'invisible' || w.tagName !== 'DIV',
    enterprise: !!document.querySelector(
      'script[src*="recaptcha/enterprise.js"]'),
    callback: w.dataset.callback || null,
  };
}"""

FILL = """(kind, token, callback) => {
  const name = kind === 'turnstile' ? 'cf-turnstile-response'
                                    : 'g-recaptcha-response';
  const fields = document.querySelectorAll(`[name="${name}"]`);
  fields.forEach(f => { f.value = token; });
  if (callback && typeof window[callback] === 'function') {
    window[callback](token);
  }
  return fields.length;
}"""


@tools.action(
    "Solve the reCAPTCHA v2 or Cloudflare Turnstile widget on the current "
    "page. Call it after the other fields are filled, then submit the form "
    "unless the page has already moved on."
)
async def solve_captcha(browser_session: BrowserSession, page_url: str):
    page = await browser_session.must_get_current_page()
    raw = await page.evaluate(FIND)
    widget = json.loads(raw) if raw else None
    if not widget:
        return ActionResult(error="No reCAPTCHA or Turnstile widget found.")
    try:
        if widget["kind"] == "turnstile":
            result = await solver.turnstile(widget["sitekey"], page_url)
        else:
            extra = {"invisible": 1} if widget["invisible"] else {}
            result = await solver.recaptcha(
                widget["sitekey"], page_url,
                enterprise=int(widget["enterprise"]), **extra)
    except CapSkipError as exc:
        return ActionResult(error=f"CapSkip did not solve it: {exc!r}")
    filled = await page.evaluate(
        FILL, widget["kind"], result["code"], widget["callback"])
    if filled == "0":
        return ActionResult(error="Solved, but no response field to fill.")
    return ActionResult(
        extracted_content=f"Solved the {widget['kind']} CAPTCHA on {page_url} "
                          "and filled in the token. Submit the form now, "
                          "unless the page has already moved on.",
    )


EXTRA = (
    "This browser does not solve CAPTCHAs on its own, whatever the rules "
    "above say. When a page shows a reCAPTCHA or Turnstile widget, fill in "
    "the other fields, call solve_captcha, then submit the form unless the "
    "page has already moved on. Never click the CAPTCHA checkbox or "
    "challenge yourself."
)


async def main():
    agent = Agent(
        task="Sign up at https://example.com/signup with YOUR_EMAIL, "
             "then report what the page says.",
        # Adaptive thinking lets Browser Use leave the tool choice to Claude.
        llm=ChatAnthropic(model="claude-opus-5-5", thinking={"type": "adaptive"}),
        tools=tools,
        extend_system_message=EXTRA,
        step_timeout=420,
    )
    history = await agent.run(max_steps=25)
    print(history.final_result())


asyncio.run(main())

हमने यह loop शुरू से आख़िर तक टेस्ट पेजों पर चलाया: एक checkbox widget, button से बँधा एक invisible widget, एक Enterprise पेज और एक Turnstile widget, और मॉडल की जगह एक scripted विकल्प रखा ताकि हर स्टेप पहले से तय रहे। प्रॉम्प्ट डिफ़ॉल्ट नियमों के बाद अतिरिक्त पैराग्राफ़ के साथ पहुँचता है, solve_captcha उन actions में दिखता है जिन्हें मॉडल चुन सकता है, token फॉर्म में पहुँचता है, data-callback function चलता है, टूल का निर्देश मॉडल तक पहुँचता है, और सबमिट स्वीकार होता है। हमने ChatAnthropic की भेजी रिक्वेस्ट भी कैप्चर की, यह पक्का करने के लिए कि adaptive thinking, tool choice मॉडल पर छोड़ देता है। असली मॉडल के साथ फ़र्क़ सिर्फ़ इतना है कि टूल कब कॉल करना है, यह मॉडल तय करता है, और description और अतिरिक्त पैराग्राफ़ इसी के लिए हैं। दोनों methods के पीछे के raw endpoints यहाँ दर्ज हैं: API रेफ़रेंस.

आम errors और उनका मतलब

आप जो देखते हैंकारणफिक्स
कैप्चा वाले पेज पर एजेंट इंतज़ार करता है, स्क्रॉल करता है या हार मान लेता है, और टूल कभी कॉल नहीं करताडिफ़ॉल्ट सिस्टम प्रॉम्प्ट कहता है कि कैप्चा अपने आप हल हो जाते हैं, और किसी ने इसे सुधारा नहींस्टेप 2 वाले पैराग्राफ़ के साथ extend_system_message पास करें
हर स्टेप एक 400 के साथ फेल होता है, जो कहता है कि इस मॉडल के लिए tool_choice type सपोर्टेड नहीं हैChatAnthropic को thinking के बिना बनाया गया, इसलिए Browser Use ने tool choice को force कियाChatAnthropic को thinking={"type": "adaptive"} पास करें
180 सेकंड बाद एक स्टेप timeout हो गयाधीमा solve और मॉडल कॉल मिलकर step_timeout से ज़्यादा लंबे चलेAgent को step_timeout=420 पास करें, और action की सीमा भी बढ़ाएँ
Action solve_captcha timed out after 180s. The browser may be unresponsive (dead CDP WebSocket).step_timeout बढ़ाने के बाद solve प्रति-action सीमा से ज़्यादा लंबा चला; ब्राउज़र ठीक हैBrowser Use लोड होने से पहले BROWSER_USE_ACTION_TIMEOUT_S को 300 से ऊपर सेट करें
वेरिएबल सेट है, फिर भी सीमा 180 सेकंड ही हैइसे Agent या Tools के import हो जाने के बाद सेट किया गयाassignment को entry script में सबसे ऊपर ले जाएँ, हर उस import से पहले जो browser_use को लाता है
कैप्चा हल होने के दौरान पूरा एजेंट जाम हो जाता हैsynchronous CapSkip क्लाइंट उस event loop को block कर रहा है जिस पर ब्राउज़र connection चलता हैAsyncCapSkip इस्तेमाल करें और उसके methods को await करें
टूल बताता है कि कोई widget नहीं मिलापेज widget को data-sitekey के बिना script से रेंडर करता है, उसे iframe में रखता है, या कोई दूसरा कैप्चा इस्तेमाल करता हैDevTools में widget की अपनी रिक्वेस्ट से sitekey पढ़ें, और उस पेज के लिए FIND और FILL को बढ़ाएँ; दोनों top-level document में चलते हैं, इसलिए iframe के अंदर वाले फॉर्म के लिए अलग lookup चाहिए
हल हो गया, पर भरने के लिए कोई response फ़ील्ड नहींTurnstile widget अपने फ़ील्ड का नाम data-response-field-name से बदल देता है, या data-response-field से उसे बंद कर देता हैFIND में वह attribute पढ़ें और token को उसी नाम वाले फ़ील्ड में लिखें
token भर दिया गया, फिर भी साइट सबमिट ठुकरा देती हैtoken सबमिट से पहले expire हो गया, या फॉर्म ऐसे callback का इंतज़ार करता है जिसे उसने script में register किया थाएजेंट से ठीक सबमिट से पहले हल करवाएँ, और अगर data-callback खाली है तो पेज का अपना callback कॉल करें
पेज किसी button पर reCAPTCHA v3 इस्तेमाल करता हैFIND उसे v2 मान लेता हैsolver.recaptcha को version v3 और पेज के action के साथ कॉल करें
टूल का error एक NetworkException हैCapSkip चल नहीं रहा, या एजेंट जहाँ चलता है उसके हिसाब से host और port गलत हैंCapSkip शुरू करें, फिर देखें कि उसे Local मोड में होना चाहिए या Server मोड में

FAQ

क्या Browser Use खुद कैप्चा हल करता है?

सिर्फ़ अपने क्लाउड ब्राउज़रों पर, जहाँ हल करने का काम Browser Use की अपनी प्रॉक्सी में होता है और library उसका इंतज़ार करती है। open-source library में ऐसा कुछ नहीं आता जो आपके खुद चलाए गए ब्राउज़र पर कैप्चा हल करे, चाहे वह लोकल Chromium हो या CDP URL के ज़रिए जुड़ा आपका अपना Chrome। यह गाइड इसी सेटअप के लिए है।

क्या मैं इसके बजाय एजेंट को CapSkip का MCP सर्वर दे सकता हूँ?

हाँ, दे सकते हैं। Browser Use किसी MCP सर्वर के टूल अपने Tools instance में लोड कर सकता है, और CapSkip का MCP सर्वर हर सपोर्टेड टाइप के लिए एक solve टूल देता है। लेकिन वे टूल token लौटाते हैं, इसलिए फिर मॉडल को खुद अपनी script से उसे पेज में लिखना पड़ता है। यानी मॉडल के लिए एक के बजाय दो फ़ैसले, और दूसरे फ़ैसले को हर पेज के markup से मेल खाना होता है। कस्टम टूल पेज को पढ़ने और उसमें लिखने का काम कोड में ही रखता है। MCP वाला रास्ता उन एजेंट के लिए ठीक है जिनमें आप कोड नहीं जोड़ सकते, और MCP कैप्चा सॉल्वर पेज पर बताया गया है कि ऐसे एजेंट को कैसे जोड़ें।

hCaptcha या full-page Cloudflare challenge का क्या?

CapSkip, hCaptcha हल नहीं करता, इसीलिए FIND सिर्फ़ reCAPTCHA और Turnstile classes से मैच करता है, h-captcha widget से कभी नहीं। full-page Cloudflare challenge, Turnstile widget से अलग flow है: इसके लिए challenge की cData और chlPageData वैल्यू चाहिए, और token के साथ लौटा user agent भी, जैसा Cloudflare Turnstile सॉल्वर पेज पर बताया गया है, इसलिए यह टूल अपने मौजूदा रूप में इसे कवर नहीं करता। CapSkip के दूसरे टाइप, जैसे GeeTest या Capy Puzzle, इसी टूल में और branches के रूप में जोड़े जा सकते हैं।

क्या क्लाउड में चल रहा एजेंट मेरे सॉल्वर तक पहुँच सकता है?

हाँ। कनेक्शन सेटिंग्स में CapSkip को Server मोड पर कर दें ताकि वह loopback के बजाय किसी नेटवर्क पते पर सुने, एजेंट जहाँ चलता है वहाँ वह पता CAPSKIP_HOST से पढ़ें, और उसे AsyncCapSkip को पास करें। VPS, कंटेनर होस्ट, CI runner और किसी क्लाउड प्लेटफ़ॉर्म पर चलने वाला scheduled job, सब उसी HTTP API के ज़रिए जुड़ते हैं। जब रास्ता इंटरनेट से होकर जाए, तो स्टैटिक पब्लिक IP और फ़ायरवॉल नियम इस्तेमाल करें। सॉल्वर आपके अपने हार्डवेयर पर ही रहता है, इसलिए एजेंट का ऐसा लंबा रन भी, जो हर पेज पर कैप्चा से टकराता है, कोई अतिरिक्त ख़र्च नहीं करवाता।

संक्षेप में

अपने ब्राउज़र पर Browser Use में कैप्चा संभालने के लिए चार बदलाव चाहिए, और जब एजेंट सॉल्वर की मशीन से हटकर कहीं और चले, तो एक पाँचवाँ भी। एक solve_captcha टूल रजिस्टर करें जो page.evaluate से sitekey पढ़े, AsyncCapSkip को await करे और token वापस लिखे, और अगर widget का callback हो तो उसे कॉल करे। extend_system_message से डिफ़ॉल्ट नियम सुधारें, ताकि एजेंट सबमिट करने से ठीक पहले टूल कॉल करे। ChatAnthropic को adaptive thinking पास करें, ताकि Claude रिक्वेस्ट स्वीकार करे। Browser Use लोड होने से पहले BROWSER_USE_ACTION_TIMEOUT_S और Agent पर step_timeout बढ़ाएँ, दोनों को SDK के 300 सेकंड से ऊपर। और जब एजेंट सॉल्वर की मशीन के अलावा कहीं और चले, तो CapSkip को Server मोड पर कर दें।

घंटों ब्राउज़ करने वाला एजेंट हर दूसरे पेज पर challenge से टकरा सकता है, और आपकी अपनी Windows मशीन पर चलने वाला कैप्चा बायपास हर challenge को बिना किसी प्रति-हल शुल्क के हल कर देता है।