CAPSOLVER
Blog
Integrando Katana com CapSolver: Resolução Automatizada de CAPTCHA para Raspagem de Web

Integração do Katana com o CapSolver: Resolução Automática de CAPTCHA para Web Crawling

Logo of CapSolver

Adélia Cruz

Neural Network Developer

12-Jan-2026

Por que resolver CAPTCHA com Katana usando CapSolver

A raspagem de web é uma técnica essencial para pesquisadores de segurança, testadores de penetração e analistas de dados. No entanto, sites modernos empregam cada vez mais CAPTCHAs para proteger contra acesso automatizado. Este guia demonstra como integrar o Katana, o poderoso framework de raspagem da ProjectDiscovery, com o CapSolver, um serviço líder de resolução de CAPTCHA, para criar uma solução de raspagem robusta que resolva automaticamente os desafios de CAPTCHA.

O que você aprenderá

  • Configurar o Katana no modo navegador sem cabeça
  • Integrar a API do Capsolver para resolução automática de CAPTCHA
  • Lidar com reCAPTCHA v2 e Cloudflare Turnstile
  • Exemplos completos de código para cada tipo de CAPTCHA
  • Boas práticas para raspagem eficiente e responsável

O que é Katana?

Katana é um framework de raspagem web de próxima geração desenvolvido pela ProjectDiscovery. Foi projetado para velocidade e flexibilidade, sendo ideal para reconhecimento de segurança e pipelines de automação.

Principais Funcionalidades

  • Dois Modos de Raspagem: Raspagem baseada em HTTP e automação de navegador sem cabeça
  • Suporte a JavaScript: Analisar e raspar conteúdo renderizado por JavaScript
  • Configuração Flexível: Cabeçalhos personalizados, cookies, preenchimento de formulários e controle de escopo
  • Vários Formatos de Saída: Texto simples, JSON ou JSONL

Instalação

bash Copy
# Requer Go 1.24+
CGO_ENABLED=1 go install github.com/projectdiscovery/katana/cmd/katana@latest

Uso Básico

bash Copy
katana -u https://example.com -headless

O que é Capsolver?

CapSolver é um serviço de resolução de CAPTCHA baseado em inteligência artificial que fornece soluções rápidas e confiáveis para vários tipos de CAPTCHA.

Tipos de CAPTCHA Suportados

  • reCAPTCHA: v2 e versões Enterprise
  • Cloudflare: Turnstile e Challenge
  • AWS WAF: Bypass da proteção WAF
  • E Mais

Fluxo de Trabalho da API

O CapSolver usa um modelo de API baseado em tarefas:

  1. Criar Tarefa: Enviar parâmetros de CAPTCHA (tipo, siteKey, URL)
  2. Obter ID da Tarefa: Receber um identificador único da tarefa
  3. Verificar Resultado: Verificar o status da tarefa até que a solução esteja pronta
  4. Receber Token: Obter o token de CAPTCHA resolvido

Pré-requisitos

Antes de começar, certifique-se de ter:

  1. Go 1.24+ instalado
  2. Chave de API do Capsolver - Registre-se aqui
  3. Navegador Chrome (para modo sem cabeça)

Defina sua chave de API como uma variável de ambiente:

bash Copy
export CAPSOLVER_API_KEY="SUA_CHAVE_DE_API"

Arquitetura de Integração

Copy
┌─────────────────────────┐
│   Aplicação Go        │
│   (navegador go-rod)      │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   Website Alvo        │
│   (com CAPTCHA)        │
└───────────┬─────────────┘
            │
    CAPTCHA Detectado
            │
            ▼
┌─────────────────────────┐
│   Extrair Parâmetros    │
│   (siteKey, URL, tipo)  │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   API do Capsolver     │
│   createTask()          │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   Verificar Resultado   │
│   getTaskResult()       │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   Injetar Token         │
│   na Página             │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│   Continuar Raspagem     │
└─────────────────────────┘

Resolvendo reCAPTCHA v2 com o CapSolver

O reCAPTCHA v2 é o tipo de CAPTCHA mais comum, mostrando um checkbox "I'm not a robot" ou desafios de imagem. Aqui está um script completo e executável para resolver o reCAPTCHA v2:

go Copy
// Solucionador de reCAPTCHA v2 - Exemplo Completo
// Uso: go run main.go
// Requer: variável de ambiente CAPSOLVER_API_KEY

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
)

// Configuração
var (
	CAPSOLVER_API_KEY = os.Getenv("CAPSOLVER_API_KEY")
	CAPSOLVER_API     = "https://api.capsolver.com"
)

// Estruturas de resposta da API
type CreateTaskResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	TaskID           string `json:"taskId"`
}

type GetTaskResultResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	Status           string `json:"status"`
	Solution         struct {
		GRecaptchaResponse string `json:"gRecaptchaResponse"`
	} `json:"solution"`
}

type BalanceResponse struct {
	ErrorID int     `json:"errorId"`
	Balance float64 `json:"balance"`
}

// CapsolverClient lida com a comunicação da API
type CapsolverClient struct {
	APIKey string
	Client *http.Client
}

// NewCapsolverClient cria um novo cliente do Capsolver
func NewCapsolverClient(apiKey string) *CapsolverClient {
	return &CapsolverClient{
		APIKey: apiKey,
		Client: &http.Client{Timeout: 120 * time.Second},
	}
}

// GetBalance recupera o saldo da conta
func (c *CapsolverClient) GetBalance() (float64, error) {
	payload := map[string]string{"clientKey": c.APIKey}
	jsonData, _ := json.Marshal(payload)

	resp, err := c.Client.Post(CAPSOLVER_API+"/getBalance", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result BalanceResponse
	json.Unmarshal(body, &result)

	if result.ErrorID != 0 {
		return 0, fmt.Errorf("verificação de saldo falhou")
	}

	return result.Balance, nil
}

// SolveRecaptchaV2 soluciona um desafio de reCAPTCHA v2
func (c *CapsolverClient) SolveRecaptchaV2(websiteURL, siteKey string) (string, error) {
	log.Printf("Criando tarefa de reCAPTCHA v2 para %s", websiteURL)

	// Criar tarefa
	task := map[string]interface{}{
		"type":       "ReCaptchaV2TaskProxyLess",
		"websiteURL": websiteURL,
		"websiteKey": siteKey,
	}

	payload := map[string]interface{}{
		"clientKey": c.APIKey,
		"task":      task,
	}

	jsonData, _ := json.Marshal(payload)
	resp, err := c.Client.Post(CAPSOLVER_API+"/createTask", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("falha ao criar tarefa: %w", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var createResult CreateTaskResponse
	json.Unmarshal(body, &createResult)

	if createResult.ErrorID != 0 {
		return "", fmt.Errorf("erro da API: %s - %s", createResult.ErrorCode, createResult.ErrorDescription)
	}

	log.Printf("Tarefa criada: %s", createResult.TaskID)

	// Verificar resultado
	for i := 0; i < 120; i++ {
		result, err := c.getTaskResult(createResult.TaskID)
		if err != nil {
			return "", err
		}

		if result.Status == "ready" {
			log.Printf("CAPTCHA resolvido com sucesso!")
			return result.Solution.GRecaptchaResponse, nil
		}

		if result.Status == "failed" {
			return "", fmt.Errorf("tarefa falhou: %s", result.ErrorDescription)
		}

		if i%10 == 0 {
			log.Printf("Aguardando solução... (%ds)", i)
		}
		time.Sleep(1 * time.Second)
	}

	return "", fmt.Errorf("tempo esgotado esperando solução")
}

func (c *CapsolverClient) getTaskResult(taskID string) (*GetTaskResultResponse, error) {
	payload := map[string]string{
		"clientKey": c.APIKey,
		"taskId":    taskID,
	}

	jsonData, _ := json.Marshal(payload)
	resp, err := c.Client.Post(CAPSOLVER_API+"/getTaskResult", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result GetTaskResultResponse
	json.Unmarshal(body, &result)

	return &result, nil
}

// extractSiteKey extrai a chave do site do reCAPTCHA da HTML da página
func extractSiteKey(html string) string {
	// Procurar atributo data-sitekey
	patterns := []string{
		`data-sitekey="`,
		`data-sitekey='`,
		`"sitekey":"`,
		`'sitekey':'`,
	}

	for _, pattern := range patterns {
		if idx := strings.Index(html, pattern); idx != -1 {
			start := idx + len(pattern)
			end := start
			for end < len(html) && html[end] != '"' && html[end] != '\'' {
				end++
			}
			if end > start {
				return html[start:end]
			}
		}
	}
	return ""
}

// injectRecaptchaToken injeta o token resolvido na página
func injectRecaptchaToken(page *rod.Page, token string) error {
	js := fmt.Sprintf(`
		(function() {
			// Definir o campo de resposta
			var responseField = document.getElementById('g-recaptcha-response');
			if (responseField) {
				responseField.style.display = 'block';
				responseField.value = '%s';
			}

			// Também definir textareas ocultas
			var textareas = document.querySelectorAll('textarea[name="g-recaptcha-response"]');
			for (var i = 0; i < textareas.length; i++) {
				textareas[i].value = '%s';
			}

			// Disparar callback se existir
			if (typeof ___grecaptcha_cfg !== 'undefined') {
				var clients = ___grecaptcha_cfg.clients;
				for (var key in clients) {
					var client = clients[key];
					if (client) {
						// Tentar encontrar e chamar o callback
						try {
							var callback = client.callback ||
								(client.Q && client.Q.callback) ||
								(client.S && client.S.callback);
							if (typeof callback === 'function') {
								callback('%s');
							}
						} catch(e) {}
					}
				}
			}

			return true;
		})();
	`, token, token, token)

	_, err := page.Eval(js)
	return err
}

func main() {
	// Verificar chave de API
	if CAPSOLVER_API_KEY == "" {
		log.Fatal("A variável de ambiente CAPSOLVER_API_KEY é necessária")
	}

	// URL alvo - página de demonstração do reCAPTCHA da Google
	targetURL := "https://www.google.com/recaptcha/api2/demo"

	log.Println("==============================================")
	log.Println("Katana + Capsolver - Demonstração de reCAPTCHA v2")
	log.Println("==============================================")

	// Inicializar cliente do Capsolver
	client := NewCapsolverClient(CAPSOLVER_API_KEY)

	// Verificar saldo
	balance, err := client.GetBalance()
	if err != nil {
		log.Printf("Aviso: Não foi possível verificar o saldo: %v", err)
	} else {
		log.Printf("Saldo do Capsolver: $%.2f", balance)
	}

	// Iniciar navegador
	log.Println("Iniciando navegador...")
	path, _ := launcher.LookPath()
	u := launcher.New().Bin(path).Headless(true).MustLaunch()
	browser := rod.New().ControlURL(u).MustConnect()
	defer browser.MustClose()

	// Navegar até o alvo
	log.Printf("Navegando até: %s", targetURL)
	page := browser.MustPage(targetURL)
	page.MustWaitLoad()
	time.Sleep(2 * time.Second)

	// Obter HTML da página e extrair a chave do site
	html := page.MustHTML()

	// Verificar reCAPTCHA
	if !strings.Contains(html, "g-recaptcha") && !strings.Contains(html, "grecaptcha") {
		log.Fatal("Nenhum reCAPTCHA encontrado na página")
	}

	log.Println("reCAPTCHA detectado!")

	// Extrair chave do site
	siteKey := extractSiteKey(html)
	if siteKey == "" {
		log.Fatal("Não foi possível extrair a chave do site")
	}
	log.Printf("Chave do site: %s", siteKey)

	// Resolver CAPTCHA
	log.Println("Resolvendo CAPTCHA com o Capsolver...")
	token, err := client.SolveRecaptchaV2(targetURL, siteKey)
	if err != nil {
		log.Fatalf("Falha ao resolver CAPTCHA: %v", err)
	}

	log.Printf("Token recebido: %s...", token[:50])

	// Injetar token
	log.Println("Injetando token na página...")
	err = injectRecaptchaToken(page, token)
	if err != nil {
		log.Fatalf("Falha ao injetar token: %v", err)
	}

	// Submeter formulário
	log.Println("Submetendo formulário...")
	submitBtn := page.MustElement("#recaptcha-demo-submit")
	submitBtn.MustClick()

	// Aguardar resultado
	time.Sleep(3 * time.Second)

	// Verificar resultado
	newHTML := page.MustHTML()
	if strings.Contains(newHTML, "Verificação bem-sucedida") || strings.Contains(newHTML, "success") {
		log.Println("==============================================")
		log.Println("SUCESSO! reCAPTCHA resolvido e verificado!")
		log.Println("==============================================")
	} else {
		log.Println("Formulário submetido - verifique a página para o resultado")
	}

	// Obter título da página
	title := page.MustEval(`document.title`).String()
	log.Printf("Título da página final: %s", title)
}

Configuração e Execução

bash Copy
# Criar projeto
mkdir katana-recaptcha-v2
cd katana-recaptcha-v2
go mod init katana-recaptcha-v2

# Instalar dependências
go get github.com/go-rod/rod@latest

# Definir chave de API
export CAPSOLVER_API_KEY="SUA_CHAVE_DE_API"

# Executar
go run main.go

Resolvendo Cloudflare Turnstile com o CapSolver

O Cloudflare Turnstile é uma alternativa de CAPTCHA focada na privacidade. Aqui está um script completo:

go Copy
// Solucionador de Cloudflare Turnstile - Exemplo Completo
// Uso: go run main.go
// Requer: variável de ambiente CAPSOLVER_API_KEY

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
)

// Configuração
var (
	CAPSOLVER_API_KEY = os.Getenv("CAPSOLVER_API_KEY")
	CAPSOLVER_API     = "https://api.capsolver.com"
)

// Estruturas de resposta da API
type CreateTaskResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	TaskID           string `json:"taskId"`
}

type GetTaskResultResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	Status           string `json:"status"`
	Solution         struct {
		Token string `json:"token"`
	} `json:"solution"`
}

type BalanceResponse struct {
	ErrorID int     `json:"errorId"`
	Balance float64 `json:"balance"`
}

// CapsolverClient lida com a comunicação da API
type CapsolverClient struct {
	APIKey string
	Client *http.Client
}

// NewCapsolverClient cria um novo cliente do Capsolver
func NewCapsolverClient(apiKey string) *CapsolverClient {
	return &CapsolverClient{
		APIKey: apiKey,
		Client: &http.Client{Timeout: 120 * time.Second},
	}
}

// GetBalance recupera o saldo da conta
func (c *CapsolverClient) GetBalance() (float64, error) {
	payload := map[string]string{"clientKey": c.APIKey}
	jsonData, _ := json.Marshal(payload)

	resp, err := c.Client.Post(CAPSOLVER_API+"/getBalance", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result BalanceResponse
	json.Unmarshal(body, &result)

	return result.Balance, nil
}

// SolveTurnstile soluciona um desafio de Cloudflare Turnstile
func (c *CapsolverClient) SolveTurnstile(websiteURL, siteKey string) (string, error) {
	log.Printf("Criando tarefa de Turnstile para %s", websiteURL)

	// Criar tarefa
	task := map[string]interface{}{
		"type":       "AntiTurnstileTaskProxyLess",
		"websiteURL": websiteURL,
		"websiteKey": siteKey,
	}

	payload := map[string]interface{}{
		"clientKey": c.APIKey,
		"task":      task,
	}

	jsonData, _ := json.Marshal(payload)
	resp, err := c.Client.Post(CAPSOLVER_API+"/createTask", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("falha ao criar tarefa: %w", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var createResult CreateTaskResponse
	json.Unmarshal(body, &createResult)

	if createResult.ErrorID != 0 {
		return "", fmt.Errorf("erro da API: %s - %s", createResult.ErrorCode, createResult.ErrorDescription)
	}

	log.Printf("Tarefa criada: %s", createResult.TaskID)

	// Verificar resultado
	for i := 0; i < 120; i++ {
		result, err := c.getTaskResult(createResult.TaskID)
		if err != nil {
			return "", err
		}

		if result.Status == "ready" {
			log.Printf("CAPTCHA resolvido com sucesso!")
			return result.Solution.Token, nil
		}

		if result.Status == "failed" {
			return "", fmt.Errorf("tarefa falhou: %s", result.ErrorDescription)
		}

		if i%10 == 0 {
			log.Printf("Aguardando solução... (%ds)", i)
		}
		time.Sleep(1 * time.Second)
	}

	return "", fmt.Errorf("tempo esgotado esperando solução")
}

func (c *CapsolverClient) getTaskResult(taskID string) (*GetTaskResultResponse, error) {
	payload := map[string]string{
		"clientKey": c.APIKey,
		"taskId":    taskID,
	}

	jsonData, _ := json.Marshal(payload)
	resp, err := c.Client.Post(CAPSOLVER_API+"/getTaskResult", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result GetTaskResultResponse
	json.Unmarshal(body, &result)

	return &result, nil
}

// extractSiteKey extrai a chave do site do Cloudflare Turnstile da HTML da página
func extractSiteKey(html string) string {
	// Procurar por atributo data-sitekey
	patterns := []string{
		`data-sitekey="`,
		`data-sitekey='`,
		`"sitekey":"`,
		`'sitekey':'`,
	}

	for _, pattern := range patterns {
		if idx := strings.Index(html, pattern); idx != -1 {
			start := idx + len(pattern)
			end := start
			for end < len(html) && html[end] != '"' && html[end] != '\'' {
				end++
			}
			if end > start {
				return html[start:end]
			}
		}
	}
	return ""
}

// injectTurnstileToken injeta o token resolvido na página
func injectTurnstileToken(page *rod.Page, token string) error {
	js := fmt.Sprintf(`
		(function() {
			// Definir o token
			var tokenField = document.querySelector('input[name="cf-turnstile-response"]');
			if (tokenField) {
				tokenField.value = '%s';
			}

			// Ativar o campo de token
			var tokenInput = document.querySelector('input[name="cf-turnstile-response"]');
			if (tokenInput) {
				tokenInput.setAttribute('data-solution', '%s');
				tokenInput.dispatchEvent(new Event('input', { bubbles: true }));
			}

			// Verificar se o token foi injetado
			if (document.querySelector('input[name="cf-turnstile-response"]')) {
				return true;
			} else {
				return false;
			}
		})();
	`, token, token)

	_, err := page.Eval(js)
	return err
}

func main() {
	// Verificar chave de API
	if CAPSOLVER_API_KEY == "" {
		log.Fatal("A variável de ambiente CAPSOLVER_API_KEY é necessária")
	}

	// URL alvo - página de demonstração do Cloudflare Turnstile
	targetURL := "https://cf-turnstile-demo.glitch.me/"

	log.Println("==============================================")
	log.Println("Katana + Capsolver - Demonstração de Cloudflare Turnstile")
	log.Println("==============================================")

	// Inicializar cliente do Capsolver
	client := NewCapsolverClient(CAPSOLVER_API_KEY)

	// Verificar saldo
	balance, err := client.GetBalance()
	if err != nil {
		log.Printf("Aviso: Não foi possível verificar o saldo: %v", err)
	} else {
		log.Printf("Saldo do Capsolver: $%.2f", balance)
	}

	// Iniciar navegador
	log.Println("Iniciando navegador...")
	path, _ := launcher.LookPath()
	u := launcher.New().Bin(path).Headless(true).MustLaunch()
	browser := rod.New().ControlURL(u).MustConnect()
	defer browser.MustClose()

	// Navegar até o alvo
	log.Printf("Navegando até: %s", targetURL)
	page := browser.MustPage(targetURL)
	page.MustWaitLoad()
	time.Sleep(2 * time.Second)

	// Obter HTML da página e extrair a chave do site
	html := page.MustHTML()

	// Verificar Cloudflare Turnstile
	if !strings.Contains(html, "cf-turnstile") {
		log.Fatal("Nenhum Cloudflare Turnstile encontrado na página")
	}

	log.Println("Cloudflare Turnstile detectado!")

	// Extrair chave do site
	siteKey := extractSiteKey(html)
	if siteKey == "" {
		log.Fatal("Não foi possível extrair a chave do site")
	}
	log.Printf("Chave do site: %s", siteKey)

	// Resolver CAPTCHA
	log.Println("Resolvendo CAPTCHA com o Capsolver...")
	token, err := client.SolveTurnstile(targetURL, siteKey)
	if err != nil {
		log.Fatalf("Falha ao resolver CAPTCHA: %v", err)
	}

	log.Printf("Token recebido: %s...", token[:50])

	// Injetar token
	log.Println("Injetando token na página...")
	err = injectTurnstileToken(page, token)
	if err != nil {
		log.Fatalf("Falha ao injetar token: %v", err)
	}

	// Submeter formulário
	log.Println("Submetendo formulário...")
	submitBtn := page.MustElement("button[type='submit']")
	submitBtn.MustClick()

	// Aguardar resultado
	time.Sleep(3 * time.Second)

	// Verificar resultado
	newHTML := page.MustHTML()
	if strings.Contains(newHTML, "success") || strings.Contains(newHTML, "Verification Success") {
		log.Println("==============================================")
		log.Println("SUCESSO! Cloudflare Turnstile resolvido e verificado!")
		log.Println("==============================================")
	} else {
		log.Println("Formulário submetido - verifique a página para o resultado")
	}

	// Obter título da página
	title := page.MustEval(`document.title`).String()
	log.Printf("Título da página final: %s", title)
}

"websiteKey": siteKey,
}

Copy
payload := map[string]interface{}{
	"clientKey": c.APIKey,
	"task":      task,
}

jsonData, _ := json.Marshal(payload)
resp, err := c.Client.Post(CAPSOLVER_API+"/createTask", "application/json", bytes.NewBuffer(jsonData))
if err != nil {
	return "", fmt.Errorf("falha ao criar tarefa: %w", err)
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
var createResult CreateTaskResponse
json.Unmarshal(body, &createResult)

if createResult.ErrorID != 0 {
	return "", fmt.Errorf("erro da API: %s - %s", createResult.ErrorCode, createResult.ErrorDescription)
}

log.Printf("Tarefa criada: %s", createResult.TaskID)

// Verificar resultado
for i := 0; i < 120; i++ {
	result, err := c.getTaskResult(createResult.TaskID)
	if err != nil {
		return "", err
	}

	if result.Status == "ready" {
		log.Printf("Turnstile resolvido com sucesso!")
		return result.Solution.Token, nil
	}

	if result.Status == "failed" {
		return "", fmt.Errorf("tarefa falhou: %s", result.ErrorDescription)
	}

	if i%10 == 0 {
		log.Printf("Aguardando solução... (%ds)", i)
	}
	time.Sleep(1 * time.Second)
}

return "", fmt.Errorf("tempo esgotado ao aguardar solução")

}

func (c *CapsolverClient) getTaskResult(taskID string) (*GetTaskResultResponse, error) {
payload := map[string]string{
"clientKey": c.APIKey,
"taskId": taskID,
}

Copy
jsonData, _ := json.Marshal(payload)
resp, err := c.Client.Post(CAPSOLVER_API+"/getTaskResult", "application/json", bytes.NewBuffer(jsonData))
if err != nil {
	return nil, err
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
var result GetTaskResultResponse
json.Unmarshal(body, &result)

return &result, nil

}

// extractTurnstileSiteKey extrai a chave do site Turnstile do HTML da página
func extractTurnstileSiteKey(html string) string {
// Padrão 1: atributo data-sitekey em div cf-turnstile
patterns := []string{
cf-turnstile[^>]*data-sitekey=['"]([^'"]+)['"],
data-sitekey=['"]([^'"]+)['"][^>]*class=['"][^'"]*cf-turnstile,
turnstile\.render\s*\([^,]+,\s*\{[^}]*sitekey['":\s]+['"]([^'"]+)['"],
sitekey['":\s]+['"]([0-9a-zA-Z_-]+)['"],
}

Copy
for _, pattern := range patterns {
	re := regexp.MustCompile(pattern)
	matches := re.FindStringSubmatch(html)
	if len(matches) > 1 {
		return matches[1]
	}
}

return ""

}

// injectTurnstileToken injeta o token resolvido na página
func injectTurnstileToken(page *rod.Page, token string) error {
js := fmt.Sprintf(`
(function() {
// Definir o campo cf-turnstile-response
var responseField = document.querySelector('[name="cf-turnstile-response"]');
if (responseField) {
responseField.value = '%s';
}

Copy
		// Também tentar encontrar por ID
		var byId = document.getElementById('cf-turnstile-response');
		if (byId) {
			byId.value = '%s';
		}

		// Criar campo oculto se necessário
		if (!responseField && !byId) {
			var input = document.createElement('input');
			input.type = 'hidden';
			input.name = 'cf-turnstile-response';
			input.value = '%s';
			var form = document.querySelector('form');
			if (form) {
				form.appendChild(input);
			}
		}

		// Tentar disparar callback
		if (window.turnstile && window.turnstileCallback) {
			window.turnstileCallback('%s');
		}

		return true;
	})();
`, token, token, token, token)

_, err := page.Eval(js)
return err

}

func main() {
// Verificar chave de API
if CAPSOLVER_API_KEY == "" {
log.Fatal("variável de ambiente CAPSOLVER_API_KEY é obrigatória")
}

Copy
// URL alvo - Substituir por um site que use Cloudflare Turnstile
targetURL := "https://example.com"

log.Println("==============================================")
log.Println("Katana + Capsolver - Demonstração de Turnstile")
log.Println("==============================================")

// Inicializar cliente Capsolver
client := NewCapsolverClient(CAPSOLVER_API_KEY)

// Verificar saldo
balance, err := client.GetBalance()
if err != nil {
	log.Printf("Aviso: Não foi possível verificar o saldo: %v", err)
} else {
	log.Printf("Saldo Capsolver: $%.2f", balance)
}

// Iniciar navegador
log.Println("Iniciando navegador...")
path, _ := launcher.LookPath()
u := launcher.New().Bin(path).Headless(true).MustLaunch()
browser := rod.New().ControlURL(u).MustConnect()
defer browser.MustClose()

// Navegar para o alvo
log.Printf("Navegando para: %s", targetURL)
page := browser.MustPage(targetURL)
page.MustWaitLoad()
time.Sleep(2 * time.Second)

// Obter HTML da página
html := page.MustHTML()

// Verificar se há Turnstile
if !strings.Contains(html, "cf-turnstile") && !strings.Contains(html, "turnstile") {
	log.Println("Nenhum Turnstile encontrado na página")
	log.Println("Dica: Substitua targetURL por um site que use Cloudflare Turnstile")
	return
}

log.Println("Turnstile da Cloudflare detectado!")

// Extrair chave do site
siteKey := extractTurnstileSiteKey(html)
if siteKey == "" {
	log.Fatal("Não foi possível extrair a chave do site")
}
log.Printf("Chave do site: %s", siteKey)

// Resolver Turnstile
log.Println("Resolvendo Turnstile com Capsolver...")
token, err := client.SolveTurnstile(targetURL, siteKey)
if err != nil {
	log.Fatalf("Falha ao resolver Turnstile: %v", err)
}

log.Printf("Token recebido: %s...", token[:min(50, len(token))])

// Injetar token
log.Println("Injetando token na página...")
err = injectTurnstileToken(page, token)
if err != nil {
	log.Fatalf("Falha ao injetar token: %v", err)
}

log.Println("==============================================")
log.Println("SUCESSO! Token do Turnstile injetado!")
log.Println("==============================================")

// Obter título da página
title := page.MustEval(`document.title`).String()
log.Printf("Título da página: %s", title)

}

func min(a, b int) int {
if a < b {
return a
}
return b
}

Copy
### Pontos Chave do Turnstile

1. **Tipo de Tarefa**: Use `AntiTurnstileTaskProxyLess`
2. **Campo de Resposta**: O Turnstile usa `cf-turnstile-response` em vez de `g-recaptcha-response`
3. **Resolução Mais Rápida**: O Turnstile geralmente é resolvido mais rápido que o reCAPTCHA (1-10 segundos)
4. **Campo do Token**: A solução está em `solution.token` em vez de `solution.gRecaptchaResponse`

---

## Crawler Universal de CAPTCHA

Aqui está um crawler completo e modular que lida automaticamente com todos os tipos de CAPTCHA:

```go
// Crawler de CAPTCHA Universal - Exemplo Completo
// Detecta e resolve automaticamente reCAPTCHA v2 e Turnstile
// Uso: go run main.go -url "https://example.com"
// Requer: variável de ambiente CAPSOLVER_API_KEY

package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
)

// ============================================
// Configuração
// ============================================

var (
	CAPSOLVER_API_KEY = os.Getenv("CAPSOLVER_API_KEY")
	CAPSOLVER_API     = "https://api.capsolver.com"
)

// CaptchaType representa diferentes tipos de CAPTCHA
type CaptchaType string

const (
	RecaptchaV2 CaptchaType = "recaptcha_v2"
	Turnstile   CaptchaType = "turnstile"
	Unknown     CaptchaType = "unknown"
)

// CaptchaInfo contém os parâmetros extraídos do CAPTCHA
type CaptchaInfo struct {
	Type    CaptchaType
	SiteKey string
}

// ============================================
// Tipos de API
// ============================================

type CreateTaskResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	TaskID           string `json:"taskId"`
}

type GetTaskResultResponse struct {
	ErrorID          int    `json:"errorId"`
	ErrorCode        string `json:"errorCode"`
	ErrorDescription string `json:"errorDescription"`
	Status           string `json:"status"`
	Solution         struct {
		GRecaptchaResponse string `json:"gRecaptchaResponse"`
		Token              string `json:"token"`
	} `json:"solution"`
}

type BalanceResponse struct {
	ErrorID int     `json:"errorId"`
	Balance float64 `json:"balance"`
}

// ============================================
// Cliente Capsolver
// ============================================

type CapsolverClient struct {
	APIKey string
	Client *http.Client
}

func NewCapsolverClient(apiKey string) *CapsolverClient {
	return &CapsolverClient{
		APIKey: apiKey,
		Client: &http.Client{Timeout: 120 * time.Second},
	}
}

func (c *CapsolverClient) GetBalance() (float64, error) {
	payload := map[string]string{"clientKey": c.APIKey}
	jsonData, _ := json.Marshal(payload)

	resp, err := c.Client.Post(CAPSOLVER_API+"/getBalance", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result BalanceResponse
	json.Unmarshal(body, &result)

	return result.Balance, nil
}

func (c *CapsolverClient) Solve(info *CaptchaInfo, websiteURL string) (string, error) {
	switch info.Type {
	case RecaptchaV2:
		return c.solveRecaptchaV2(websiteURL, info.SiteKey)
	case Turnstile:
		return c.solveTurnstile(websiteURL, info.SiteKey)
	default:
		return "", fmt.Errorf("tipo de CAPTCHA não suportado: %s", info.Type)
	}
}

func (c *CapsolverClient) solveRecaptchaV2(websiteURL, siteKey string) (string, error) {
	task := map[string]interface{}{
		"type":       "ReCaptchaV2TaskProxyLess",
		"websiteURL": websiteURL,
		"websiteKey": siteKey,
	}
	return c.solveTask(task, "recaptcha")
}

func (c *CapsolverClient) solveTurnstile(websiteURL, siteKey string) (string, error) {
	task := map[string]interface{}{
		"type":       "AntiTurnstileTaskProxyLess",
		"websiteURL": websiteURL,
		"websiteKey": siteKey,
	}
	return c.solveTask(task, "turnstile")
}

func (c *CapsolverClient) solveTask(task map[string]interface{}, tokenType string) (string, error) {
	// Criar tarefa
	payload := map[string]interface{}{
		"clientKey": c.APIKey,
		"task":      task,
	}

	jsonData, _ := json.Marshal(payload)
	resp, err := c.Client.Post(CAPSOLVER_API+"/createTask", "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("falha ao criar tarefa: %w", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var createResult CreateTaskResponse
	json.Unmarshal(body, &createResult)

	if createResult.ErrorID != 0 {
		return "", fmt.Errorf("erro da API: %s - %s", createResult.ErrorCode, createResult.ErrorDescription)
	}

	log.Printf("Tarefa criada: %s", createResult.TaskID)

	// Verificar resultado
	for i := 0; i < 120; i++ {
		getPayload := map[string]string{
			"clientKey": c.APIKey,
			"taskId":    createResult.TaskID,
		}

		jsonData, _ := json.Marshal(getPayload)
		resp, err := c.Client.Post(CAPSOLVER_API+"/getTaskResult", "application/json", bytes.NewBuffer(jsonData))
		if err != nil {
			return "", err
		}

		body, _ := io.ReadAll(resp.Body)
		resp.Body.Close()

		var result GetTaskResultResponse
		json.Unmarshal(body, &result)

		if result.Status == "ready" {
			if tokenType == "turnstile" {
				return result.Solution.Token, nil
			}
			return result.Solution.GRecaptchaResponse, nil
		}

		if result.Status == "failed" {
			return "", fmt.Errorf("tarefa falhou: %s", result.ErrorDescription)
		}

		if i%10 == 0 {
			log.Printf("Aguardando solução... (%ds)", i)
		}
		time.Sleep(1 * time.Second)
	}

	return "", fmt.Errorf("tempo esgotado ao aguardar solução")
}

// ============================================
// Detecção de CAPTCHA
// ============================================

func DetectCaptcha(html string) *CaptchaInfo {
	// Verificar reCAPTCHA v2 (checkbox)
	if strings.Contains(html, "g-recaptcha") {
		siteKey := extractDataSiteKey(html, "g-recaptcha")
		if siteKey != "" {
			return &CaptchaInfo{
				Type:    RecaptchaV2,
				SiteKey: siteKey,
			}
		}
	}

	// Verificar Cloudflare Turnstile
	if strings.Contains(html, "cf-turnstile") || strings.Contains(html, "challenges.cloudflare.com/turnstile") {
		siteKey := extractDataSiteKey(html, "cf-turnstile")
		if siteKey != "" {
			return &CaptchaInfo{
				Type:    Turnstile,
				SiteKey: siteKey,
			}
		}
	}

	return nil
}

func extractDataSiteKey(html, className string) string {
	pattern := fmt.Sprintf(`class=['"][^'"]*%s[^'"]*['"][^>]*data-sitekey=['"]([^'"]+)['"]`, className)
	re := regexp.MustCompile(pattern)
	matches := re.FindStringSubmatch(html)
	if len(matches) > 1 {
		return matches[1]
	}

	// Padrão alternativo
	pattern = fmt.Sprintf(`data-sitekey=['"]([^'"]+)['"][^>]*class=['"][^'"]*%s`, className)
	re = regexp.MustCompile(pattern)
	matches = re.FindStringSubmatch(html)
	if len(matches) > 1 {
		return matches[1]
	}

	// Padrão genérico para sitekey
	re = regexp.MustCompile(`data-sitekey=['"]([^'"]+)['"]`)
	matches = re.FindStringSubmatch(html)
	if len(matches) > 1 {
		return matches[1]
	}

	return ""
}

// ============================================
// Injeção de Token
// ============================================

func InjectToken(page *rod.Page, token string, captchaType CaptchaType) error {
	var js string

	switch captchaType {
	case RecaptchaV2:
		js = fmt.Sprintf(`
			(function() {
				var responseField = document.getElementById('g-recaptcha-response');
				if (responseField) {
					responseField.style.display = 'block';
					responseField.value = '%s';
				}

				var textareas = document.querySelectorAll('textarea[name="g-recaptcha-response"]');
				for (var i = 0; i < textareas.length; i++) {
					textareas[i].value = '%s';
				}

				if (typeof ___grecaptcha_cfg !== 'undefined') {
					var clients = ___grecaptcha_cfg.clients;
					for (var key in clients) {
						var client = clients[key];
						if (client) {
							try {
								var callback = client.callback ||
									(client.Q && client.Q.callback) ||
									(client.S && client.S.callback);
								if (typeof callback === 'function') {
									callback('%s');
								}
							} catch(e) {}
						}
					}
				}
				return true;
			})();
		`, token, token, token)

	case Turnstile:
		js = fmt.Sprintf(`
			(function() {
				var responseField = document.querySelector('[name="cf-turnstile-response"]');
				if (responseField) {
					responseField.value = '%s';
				}

				if (!responseField) {
					var input = document.createElement('input');
					input.type = 'hidden';
					input.name = 'cf-turnstile-response';
					input.value = '%s';
					var form = document.querySelector('form');
					if (form) form.appendChild(input);
				}

				if (window.turnstile && window.turnstileCallback) {
					window.turnstileCallback('%s');
				}
				return true;
			})();
		`, token, token, token)

	default:
		return fmt.Errorf("tipo de CAPTCHA não suportado: %s", captchaType)
	}

	_, err := page.Eval(js)
	return err
}

// ============================================
// Crawler
// ============================================

type CrawlResult struct {
	URL           string
	Title         string
	Success       bool
	CaptchaFound  bool
	CaptchaType   CaptchaType
	CaptchaSolved bool
	Error         string
}

func Crawl(browser *rod.Browser, client *CapsolverClient, targetURL string) *CrawlResult {
	result := &CrawlResult{
		URL:     targetURL,
Sucesso: false,
	}

	// Navegar para o destino
	log.Printf("Navegando para: %s", targetURL)
	page := browser.MustPage(targetURL)
	defer page.MustClose()

	page.MustWaitLoad()
	time.Sleep(2 * time.Second)

	// Obter HTML da página
	html := page.MustHTML()

	// Detectar CAPTCHA
	captchaInfo := DetectCaptcha(html)

	if captchaInfo != nil && captchaInfo.Type != Unknown {
		result.CaptchaFound = true
		result.CaptchaType = captchaInfo.Type

		log.Printf("CAPTCHA detectado: %s (siteKey: %s)", captchaInfo.Type, captchaInfo.SiteKey)

		// Resolver CAPTCHA
		log.Println("Resolvendo CAPTCHA com Capsolver...")
		token, err := client.Solve(captchaInfo, targetURL)
		if err != nil {
			result.Error = fmt.Sprintf("falha ao resolver CAPTCHA: %v", err)
			log.Printf("Erro: %s", result.Error)
			return result
		}

		log.Printf("Token recebido: %s...", token[:min(50, len(token))])

		// Injetar token
		log.Println("Injetando token...")
		err = InjectToken(page, token, captchaInfo.Type)
		if err != nil {
			result.Error = fmt.Sprintf("falha ao injetar token: %v", err)
			log.Printf("Erro: %s", result.Error)
			return result
		}

		result.CaptchaSolved = true
		log.Println("Token injetado com sucesso!")

		// Tentar enviar formulário
		submitForm(page)
		time.Sleep(3 * time.Second)
	} else {
		log.Println("Nenhum CAPTCHA detectado na página")
	}

	// Obter informações da página final
	result.Title = page.MustEval(`document.title`).String()
	result.Success = true

	return result
}

func submitForm(page *rod.Page) {
	selectors := []string{
		"button[type='submit']",
		"input[type='submit']",
		"#recaptcha-demo-submit",
		".submit-button",
	}

	for _, selector := range selectors {
		js := fmt.Sprintf(`
			(function() {
				var btn = document.querySelector('%s');
				if (btn && btn.offsetParent !== null) {
					btn.click();
					return true;
				}
				return false;
			})();
		`, selector)

		result := page.MustEval(js)
		if result.Bool() {
			log.Printf("Clicado no botão de envio: %s", selector)
			return
		}
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// ============================================
// Principal
// ============================================

func main() {
	// Analisar flags
	targetURL := flag.String("url", "https://www.google.com/recaptcha/api2/demo", "URL alvo para navegação")
	headless := flag.Bool("headless", true, "Executar o navegador em modo sem cabeça")
	checkBalance := flag.Bool("balance", false, "Verificar apenas o saldo da conta")
	flag.Parse()

	// Verificar chave de API
	if CAPSOLVER_API_KEY == "" {
		log.Fatal("A variável de ambiente CAPSOLVER_API_KEY é obrigatória")
	}

	log.Println("==============================================")
	log.Println("Katana + Capsolver - Crawler Universal de CAPTCHA")
	log.Println("==============================================")

	// Inicializar cliente
	client := NewCapsolverClient(CAPSOLVER_API_KEY)

	// Verificar saldo
	balance, err := client.GetBalance()
	if err != nil {
		log.Printf("Aviso: Não foi possível verificar o saldo: %v", err)
	} else {
		log.Printf("Saldo do Capsolver: $%.2f", balance)
	}

	if *checkBalance {
		return
	}

	// Iniciar navegador
	log.Println("Iniciando navegador...")
	path, _ := launcher.LookPath()
	u := launcher.New().Bin(path).Headless(*headless).MustLaunch()
	browser := rod.New().ControlURL(u).MustConnect()
	defer browser.MustClose()

	// Navegar
	result := Crawl(browser, client, *targetURL)

	// Exibir resultados
	log.Println("==============================================")
	log.Println("RESULTADOS DA NAVEGAÇÃO")
	log.Println("==============================================")
	log.Printf("URL: %s", result.URL)
	log.Printf("Título: %s", result.Title)
	log.Printf("Sucesso: %v", result.Success)
	log.Printf("CAPTCHA Detectado: %v", result.CaptchaFound)
	if result.CaptchaFound {
		log.Printf("Tipo de CAPTCHA: %s", result.CaptchaType)
		log.Printf("CAPTCHA Resolvido: %v", result.CaptchaSolved)
	}
	if result.Error != "" {
		log.Printf("Erro: %s", result.Error)
	}
	log.Println("==============================================")
}

Uso

bash Copy
# Criar projeto
mkdir katana-universal-crawler
cd katana-universal-crawler
go mod init katana-universal-crawler

# Instalar dependências
go get github.com/go-rod/rod@latest

# Definir chave de API
export CAPSOLVER_API_KEY="SUA_CHAVE_DE_API"

# Executar com padrão (demonstração reCAPTCHA v2)
go run main.go

# Executar com URL personalizada
go run main.go -url "https://exemplo.com"

# Verificar saldo apenas
go run main.go -balance

# Executar com navegador visível
go run main.go -headless=false

Boas Práticas

1. Otimização de Desempenho

  • Usar tipos de tarefa sem proxy: ReCaptchaV2TaskProxyLess usa proxies internos do Capsolver para resolver mais rapidamente
  • Processamento paralelo: Comece a resolver CAPTCHA enquanto outros elementos da página carregam
  • Cache de tokens: Tokens de reCAPTCHA são válidos por ~2 minutos; cache quando possível

2. Gestão de Custos

  • Detectar antes de resolver: Chame o Capsolver apenas quando um CAPTCHA realmente estiver presente
  • Validar chaves de site: Certifique-se de que as chaves extraídas sejam válidas antes das chamadas à API
  • Monitorar uso: Rastreie chamadas à API para gerenciar custos efetivamente

3. Tratamento de Erros

go Copy
func SolveWithRetry(client *CapsolverClient, info *CaptchaInfo, url string, maxRetries int) (string, error) {
    var lastErr error

    for i := 0; i < maxRetries; i++ {
        token, err := client.Solve(info, url)
        if err == nil {
            return token, nil
        }

        lastErr = err
        log.Printf("Tentativa %d falhou: %v", i+1, err)

        // Backoff exponencial
        time.Sleep(time.Duration(i+1) * time.Second)
    }

    return "", fmt.Errorf("falha após %d tentativas: %w", maxRetries, lastErr)
}

4. Limitação de Taxa

Implemente atrasos apropriados entre solicitações para evitar detecção:

go Copy
type RateLimiter struct {
    requests    int
    interval    time.Duration
    lastRequest time.Time
    mu          sync.Mutex
}

func (r *RateLimiter) Wait() {
    r.mu.Lock()
    defer r.mu.Unlock()

    elapsed := time.Since(r.lastRequest)
    if elapsed < r.interval {
        time.Sleep(r.interval - elapsed)
    }
    r.lastRequest = time.Now()
}

Solução de Problemas

Erros Comuns

Erro Causa Solução
ERROR_ZERO_BALANCE Créditos insuficientes Recarregar conta do Capsolver
ERROR_CAPTCHA_UNSOLVABLE Chave de site inválida Verificar lógica de extração
ERROR_INVALID_TASK_DATA Parâmetros ausentes Verificar estrutura da tarefa
context deadline exceeded Tempo limite Aumentar tempo limite ou verificar rede

Dicas de Depuração

  1. Ativar navegador visível: Definir Headless(false) para ver o que está acontecendo
  2. Logar tráfego de rede: Monitorar solicitações para identificar problemas
  3. Salvar capturas de tela: Capturar estado da página para depuração
  4. Validar tokens: Registrar formato do token antes da injeção

Perguntas Frequentes

Q: Posso usar o Katana sem modo sem cabeça para páginas de CAPTCHA?
A: Não, páginas de CAPTCHA exigem renderização de JavaScript, que só funciona no modo sem cabeça.

Q: Por quanto tempo os tokens de CAPTCHA são válidos?
A: Tokens de reCAPTCHA: ~2 minutos. Turnstile: varia conforme configuração.

Q: Qual é o tempo médio de resolução?
A: reCAPTCHA v2: 5-15s, Turnstile: 1-10s.

Q: Posso usar meu próprio proxy?
A: Sim, use tipos de tarefa sem o sufixo "ProxyLess" e forneça a configuração do proxy.


Conclusão

Integrar o Capsolver com o Katana permite lidar com CAPTCHA de forma robusta para suas necessidades de raspagem de web. Os scripts completos acima podem ser copiados diretamente e usados com seus projetos Go.

Pronto para começar? Registre-se no Capsolver e potencialize seus raspadores!

💡 Bônus Exclusivo para Usuários de Integração Katana:
Para comemorar esta integração, oferecemos um código de bônus exclusivo de 6% — Katana para todos os usuários do CapSolver que se registrarem por meio deste tutorial.
Basta inserir o código durante o recarregamento no Dashboard para receber créditos extras de 6% instantaneamente.


12. Documentações

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

Selenium vs. Puppeteer para a resolução de CAPTCHA
Selenium vs Puppeteer para Resolução de CAPTCHA: Comparação de Desempenho e Caso de Uso

Compare o Selenium vs Puppeteer para resolver CAPTCHA. Descubra benchmarks de desempenho, notas de estabilidade e como integrar o CapSolver para o máximo de sucesso.

web scraping
Logo of CapSolver

Ethan Collins

08-Apr-2026

Dados como Serviço (DaaS): O que é e por que importa em 2026
Dados como Serviço (DaaS): O que é e por que importa em 2026

Entenda Dados como Serviço (DaaS) em 2026. Descubra seus benefícios, casos de uso e como transforma os negócios com visões em tempo real e escalabilidade.

web scraping
Logo of CapSolver

Ethan Collins

12-Feb-2026

Como corrigir erros comuns de raspagem da web em 2026
Como corrigir erros comuns de raspagem da web em 2026

Dominar a correção de diversos erros de raspagem de web, como 400, 401, 402, 403, 429, 5xx e 1001 do Cloudflare em 2026. Aprenda estratégias avançadas para rotação de IPs, cabeçalhos e limitação de taxa adaptativa com o CapSolver.

web scraping
Logo of CapSolver

Rajinder Singh

05-Feb-2026

RoxyBrowser com Integração CapSolver
Como resolver Captcha no RoxyBrowser com integração do CapSolver

Integre o CapSolver com o RoxyBrowser para automatizar tarefas do navegador e contornar o reCAPTCHA, o Turnstile e outros CAPTCHAS.

web scraping
Logo of CapSolver

Adélia Cruz

04-Feb-2026

Easyspider CapSolver Integração de Captcha
Como resolver Captcha no EasySpider com integração do CapSolver

EasySpider é uma ferramenta de raspagem de web e automação do navegador visual e sem código, e quando combinado com o CapSolver, pode resolver de forma confiável CAPTCHAs como reCAPTCHA v2 e Cloudflare Turnstile, permitindo a extração de dados automatizada sem interrupções em sites.

web scraping
Logo of CapSolver

Adélia Cruz

04-Feb-2026

Relevância AI com CapSolver
Como resolver reCAPTCHA v2 no Relevance AI com integração da CapSolver

Construa uma ferramenta da Relevance AI para resolver reCAPTCHA v2 usando o CapSolver. Automatize os envios de formulários via API sem automação de navegador.

web scraping
Logo of CapSolver

Adélia Cruz

03-Feb-2026