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

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

Logo of 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


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:

  1. Extração de Alto Desempenho Ininterrupta: Mantenha 100k+ visitas diárias sem bloqueios de CAPTCHA
  2. Operações Escaláveis: Trate CAPTCHAs em execuções paralelas de corrotinas
  3. Fluxo de Trabalho Sempre Contínuo: Resolva CAPTCHAs como parte do seu pipeline de extração
  4. Custo-Efetivo: Pague apenas pelos CAPTCHAS resolvidos com sucesso
  5. Alta Taxa de Sucesso: Precisão líder do setor para todos os tipos de CAPTCHA suportados

Instalação

Requisitos Prévios

Adicionando Dependências

Maven (pom.xml):

xml Copy
<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 Copy
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 Copy
# 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 Copy
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 Copy
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 Copy
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 Copy
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!")

Copy
    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)
    )
}

}

Copy
---

## 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 Copy
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 Copy
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 Copy
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 Copy
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 Copy
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 Copy
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 Copy
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 Copy
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:

  1. Injeção de Token Direta: Injetar tokens resolvidos via avaliação de JavaScript
  2. Autenticação Prévia: Resolver CAPTCHAs para estabelecer sessões antes da extração
  3. Processamento Paralelo: Aproveitar coroutines para lidar com CAPTCHAs simultâneos
  4. 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-sitekey no elemento .g-recaptcha
  • Turnstile: atributo data-sitekey no 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

Maxun com Integração CapSolver
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ô.

web scraping
Logo of CapSolver

Adélia Cruz

21-Jan-2026

Browser4 com Integração do CapSolver
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.

web scraping
Logo of CapSolver

Adélia Cruz

21-Jan-2026

O que é um bot de raspagem e como construir um
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.

web scraping
Logo of CapSolver

Adélia Cruz

16-Jan-2026

Melhor Solucionador de reCAPTCHA 2026 para Automação & Web Scraping
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.

web scraping
Logo of CapSolver

Rajinder Singh

15-Jan-2026

Scrapy vs. Selenium
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.

web scraping
Logo of CapSolver

Anh Tuan

14-Jan-2026

Como usar o Selenium Driverless para coleta eficiente de dados da web
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.

web scraping
Logo of CapSolver

Emma Foster

14-Jan-2026