CAPSOLVER
博客
如何在 Go 的 chromedp 中添加 CAPTCHA 解题器

如何在 Go 的 chromedp 中添加验证码(CAPTCHA)求解器

Logo of CapSolver

Lucas Mitchell

How to use CapSolver

02-Nov-2026

摘要

  • chromedp 通过 Go 控制 Chrome;在允许的流程需要验证码结果时,由单独的验证码服务提供解题结果。
  • 固定 chromedp 版本,因为当前示例使用的 API 与旧教程不同。
  • 在运行付费挑战前,分别测试浏览器访问能力和求解服务的 API 连接。
  • 同时检查 Go 错误和 API 的 ErrorId;Go 错误为 nil 并不代表服务调用成功。
  • 把浏览器当前挑战所用输入保持在一起,在应用结果后再检查页面状态。

chromedp 是一个基于 Go 的库,通过 Chrome DevTools Protocol 控制浏览器。开发者可以利用它做浏览器测试和自动化,而无需引入 Python 或 JavaScript 控制器。当被授权的浏览器任务遇到支持的 CAPTCHA 时,Go 应用可以调用求解服务,并继续操控同一页面。

CapSolver 提供了官方 Go SDK 和文档化的任务 API 用于求解步骤。本文将这两部分串联起来,但不会把浏览器库伪装成求解器。可运行检查使用本地自有浏览器 fixture 和一个带有刻意无效占位 key 的真实 API 请求。它验证的是线路和错误处理,而不是付费求解。

CAPTCHA 求解在 chromedp 中处于什么位置?

CAPTCHA 求解位于收集当前挑战参数和继续需要该结果的浏览器操作之间。

chromedp 官方仓库 提供浏览器控制能力。你的 Go 程序会打开被允许的页面,读取相关状态,并在需要处理受支持的挑战时做出判断。求解服务提供文档规定的输出;chromedp 仍然负责随后的页面操作。

CAPTCHA 本身并不能证明每一次浏览器阻塞都需要发起求解请求。缺失字段、导航失败或应用错误可能需要其它修复。应先识别真正的挑战,再选择任务类型。

对于自有 QA 表单,流程相对简单:打开表单,识别其 CAPTCHA 配置,在合适的时机请求解题,通过应用期望的集成路径提交结果,并检查表单确认信息。本文不会为任意网站提供通用回调或通用提交流脚本。

安装兼容的 Go 依赖

使用隔离的 Go 模块并固定依赖版本,以便文中的 API 调用与实际构建保持一致。

本文检查的环境使用 Go 1.27.3、github.com/chromedp/chromedp@v0.21.0 和 github.com/capsolver/capsolver-go@v0.0.0-20251204081438-e4e07af23eae。Chrome 安装在本地,并通过单独的临时浏览器上下文启动。

创建工作目录,用 go mod init captcha-browser-check 初始化模块,然后运行:

go get github.com/chromedp/chromedp@v0.21.0 github.com/capsolver/capsolver-go@v0.0.0-20251204081438-e4e07af23eae

v0.21.0 版本说明 指出支持 Go 1.25 及之后的版本。在迁移旧浏览器脚本时,请使用该版本的文档。把旧的指针输出示例和新的强类型 action API 混合使用,可能会在任何浏览器或求解请求运行之前就触发编译错误。

官方余额 API 文档 包含 Go SDK 的 Balance() 方法。余额查询有助于把账号/API 访问与特定挑战求解区分开。它不会创建 CAPTCHA 任务。

运行浏览器和 API 连接检查

运行一个小检查,以证明 Chrome 可以读取自有页面,并且 Go SDK 能收到真实的 API 响应。

将以下代码保存为 main.go,然后在初始化好的模块中运行 go run .。本地 FIXTURE_ONLY 属性是测试数据,而不是真实的 sitekey。API key 故意无效,程序预期服务会拒绝它。

go 复制代码
package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "net/http/httptest"
    "time"
    "github.com/chromedp/chromedp"
    capsolver "github.com/capsolver/capsolver-go"
)

func main() {
    // 本地 fixture 用于检查浏览器线路,它不是真实 CAPTCHA。
    fixture := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, `<title>Owned QA fixture</title><div id="widget" data-sitekey="FIXTURE_ONLY"></div>`)
    }))
    defer fixture.Close()
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()
    ctx, deadline := context.WithTimeout(ctx, 30*time.Second)
    defer deadline()
    if err := chromedp.Do(ctx, chromedp.Navigate(fixture.URL)); err != nil { log.Fatal(err) }
    sitekey, err := chromedp.Run(ctx, chromedp.AttributeValue("#widget", "data-sitekey"))
    if err != nil { log.Fatal(err) }
    if !sitekey.Exists || sitekey.Value != "FIXTURE_ONLY" { log.Fatal("Fixture key not found") }; fmt.Println("Fixture key:", sitekey.Value)
    // 故意使用无效凭证:检查真实 API 错误,而不是账号。
    solver := capsolver.CapSolver{ApiKey: "YOUR_API_KEY"}
    result, err := solver.Balance()
    if err != nil { log.Fatal(err) }
    fmt.Println("API error:", result.ErrorId, result.ErrorCode)
    if result.ErrorId == 0 { log.Fatal("Expected the placeholder credential to be rejected") }
}

验证运行时会先打印 Fixture key: FIXTURE_ONLY,然后打印 ErrorId 为 1 且错误码为 ERROR_KEY_DOES_NOT_EXIST 的 API 错误。应把该特定错误视作对这个占位检查的观测结果,而不是对任意无效凭证的结果承诺。

这样就建立了本地浏览器访问能力和 API 的真实请求-响应路径。没有查询真实账号、没有解任何挑战,也没有执行任何表单提交。

显式检查返回的属性

当前的 AttributeValue 动作返回一个 AttributeResult,其中包含属性值和存在标记。

示例会在继续之前检查这两个字段。缺失的属性应阻止参数收集,而不是在付费请求中变成空的 sitekey。适用于本地 fixture 的选择器不应被视为适用于所有 CAPTCHA 集成的通用选择器。

将业务错误与 Go 错误分开检查

当前检查过的 SDK 可以在不返回 Go 错误的情况下,返回一个已解析的服务响应。

这就是示例在处理完 err 之后还要检查 result.ErrorId 的原因。网络失败、JSON 解析失败,以及描述账号错误的有效响应属于不同情况。应阅读返回的完整响应,而不是假设 err == nil 就表示账号或任务成功。

兑换你的 CapSolver 奖励码

即时提升你的自动化预算!
在为 CapSolver 账号充值时使用奖励码 CAP26,每笔充值都可额外获得 5% 奖励 —— 无上限。
立刻在你的 CapSolver 控制台 中兑换。
CapSolver recharge promotion showing bonus code CAP26

将当前挑战映射到文档化任务

基于你实际检查到的页面,利用选定 CAPTCHA 的当前任务文档构造求解请求。

对于 reCAPTCHA v2,官方任务文档 说明了任务家族以及 websiteURL、websiteKey 等字段。使用文档中规定的拼写和大小写。不要凭记忆构造任务名,也不要在未经检查当前约定的前提下复制旧 SDK 示例。

官方 Go SDK 为任务 map 暴露了 Solve() 方法。生产实现应以安全方式提供真实凭证,传入当前任务参数,并根据固定的 SDK 版本检查返回的结果或错误。

上面的连接检查刻意不是完整的付费求解程序。在部署求解步骤前,应使用你自己有资金的账号,对一个被允许的挑战做一次测试,并在自有应用中验证结果。由于本文没有执行该与凭证相关的步骤,因此不声明任何成功率或端到端完成度。

保持页面 URL、挑战类型、公钥以及必需的可选参数与同一个浏览器操作关联。如果导航替换了页面或重新生成了挑战,在发起下一次尝试前应重新检查输入。

通过页面实际集成方式应用结果

以自有应用期望的方式使用解题结果,然后确认应用行为按预期发生变化。

基于 token 的结果并不是让你“点击任何可见验证按钮”的指令。有些应用通过回调处理,有些会把结果绑定到表单上,最后的服务端验证仍然很重要。应查阅应用自身的实现,而不是猜测一个 JavaScript 回调名称。

Google 的 响应验证文档 解释了 reCAPTCHA 的服务器端验证步骤。浏览器自动化在求解后继续执行某一行代码,并不等于服务器已经接受了该响应。

保持测试的成功条件足够具体。对于自有表单,应检查其确认或测试记录;对于被允许的读取流程,应检查预期内容。避免只把 widget 消失视作唯一完成信号,而忽略应用本身更可靠的结果。

在不重复整个流程的前提下诊断失败

先诊断出失败组件,再重新跑导航、账号检查和求解。

编译错误指向代码和依赖兼容性问题。浏览器启动失败指向可执行文件或运行环境。缺失 key 指向页面检查。服务错误指向文档化 API 响应。解题后表单仍被拒绝则指向结果应用方式和应用自身。

对于输入契约相关的失败,invalid-task-data 故障排查指南 展示了如何将实际请求与选定任务进行对比。更多的浏览器重试并不能修正请求中拼写错误的字段。

保留一个小型诊断记录,其中包含包版本、失败阶段、可用时的任务 ID,以及经脱敏的错误信息。不要记录真实账号 key 或完整解题 token。在向上汇报时,应分别说明浏览器检查和 API 检查各自已经证明了什么。

使用 CapSolver 构建可靠的自动化流程

让 chromedp 负责浏览器控制,并仅在真正出现 CAPTCHA 步骤时调用有文档的求解接口。CapSolver 提供求解接口;你的应用则负责页面状态、错误决策以及最终完成检查。

常见问题

问:chromedp 自带 CAPTCHA 求解能力吗?

chromedp 是浏览器控制器。本文工作流是在被允许的任务中遇到受支持挑战时,额外接入独立求解服务。

问:示例会消耗求解额度吗?

不会创建任何付费任务。示例只会使用一个刻意无效的占位 key 发送余额请求,并检查返回错误。

问:为什么 API 会在 Go 错误为 nil 时仍然拒绝请求?

因为 SDK 可能已经成功接收并解析了一个包含服务级错误的响应。应同时检查响应中的错误字段和 Go 错误。

问:我可以把 FIXTURE_ONLY 当作我的 sitekey 吗?

不可以。它只是用于验证浏览器属性读取的本地测试数据。真实求解任务需要来自被允许页面的当前公钥。

问:本文有没有测试完整的付费 CAPTCHA 求解流程?

没有。已验证的范围仅包括 chromedp 浏览器 fixture 和一次真实的 API 拒绝。付费求解及其在自有应用中的接受情况,需要你的账号和单独的端到端测试。

合规声明: 本博客提供的信息仅供参考。CapSolver 致力于遵守所有适用的法律和法规。严禁以非法、欺诈或滥用活动使用 CapSolver 网络,任何此类行为将受到调查。我们的验证码解决方案在确保 100% 合规的同时,帮助解决公共数据爬取过程中的验证码难题。我们鼓励负责任地使用我们的服务。如需更多信息,请访问我们的服务条款和隐私政策。

更多