> For the complete documentation index, see [llms.txt](https://developers.oxylabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.oxylabs.io/products/cn/agent-browser/captcha-handling.md).

# CAPTCHA 处理

了解 Oxylabs 代理浏览器的 CAPTCHA 检测和处理机制及其使用方式。

{% hint style="warning" %}
`solve_captcha` CAPTCHA 处理参数正在逐步弃用。当前推荐方案请参见 [页面处理程序](/products/cn/agent-browser/ye-mian-chu-li-cheng-xu.md).
{% endhint %}

默认情况下，Oxylabs Agent Browser 不会自动处理 CAPTCHA。要在页面加载后立即启用自动检测和处理，请添加 `solve_captcha=true` 到你的连接 URL。

如果目标网站在多步骤交互过程中动态显示挑战，或者你需要高级事件监控和速度优化，可以使用下文记录的参数、事件和方法。

{% hint style="info" %}
**注意：** 访问成功率高度依赖目标站点。结果可能因目标站点的具体配置、执行级别（例如，被动指纹跟踪与主动挑战升级）以及会话住宅 IP 的实时信誉而异。
{% endhint %}

## 监控 CAPTCHA 事件

你可以监控求解器的生命周期。内部 `oxylabs-runtime` 浏览器扩展会将状态事件直接广播到浏览器的 `window` 对象。通过注册自定义的 "message" 事件监听器，你的脚本可以跟踪这些事件，以暂停和恢复操作。

<table><thead><tr><th width="243">事件类型</th><th>说明</th></tr></thead><tbody><tr><td><code>oxylabs-captcha-start</code></td><td>求解器已检测到 CAPTCHA 并启动处理流程。</td></tr><tr><td><code>oxylabs-captcha-end</code></td><td>求解器已成功完成并处理了挑战。</td></tr><tr><td><code>oxylabs-captcha-solve-end</code></td><td>成功后发出的备用完成事件。</td></tr><tr><td><code>oxylabs-captcha-error</code></td><td>求解器未能处理该挑战。</td></tr></tbody></table>

{% hint style="info" %}
自动求解 **默认禁用**。添加 `solve_captcha=true` 到你的连接 URL，以启用自动处理并开始触发这些事件。
{% endhint %}

### 代码示例

这些示例展示如何注入一个 `init` 脚本，以在页面导航前捕获运行时 CAPTCHA 事件，从而使脚本在处理期间暂停。

{% tabs %}
{% tab title="Python（Playwright）" %}

```python
from playwright.sync_api import sync_playwright

username = "USERNAME_abc12"
password = "PASSWORD"
endpoint = "hb.oxylabs.io"
# solve_captcha=true enables handling and event emission (off by default)
browser_url = f"wss://{username}:{password}@{endpoint}?solve_captcha=true"

def run():
    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(browser_url)
        ctx = browser.contexts[0]
        page = ctx.new_page()

        # Inject listener BEFORE navigation
        ctx.add_init_script("""
            window.addEventListener("message", (event) => {
                if (event.data && event.data.source === "oxylabs-runtime") {
                    window.__extensionStatus = event.data.type;
                }
            });
        """)

        page.goto("https://example.com/captcha-page", wait_until="domcontentloaded")

        # Wait for solver to complete (polls status flag)
        page.wait_for_function(
            """() => {
                const status = window.__extensionStatus;
                if (status === "oxylabs-captcha-error") {
                    throw new Error("CAPTCHA solving failed");
                }
                return status === "oxylabs-captcha-solve-end" || status === "oxylabs-captcha-end";
            }""",
            timeout=60000
        )
        print("CAPTCHA solved. Resuming automation...")
        browser.close()

if __name__ == "__main__":
    run()
```

{% endtab %}

{% tab title="JavaScript（Playwright）" %}

```javascript
import { chromium } from "playwright";

const username = "USERNAME_abc12";
const password = "PASSWORD";
const endpoint = "hb.oxylabs.io";
const browserUrl = `wss://${username}:${password}@${endpoint}?solve_captcha=true`;

(async () => {
    const browser = await chromium.connectOverCDP(browserUrl);
    const ctx = browser.contexts()[0];
    const page = await ctx.newPage();

    // Register init script to listen for oxylabs-runtime events
    await ctx.addInitScript(() => {
        window.addEventListener("message", (e) => {
            if (e.data?.source === "oxylabs-runtime") {
                window.__extensionStatus = e.data.type;
            }
        });
    });

    await page.goto("https://example.com/captcha-page", { waitUntil: "domcontentloaded" });

    try {
        // Halt script execution until CAPTCHA returns positive solve status
        await page.waitForFunction(() => {
            const status = window.__extensionStatus;
            if (status === "oxylabs-captcha-error") {
                throw new Error("CAPTCHA solving failed");
            }
            return status === "oxylabs-captcha-solve-end" || status === "oxylabs-captcha-end";
        }, null, { timeout: 60000 });

        console.log("CAPTCHA solved. Resuming automation...");
    } catch (err) {
        console.error("Error during bypass execution:", err.message);
    } finally {
        await browser.close();
    }
})();
```

{% endtab %}

{% tab title="JavaScript (Puppeteer)" %}

```javascript
import puppeteer from "puppeteer";

const username = "USERNAME_abc12";
const password = "PASSWORD";
const endpoint = "hb.oxylabs.io";
const browserUrl = `wss://${username}:${password}@${endpoint}?solve_captcha=true`;

(async () => {
    const browser = await puppeteer.connect({ browserWSEndpoint: browserUrl });
    const page = await browser.newPage();

    // Puppeteer alternative: Evaluate on document creation
    await page.evaluateOnNewDocument(() => {
        window.addEventListener("message", (e) => {
            if (e.data?.source === "oxylabs-runtime") {
                window.__extensionStatus = e.data.type;
            }
        });
    });

    await page.goto("https://example.com/captcha-page", { waitUntil: "domcontentloaded" });

    try {
        await page.waitForFunction(() => {
            const status = window.__extensionStatus;
            if (status === "oxylabs-captcha-error") {
                throw new Error("CAPTCHA solving failed");
            }
            return status === "oxylabs-captcha-solve-end" || status === "oxylabs-captcha-end";
        }, { timeout: 60000 });

        console.log("CAPTCHA solved. Resuming automation...");
    } catch (err) {
        console.error("Error during bypass execution:", err.message);
    } finally {
        await browser.close();
    }
})();
```

{% endtab %}
{% endtabs %}

## 动态手动触发

某些目标只会在用户操作后显示 CAPTCHA 挑战（例如，在点击交互式表单提交按钮或执行动态滚动之后）。

你可以在会话中的任意时刻使用 `window.postMessage` 事件直接发送到 window 对象：

```
window.postMessage({ action: "solve_captcha", type: "type_name" }, "*");
```

{% hint style="info" %}
如需了解更多受支持的 CAPTCHA 类型，请联系 Oxylabs 支持（[在线聊天](https://oxylabs.io/) 或 [电子邮件](mailto:support@oxylabs.io)）或你的专属客户经理。
{% endhint %}

### 标准触发模式

对于典型元素，请在执行用户操作后立即触发求解器：

```javascript
// 执行表单交互
await page.click("#form-submit-button");

// 为后期出现的 CAPTCHA 触发求解
await page.evaluate(() => {
    window.postMessage({ action: "solve_captcha", type: "type_name" }, "*");
});
```

{% hint style="info" %}
如需了解更多受支持的 CAPTCHA 类型或特定类型的例外情况，请联系 Oxylabs 支持（在线聊天或电子邮件）或你的专属客户经理以获取更多详情。
{% endhint %}

## 速度优化

处理 CAPTCHA 会增加自动化执行延迟。当抓取需要反复经过 CAPTCHA 门禁的目标时，可考虑以下方法以提升性能：

<table data-header-hidden><thead><tr><th width="175"></th><th></th></tr></thead><tbody><tr><td><strong>复用会话</strong></td><td>当远程浏览器会话在某个域名上完成一次 CAPTCHA 验证后，该验证会被保存。你可以在同一浏览器会话中重复导航或执行额外的页面步骤，而无需再次触发挑战求解流程。</td></tr><tr><td><strong>多标签页</strong></td><td>不要改用单独的 WebSocket 连接（它们会启动独立的沙箱，并带有空的 Cookie 池），而是在现有会话中打开多个标签页或上下文来并发执行任务，以减少所有页面的连接和验证时间。</td></tr><tr><td><strong>选择性启用</strong></td><td>由于 <code>solve_captcha</code> 默认关闭，只在需要的特定连接上启用它（<code>solve_captcha=true</code>)</td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers.oxylabs.io/products/cn/agent-browser/captcha-handling.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
