Como resolver Captcha no Browser4 com integração do CapSolver

Adélia Cruz
Neural Network Developer
21-Jan-2026

Para automação web, o Browser4 (da PulsarRPA) emergiu como um motor de navegador rápido, seguro para corrotinas, projetado para extração de dados com inteligência artificial. Com capacidades que suportam 100k-200k visitas a páginas complexas por máquina por dia, o Browser4 é construído para escala séria. No entanto, ao extrair dados de sites protegidos, desafios de CAPTCHA tornam-se uma barreira significativa.
CapSolver fornece o complemento perfeito às capacidades de automação do Browser4, permitindo que seus agentes naveguem por páginas protegidas por CAPTCHA de forma semiplena. Essa integração combina a automação de navegador de alto throughput do Browser4 com soluções líderes de mercado para resolução de CAPTCHA.
O que é Browser4?
Browser4 é um framework de automação de navegador de alto desempenho construído em Kotlin. Foi projetado para aplicações de inteligência artificial que exigem capacidades de agentes autônomos, throughput extremo e extração de dados híbrida que combina LLM, algoritmos de aprendizado de máquina e abordagens baseadas em seletores.
Principais Funcionalidades do Browser4
- Throughput Extremo: 100k-200k visitas a páginas complexas por máquina por dia
- Seguro para Corrotinas: Construído com corrotinas Kotlin para processamento paralelo eficiente
- Agentes Impulsionados por IA: Agentes de navegador autônomos capazes de raciocínio e execução de tarefas de múltiplos passos
- Extração Híbrida: Combina inteligência de LLM, algoritmos de ML e seletores CSS/XPath
- Consultas X-SQL: Sintaxe SQL estendida para extração de dados complexa
- Funcionalidades Anti-Bot: Rotação de perfis, suporte a proxies e agendamento resistente
Métodos da API Principal
| Método | Descrição |
|---|---|
session.open(url) |
Carrega uma página e retorna um PageSnapshot |
session.parse(page) |
Converte o snapshot em documento na memória |
driver.selectFirstTextOrNull(selector) |
Recupera texto do DOM em tempo real |
driver.evaluate(script) |
Executa JavaScript no navegador |
session.extract(document, fieldMap) |
Mapeia seletores CSS para campos estruturados |
O que é CapSolver?
CapSolver é um serviço líder de resolução de CAPTCHA que fornece soluções impulsionadas por inteligência artificial para contornar diversos desafios de CAPTCHA. Com suporte para vários tipos de CAPTCHA e tempos de resposta rápidos, o CapSolver se integra de forma eficiente em fluxos de trabalho automatizados.
Tipos de CAPTCHA Suportados
- reCAPTCHA v2 (Imagem & Invisible)
- reCAPTCHA v3
- Cloudflare Turnstile
- Cloudflare Challenge (5s)
- AWS WAF
- E muitos mais...
Por que Integrar o CapSolver com o Browser4?
Ao construir automação com Browser4 que interage com sites protegidos - seja para extração de dados, monitoramento de preços ou pesquisa de mercado - os desafios de CAPTCHA tornam-se uma barreira significativa. Aqui está por que a integração importa:
- Extração de Alto Desempenho Ininterrupta: Mantenha 100k+ visitas diárias sem bloqueios de CAPTCHA
- Operações Escaláveis: Trate CAPTCHAs em execuções paralelas de corrotinas
- Fluxo de Trabalho Sempre Contínuo: Resolva CAPTCHAs como parte do seu pipeline de extração
- Custo-Efetivo: Pague apenas pelos CAPTCHAS resolvidos com sucesso
- Alta Taxa de Sucesso: Precisão líder do setor para todos os tipos de CAPTCHA suportados
Instalação
Requisitos Prévios
- Java 17 ou superior
- Maven 3.6+ ou Gradle
- Uma chave de API do CapSolver

Adicionando Dependências
Maven (pom.xml):
xml
<dependencies>
<!-- Browser4/PulsarRPA -->
<dependency>
<groupId>ai.platon.pulsar</groupId>
<artifactId>pulsar-boot</artifactId>
<version>2.2.0</version>
</dependency>
<!-- Cliente HTTP para CapSolver -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- Análise JSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Corrotinas Kotlin -->
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
Gradle (build.gradle.kts):
kotlin
dependencies {
implementation("ai.platon.pulsar:pulsar-boot:2.2.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.google.code.gson:gson:2.10.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
}
Configuração do Ambiente
Crie um arquivo application.properties:
properties
# Configuração do CapSolver
CAPSOLVER_API_KEY=seu_capsolver_api_key
# Configuração do LLM (opcional, para extração de IA)
OPENROUTER_API_KEY=seu_openrouter_api_key
# Configuração de Proxy (opcional)
PROXY_ROTATION_URL=seu_proxy_url
Criando um Serviço CapSolver para Browser4
Aqui está um serviço Kotlin reutilizável que integra o CapSolver ao Browser4:
Serviço Básico do CapSolver
kotlin
import com.google.gson.Gson
import com.google.gson.JsonObject
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import kotlinx.coroutines.delay
import java.util.concurrent.TimeUnit
data class TaskResult(
val gRecaptchaResponse: String? = null,
val token: String? = null,
val cookies: List<Map<String, String>>? = null,
val userAgent: String? = null
)
class CapSolverService(private val apiKey: String) {
private val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
private val gson = Gson()
private val baseUrl = "https://api.capsolver.com"
private val jsonMediaType = "application/json".toMediaType()
private suspend fun createTask(taskData: Map<String, Any>): String {
val payload = mapOf(
"clientKey" to apiKey,
"task" to taskData
)
val request = Request.Builder()
.url("$baseUrl/createTask")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
if (result.get("errorId").asInt != 0) {
throw Exception("Erro do CapSolver: ${result.get("errorDescription").asString}")
}
return result.get("taskId").asString
}
private suspend fun getTaskResult(taskId: String, maxAttempts: Int = 60): TaskResult {
val payload = mapOf(
"clientKey" to apiKey,
"taskId" to taskId
)
repeat(maxAttempts) {
delay(2000)
val request = Request.Builder()
.url("$baseUrl/getTaskResult")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
when (result.get("status")?.asString) {
"ready" -> {
val solution = result.getAsJsonObject("solution")
return TaskResult(
gRecaptchaResponse = solution.get("gRecaptchaResponse")?.asString,
token = solution.get("token")?.asString,
userAgent = solution.get("userAgent")?.asString
)
}
"failed" -> throw Exception("Tarefa falhou: ${result.get("errorDescription")?.asString}")
}
}
throw Exception("Tempo esgotado ao aguardar a solução do CAPTCHA")
}
suspend fun solveReCaptchaV2(websiteUrl: String, websiteKey: String): String {
val taskId = createTask(mapOf(
"type" to "ReCaptchaV2TaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey
))
val result = getTaskResult(taskId)
return result.gRecaptchaResponse ?: throw Exception("Nenhum gRecaptchaResponse na solução")
}
suspend fun solveReCaptchaV3(
websiteUrl: String,
websiteKey: String,
pageAction: String = "submit"
): String {
val taskId = createTask(mapOf(
"type" to "ReCaptchaV3TaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey,
"pageAction" to pageAction
))
val result = getTaskResult(taskId)
return result.gRecaptchaResponse ?: throw Exception("Nenhum gRecaptchaResponse na solução")
}
suspend fun solveTurnstile(
websiteUrl: String,
websiteKey: String,
action: String? = null,
cdata: String? = null
): String {
val taskData = mutableMapOf(
"type" to "AntiTurnstileTaskProxyLess",
"websiteURL" to websiteUrl,
"websiteKey" to websiteKey
)
// Adicionar metadados opcionais
if (action != null || cdata != null) {
val metadata = mutableMapOf<String, String>()
action?.let { metadata["action"] = it }
cdata?.let { metadata["cdata"] = it }
taskData["metadata"] = metadata
}
val taskId = createTask(taskData)
val result = getTaskResult(taskId)
return result.token ?: throw Exception("Nenhum token na solução")
}
suspend fun checkBalance(): Double {
val payload = mapOf("clientKey" to apiKey)
val request = Request.Builder()
.url("$baseUrl/getBalance")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
return result.get("balance")?.asDouble ?: 0.0
}
}
Resolvendo Diferentes Tipos de CAPTCHA
reCAPTCHA v2 com Browser4
kotlin
import ai.platon.pulsar.context.PulsarContexts
import ai.platon.pulsar.skeleton.session.PulsarSession
import kotlinx.coroutines.runBlocking
class ReCaptchaV2Extractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithCaptcha(targetUrl: String, siteKey: String): Map<String, Any?> {
println("Resolvendo reCAPTCHA v2...")
// Resolva o CAPTCHA primeiro
val token = capSolver.solveReCaptchaV2(targetUrl, siteKey)
println("CAPTCHA resolvido, comprimento do token: ${token.length}")
// Crie sessão e abra a página
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Injete o token em um campo de texto oculto usando a propriedade value (seguro)
driver?.evaluate("""
(function() {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = arguments[0];
})('$token');
""")
// Submeta o formulário
driver?.evaluate("document.querySelector('form').submit();")
// Aguarde a navegação
Thread.sleep(3000)
// Extraia dados da página de resultado
val document = session.parse(page)
mapOf(
"título" to document.selectFirstTextOrNull("h1"),
"conteúdo" to document.selectFirstTextOrNull(".conteúdo"),
"sucesso" to (document.body().text().contains("sucesso", ignoreCase = true))
)
}
}
fun main() = runBlocking {
val apiKey = System.getenv("CAPSOLVER_API_KEY") ?: "sua_api_key"
val capSolver = CapSolverService(apiKey)
val extractor = ReCaptchaV2Extractor(capSolver)
val result = extractor.extractWithCaptcha(
targetUrl = "https://exemplo.com/página-protegida",
siteKey = "6LcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxABC"
)
println("Resultado da extração: $result")
}
reCAPTCHA v3 com Browser4
kotlin
class ReCaptchaV3Extractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithCaptchaV3(
targetUrl: String,
siteKey: String,
action: String = "submit"
): Map<String, Any?> {
println("Resolvendo reCAPTCHA v3 com ação: $action")
// Resolva reCAPTCHA v3 com ação de página personalizada
val token = capSolver.solveReCaptchaV3(
websiteUrl = targetUrl,
websiteKey = siteKey,
pageAction = action
)
println("Token obtido com sucesso")
// Crie sessão e abra a página
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Injete token em entrada oculta (usando atribuição segura de valor)
driver?.evaluate("""
(function(tokenValue) {
var input = document.querySelector('input[name="g-recaptcha-response"]');
if (input) {
input.value = tokenValue;
} else {
var hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = 'g-recaptcha-response';
hidden.value = tokenValue;
var form = document.querySelector('form');
if (form) form.appendChild(hidden);
}
})('$token');
""")
// Clique no botão de envio
driver?.evaluate("document.querySelector('#submit-btn').click();")
Thread.sleep(3000)
val document = session.parse(page)
mapOf(
"resultado" to document.selectFirstTextOrNull(".dados-resultados"),
"status" to "sucesso"
)
}
}
Cloudflare Turnstile com Browser4
kotlin
class TurnstileExtractor(
private val capSolver: CapSolverService
) {
suspend fun extractWithTurnstile(targetUrl: String, siteKey: String): Map<String, Any?> {
println("Resolvendo Cloudflare Turnstile...")
// Resolva com metadados opcionais (ação e cdata)
val token = capSolver.solveTurnstile(
targetUrl,
siteKey,
action = "login", // opcional
cdata = "0000-1111-2222-3333-example" // opcional
)
println("Turnstile resolvido!")
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Injetar token Turnstile (usando atribuição segura de valor)
driver?.evaluate("""
(function(tokenValue) {
var input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) input.value = tokenValue;
})('$token');
""")
// Enviar formulário
driver?.evaluate("document.querySelector('form').submit();")
Thread.sleep(3000)
val document = session.parse(page)
mapOf(
"title" to document.selectFirstTextOrNull("title"),
"content" to document.selectFirstTextOrNull("body")?.take(500)
)
}
}
---
## Integração com Browser4 X-SQL
O X-SQL do Browser4 fornece capacidades poderosas de extração. Aqui está como combiná-lo com a resolução de CAPTCHA:
```kotlin
class XSqlCaptchaExtractor(
private val capSolver: CapSolverService
) {
suspend fun extractProductsWithCaptcha(
targetUrl: String,
siteKey: String
): List<Map<String, Any?>> {
// Resolver CAPTCHA antes
val token = capSolver.solveReCaptchaV2(targetUrl, siteKey)
// Criar sessão e estabelecer sessão autenticada
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
document.querySelector('form').submit();
})('$token');
""")
Thread.sleep(3000)
// Agora analisar a página e extrair dados de produtos
val document = session.parse(page)
// Extrair dados de produtos usando métodos embutidos da sessão
val products = mutableListOf<Map<String, Any?>>()
val productElements = document.select(".product-item")
for ((index, element) in productElements.withIndex()) {
if (index >= 50) break // LIMITE DE 50
products.add(mapOf(
"name" to element.selectFirstTextOrNull(".product-name"),
"price" to element.selectFirstTextOrNull(".price")?.let {
"""(\d+\.?\d*)""".toRegex().find(it)?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0
},
"rating" to element.selectFirstTextOrNull(".rating")
))
}
return products.map { row ->
mapOf(
"name" to row["name"],
"price" to row["price"],
"rating" to row["rating"],
"image_url" to row["image_url"]
)
}
}
}
Padrão de Pré-Autenticação
Para sites que exigem CAPTCHA antes de acessar conteúdo, use um fluxo de trabalho de pré-autenticação:
kotlin
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
class PreAuthenticator(
private val capSolver: CapSolverService
) {
data class AuthSession(
val cookies: Map<String, String>,
val userAgent: String?
)
suspend fun authenticateWithCaptcha(
loginUrl: String,
siteKey: String
): AuthSession {
// Resolver CAPTCHA
val captchaToken = capSolver.solveReCaptchaV2(loginUrl, siteKey)
// Enviar CAPTCHA para obter cookies de sessão
val client = OkHttpClient.Builder()
.cookieJar(object : CookieJar {
private val cookies = mutableListOf<Cookie>()
override fun saveFromResponse(url: HttpUrl, cookieList: List<Cookie>) {
cookies.addAll(cookieList)
}
override fun loadForRequest(url: HttpUrl): List<Cookie> = cookies
})
.build()
val formBody = okhttp3.FormBody.Builder()
.add("g-recaptcha-response", captchaToken)
.build()
val request = Request.Builder()
.url(loginUrl)
.post(formBody)
.build()
val response = client.newCall(request).execute()
// Extrair cookies da resposta
val responseCookies = response.headers("Set-Cookie")
.associate { cookie ->
val parts = cookie.split(";")[0].split("=", limit = 2)
parts[0] to (parts.getOrNull(1) ?: "")
}
return AuthSession(
cookies = responseCookies,
userAgent = response.request.header("User-Agent")
)
}
}
class AuthenticatedExtractor(
private val preAuth: PreAuthenticator,
private val capSolver: CapSolverService
) {
suspend fun extractWithAuth(
loginUrl: String,
targetUrl: String,
siteKey: String
): Map<String, Any?> {
// Pré-autenticar
val authSession = preAuth.authenticateWithCaptcha(loginUrl, siteKey)
println("Sessão estabelecida com ${authSession.cookies.size} cookies")
// Criar sessão do Browser4
val session = PulsarContexts.createSession()
// Configurar sessão com cookies
val cookieScript = authSession.cookies.entries.joinToString(";") { (k, v) ->
"$k=$v"
}
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
// Definir cookies
driver?.evaluate("document.cookie = '$cookieScript';")
// Recarregar com sessão autenticada
driver?.evaluate("location.reload();")
Thread.sleep(2000)
// Extrair dados
val document = session.parse(page)
return mapOf(
"authenticated" to true,
"content" to document.selectFirstTextOrNull(".protected-content"),
"userData" to document.selectFirstTextOrNull(".user-profile")
)
}
}
Integração com OpenRouter para Extração com IA
As capacidades de IA do Browser4 podem ser aprimoradas com o OpenRouter, um gateway de API unificado para acessar vários modelos de linguagem. Isso permite extração inteligente de conteúdo que se adapta a diferentes estruturas de página.
Serviço OpenRouter
kotlin
import com.google.gson.Gson
import com.google.gson.JsonObject
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.concurrent.TimeUnit
data class ChatMessage(val role: String, val content: String)
data class ChatCompletion(val content: String, val model: String, val usage: TokenUsage)
data class TokenUsage(val promptTokens: Int, val completionTokens: Int, val totalTokens: Int)
class OpenRouterService(private val apiKey: String) {
private val client = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
private val gson = Gson()
private val baseUrl = "https://openrouter.ai/api/v1"
private val jsonMediaType = "application/json".toMediaType()
fun chat(
messages: List<ChatMessage>,
model: String = "openai/gpt-4o-mini"
): ChatCompletion {
val payload = mapOf(
"model" to model,
"messages" to messages.map { mapOf("role" to it.role, "content" to it.content) }
)
val request = Request.Builder()
.url("$baseUrl/chat/completions")
.header("Authorization", "Bearer $apiKey")
.post(gson.toJson(payload).toRequestBody(jsonMediaType))
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
val choice = result.getAsJsonArray("choices")?.get(0)?.asJsonObject
val content = choice?.getAsJsonObject("message")?.get("content")?.asString ?: ""
val usage = result.getAsJsonObject("usage")
return ChatCompletion(
content = content,
model = result.get("model")?.asString ?: model,
usage = TokenUsage(
promptTokens = usage?.get("prompt_tokens")?.asInt ?: 0,
completionTokens = usage?.get("completion_tokens")?.asInt ?: 0,
totalTokens = usage?.get("total_tokens")?.asInt ?: 0
)
)
}
fun extractStructuredData(html: String, schema: String): String {
val prompt = """
Extraia os seguintes dados deste conteúdo HTML.
Retorne APENAS JSON válido correspondendo a este esquema: $schema
HTML:
${html.take(4000)}
""".trimIndent()
return chat(listOf(ChatMessage("user", prompt))).content
}
fun listModels(): List<String> {
val request = Request.Builder()
.url("$baseUrl/models")
.header("Authorization", "Bearer $apiKey")
.build()
val response = client.newCall(request).execute()
val result = gson.fromJson(response.body?.string(), JsonObject::class.java)
return result.getAsJsonArray("data")?.mapNotNull {
it.asJsonObject.get("id")?.asString
} ?: emptyList()
}
}
Extração com IA e Resolução de CAPTCHA
Combine resolução de CAPTCHA com extração inteligente de conteúdo:
kotlin
class SmartExtractor(
private val capSolver: CapSolverService,
private val openRouter: OpenRouterService
) {
suspend fun extractWithAI(
targetUrl: String,
siteKey: String?,
extractionPrompt: String
): Map<String, Any?> {
// Passo 1: Resolver CAPTCHA se necessário
val captchaToken = siteKey?.let {
println("Resolvendo CAPTCHA...")
capSolver.solveReCaptchaV2(targetUrl, it)
}
// Passo 2: Criar sessão e abrir página
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
captchaToken?.let { token ->
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
var form = document.querySelector('form');
if (form) form.submit();
})('$token');
""")
Thread.sleep(3000)
}
// Passo 3: Extrair conteúdo da página
val document = session.parse(page)
val pageContent = document.body().text().take(8000)
// Passo 4: Usar IA para extrair dados estruturados
val llmResponse = openRouter.chat(listOf(
ChatMessage("system", "Você é um assistente de extração de dados. Extraia dados estruturados de páginas da web."),
ChatMessage("user", """
$extractionPrompt
Conteúdo da página:
$pageContent
""".trimIndent())
))
println("LLM usou ${llmResponse.usage.totalTokens} tokens")
return mapOf(
"url" to targetUrl,
"captchaSolved" to (captchaToken != null),
"extractedData" to llmResponse.content,
"tokensUsed" to llmResponse.usage.totalTokens
)
}
}
// Uso
fun main() = runBlocking {
val capSolver = CapSolverService(System.getenv("CAPSOLVER_API_KEY")!!)
val openRouter = OpenRouterService(System.getenv("OPENROUTER_API_KEY")!!)
val extractor = SmartExtractor(capSolver, openRouter)
val result = extractor.extractWithAI(
targetUrl = "https://example.com/products",
siteKey = "6LcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxABC",
extractionPrompt = """
Extraia todos os produtos com:
- nome
- preço (como número)
- disponibilidade (em_estoque/fora_de_estoque)
- avaliação (1-5)
Retorne como array JSON.
""".trimIndent()
)
println("Resultado da extração: ${result["extractedData"]}")
}
Geração de Seletores Adaptativos
Use LLM para gerar seletores CSS para estruturas de página desconhecidas:
kotlin
class AdaptiveExtractor(
private val capSolver: CapSolverService,
private val openRouter: OpenRouterService
) {
suspend fun extractWithAdaptiveSelectors(
targetUrl: String,
siteKey: String?,
dataFields: List<String>
): Map<String, Any?> {
// Resolver CAPTCHA primeiro
val token = siteKey?.let { capSolver.solveReCaptchaV2(targetUrl, it) }
val session = PulsarContexts.createSession()
val page = session.open(targetUrl)
val driver = session.getOrCreateBoundDriver()
token?.let { t ->
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
})('$t');
""")
}
// Obter estrutura HTML da página
val htmlSample = driver?.evaluate("document.body.innerHTML")?.toString()?.take(5000) ?: ""
// Pedir ao LLM para gerar seletores
val selectorPrompt = """
Analise este HTML e forneça seletores CSS para estes campos: ${dataFields.joinToString(", ")}
Amostra de HTML:
$htmlSample
Retorne JSON como: {"fieldName": "css-selector", ...}
""".trimIndent()
val selectorsJson = openRouter.chat(listOf(ChatMessage("user", selectorPrompt))).content
val selectors = Gson().fromJson(selectorsJson, Map::class.java) as Map<String, String>
// Extrair usando seletores gerados
val document = session.parse(page)
val extractedData = selectors.mapValues { (_, selector) ->
document.selectFirstTextOrNull(selector)
}
return mapOf(
"url" to targetUrl,
"selectors" to selectors,
"data" to extractedData
)
}
}
Extração Paralela com Coroutines
O design seguro para coroutines do Browser4 permite gerenciamento eficiente de CAPTCHA em paralelo:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
data class ExtractionJob(
val url: String,
val siteKey: String?
)
data class ExtractionResult(
val url: String,
val data: Map<String, Any?>?,
val captchaSolved: Boolean,
val error: String?,
val duration: Long
)
class ParallelExtractor(
private val capSolver: CapSolverService,
private val concurrency: Int = 5
) {
suspend fun extractAll(jobs: List<ExtractionJob>): List<ExtractionResult> = coroutineScope {
val channel = Channel<ExtractionJob>(Channel.UNLIMITED)
val results = mutableListOf<ExtractionResult>()
// Enviar todos os trabalhos para o canal
jobs.forEach { channel.send(it) }
channel.close()
// Processar com concorrência limitada
val workers = (1..concorrência).map { workerId ->
async {
val workerResults = mutableListOf<ExtractionResult>()
// Cada worker cria sua própria sessão para segurança de thread
val workerSession = PulsarContexts.createSession()
for (job in channel) {
val startTime = System.currentTimeMillis()
var captchaResolvido = false
try {
// Resolver CAPTCHA se fornecido a chave do site
val token = job.chaveDoSite?.let {
captchaResolvido = true
capSolver.resolverReCaptchaV2(job.url, it)
}
// Extrair dados
val page = workerSession.open(job.url)
token?.let { t ->
val driver = workerSession.getOrCreateBoundDriver()
driver?.evaluate("""
(function(tokenValue) {
var el = document.querySelector('#g-recaptcha-response');
if (el) el.value = tokenValue;
})('$t');
""")
}
val document = workerSession.parse(page)
workerResults.add(ExtractionResult(
url = job.url,
dados = mapOf(
"título" to document.selectFirstTextOrNull("title"),
"h1" to document.selectFirstTextOrNull("h1")
),
captchaResolvido = captchaResolvido,
erro = null,
duração = System.currentTimeMillis() - startTime
))
} catch (e: Exception) {
workerResults.add(ExtractionResult(
url = job.url,
dados = null,
captchaResolvido = captchaResolvido,
erro = e.message,
duração = System.currentTimeMillis() - startTime
))
}
}
workerResults
}
}
workers.awaitAll().flatten()
}
}
// Uso
fun main() = runBlocking {
val capSolver = CapSolverService(System.getenv("CAPSOLVER_API_KEY")!!)
val extractor = ParallelExtractor(capSolver, concorrência = 5)
val jobs = listOf(
ExtractionJob("https://site1.com/dados", "6Lc..."),
ExtractionJob("https://site2.com/dados", null),
ExtractionJob("https://site3.com/dados", "6Lc..."),
)
val results = extractor.extractAll(jobs)
val resolvidos = results.count { it.captchaResolvido }
println("Concluído ${results.size} extrações, resolvidos $resolvidos CAPTCHAs")
results.forEach { r ->
println("${r.url}: ${r.duração}ms - ${r.erro ?: "sucesso"}")
}
}
Práticas Recomendadas
1. Tratamento de Erros com Reinícios
kotlin
suspend fun <T> withRetry(
maxTentativas: Int = 3,
tempoInicial: Long = 1000,
block: suspend () -> T
): T {
var últimaExceção: Exception? = null
repeat(maxTentativas) { tentativa ->
try {
return block()
} catch (e: Exception) {
últimaExceção = e
println("Tentativa ${tentativa + 1} falhou: ${e.message}")
delay(tempoInicial * (tentativa + 1))
}
}
throw últimaExceção ?: Exception("Máximo de tentativas excedido")
}
// Uso
val token = withRetry(maxTentativas = 3) {
capSolver.resolverReCaptchaV2(url, chaveDoSite)
}
2. Gerenciamento de Saldo
kotlin
suspend fun garantirSaldoSuficiente(
capSolver: CapSolverService,
saldoMínimo: Double = 1.0
) {
val saldo = capSolver.verificarSaldo()
if (saldo < saldoMínimo) {
throw Exception("Saldo insuficiente do CapSolver: $${"%.2f".format(saldo)}. Por favor, recarregue.")
}
println("Saldo do CapSolver: $${"%.2f".format(saldo)}")
}
3. Cache de Tokens
kotlin
class CacheDeToken(private val ttlMs: Long = 90_000) {
private data class TokenCacheado(val token: String, val timestamp: Long)
private val cache = mutableMapOf<String, TokenCacheado>()
private fun getKey(domínio: String, chaveDoSite: String) = "$domínio:$chaveDoSite"
fun get(domínio: String, chaveDoSite: String): String? {
val key = getKey(domínio, chaveDoSite)
val cached = cache[key] ?: return null
if (System.currentTimeMillis() - cached.timestamp > ttlMs) {
cache.remove(key)
return null
}
return cached.token
}
fun set(domínio: String, chaveDoSite: String, token: String) {
val key = getKey(domínio, chaveDoSite)
cache[key] = TokenCacheado(token, System.currentTimeMillis())
}
}
// Uso com cache
class CapSolverComCache(
private val capSolver: CapSolverService,
private val cache: CacheDeToken = CacheDeToken()
) {
suspend fun resolverReCaptchaV2ComCache(urlDoSite: String, chaveDoSite: String): String {
val domínio = java.net.URL(urlDoSite).host
cache.get(domínio, chaveDoSite)?.let {
println("Usando token em cache")
return it
}
val token = capSolver.resolverReCaptchaV2(urlDoSite, chaveDoSite)
cache.set(domínio, chaveDoSite, token)
return token
}
}
Opções de Configuração
| Configuração | Descrição | Padrão |
|---|---|---|
CAPSOLVER_API_KEY |
Sua chave de API do CapSolver | - |
OPENROUTER_API_KEY |
Sua chave de API do OpenRouter para recursos de LLM | - |
PROXY_ROTATION_URL |
URL do serviço de rotação de proxy | - |
O Browser4 usa application.properties para configuração adicional |
Conclusão
Integrar o CapSolver com o Browser4 cria uma combinação poderosa para extração de dados da web de alto throughput. A arquitetura do Browser4 segura para coroutines e suas capacidades de desempenho extremo, combinadas com a resolução confiável de CAPTCHAs do CapSolver, permitem extração em escala.
Padrões de integração principais:
- Injeção de Token Direta: Injetar tokens resolvidos via avaliação de JavaScript
- Autenticação Prévia: Resolver CAPTCHAs para estabelecer sessões antes da extração
- Processamento Paralelo: Aproveitar coroutines para lidar com CAPTCHAs simultâneos
- Integração com X-SQL: Combinar resolução de CAPTCHA com a linguagem de consulta poderosa do Browser4
Seja você estiver construindo sistemas de monitoramento de preços, pipelines de pesquisa de mercado ou plataformas de agregação de dados, a combinação Browser4 + CapSolver fornece a confiabilidade e a escalabilidade necessárias para ambientes de produção.
Pronto para começar? Registre-se no CapSolver e use o código de bônus BROWSER4 para obter um bônus extra de 6% na primeira recarga!
Perguntas Frequentes
O que é Browser4?
O Browser4 é um framework de automação de navegador seguro para coroutines da PulsarRPA. Ele é construído em Kotlin e projetado para extração de dados com inteligência artificial, suportando 100k-200k visitas a páginas complexas por máquina por dia.
Como o CapSolver se integra ao Browser4?
O CapSolver se integra ao Browser4 por meio de uma classe de serviço que resolve CAPTCHAs via API do CapSolver. Os tokens resolvidos são então injetados nas páginas usando as capacidades de avaliação de JavaScript do Browser4 (driver.evaluate()).
Quais tipos de CAPTCHAs o CapSolver pode resolver?
O CapSolver suporta reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, Cloudflare Challenge (5s), AWS WAF, GeeTest v3/v4 e muitos outros.
Quanto custa o CapSolver?
O CapSolver oferece preços competitivos com base no tipo e volume de CAPTCHAs resolvidos. Visite capsolver.com para os preços atuais. Use o código BROWSER4 para obter um bônus de 6%.
Qual linguagem de programação o Browser4 usa?
O Browser4 é construído em Kotlin e roda na JVM (Java 17+). Também pode ser usado em aplicações Java.
O Browser4 pode lidar com resolução de CAPTCHA paralela?
Sim! O design seguro para coroutines do Browser4 permite processamento eficiente em paralelo. Combinado com a API do CapSolver, você pode resolver múltiplos CAPTCHAs simultaneamente em diferentes trabalhos de extração.
Como encontrar a chave do CAPTCHA?
A chave do CAPTCHA geralmente está presente no código fonte da página:
- reCAPTCHA: atributo
data-sitekeyno elemento.g-recaptcha - Turnstile: atributo
data-sitekeyno elemento.cf-turnstile - Ou verifique as requisições de rede para encontrar a chave nas chamadas de API
Declaração de Conformidade: As informações fornecidas neste blog são apenas para fins informativos. A CapSolver está comprometida em cumprir todas as leis e regulamentos aplicáveis. O uso da rede CapSolver para atividades ilegais, fraudulentas ou abusivas é estritamente proibido e será investigado. Nossas soluções de resolução de captcha melhoram a experiência do usuário enquanto garantem 100% de conformidade ao ajudar a resolver dificuldades de captcha durante a coleta de dados públicos. Incentivamos o uso responsável de nossos serviços. Para mais informações, visite nossos Termos de Serviço e Política de Privacidade.
Mais

Como resolver Captcha no Maxun com Integração do CapSolver
Um guia prático para integrar o CapSolver com o Maxun para raspagem de web realista. Aprenda como lidar com reCAPTCHA, Cloudflare Turnstile e sites protegidos por CAPTCHA usando fluxos de trabalho de pré-autenticação e robô.

Adélia Cruz
21-Jan-2026

Como resolver Captcha no Browser4 com integração do CapSolver
Automação do Browser4 de alto throughput combinada com o CapSolver para lidar com desafios de CAPTCHA na extração de dados da web em larga escala.

Adélia Cruz
21-Jan-2026

O que é um bot de raspagem e como construir um
Aprenda o que é um bot de raspagem e como criar um para extração automática de dados. Descubra os melhores ferramentas, técnicas de navegação segura e práticas éticas de raspagem.

Adélia Cruz
16-Jan-2026

Melhor Resolutor de reCAPTCHA 2026 para Automação & Web Scraping
Descubra os melhores solucionadores de reCAPTCHA para automação e raspagem de dados da web em 2026. Aprenda como eles funcionam, escolha o adequado e fique à frente da detecção de bots.

Rajinder Singh
15-Jan-2026

Scrapy vs. Selenium: Qual é o melhor para o seu projeto de raspagem de web
Descubra as vantagens e diferenças entre o Scrapy e o Selenium para raspagem de dados. Aprenda qual ferramenta é a mais adequada para o seu projeto e como lidar com desafios como CAPTCHAs.

Anh Tuan
14-Jan-2026

Como Usar o Selenium Driverless para Web Scraping Eficiente
Aprenda como usar o Selenium Driverless para raspagem de web eficiente. Este guia fornece instruções passo a passo para configurar seu ambiente, escrever seu primeiro script Selenium Driverless e lidar com conteúdo dinâmico. Simplifique suas tarefas de raspagem de web evitando as complexidades da gestão tradicional do WebDriver, tornando seu processo de extração de dados mais simples, mais rápido e mais portátil.

Emma Foster
14-Jan-2026


