CAPSOLVER
Blog
Como resolver o fingerprinting TLS em n8n com o CapSolver

Como resolver o fingerprinting TLS no n8n com o CapSolver

Logo of CapSolver

Adélia Cruz

Neural Network Developer

18-Mar-2026

Se você já tentou raspar um site protegido por detecção de bots de nível corporativo, provavelmente encontrou uma parede invisível: seus pedidos são bloqueados mesmo que seus cabeçalhos, cookies e User-Agent sejam perfeitos. O motivo? Fingerprinting TLS — e acontece antes que a solicitação HTTP seja enviada.

Serviços anti-bot como Cloudflare, Akamai, DataDome e outros inspecionam o handshake TLS para determinar se o cliente é um navegador real ou uma ferramenta de automação. Clientes HTTP padrão — net/http do Go, requests do Python, curl, axios do Node.js — todos têm fingerprints TLS distintos que são marcados imediatamente.

Neste guia, você criará um servidor Go leve usando httpcloak que imita um fingerprint TLS do Chrome real e o conectará aos seus fluxos de trabalho n8n para que cada solicitação HTTP pareça tráfego de navegador Chrome genuíno no nível da rede.


O que é Fingerprinting TLS?

Toda vez que um cliente se conecta a um site por HTTPS, inicia um handshake TLS enviando uma mensagem ClientHello. Esta mensagem contém:

  • Conjuntos de criptografia — os algoritmos de criptografia que o cliente suporta e sua ordem
  • Extensões TLS — recursos como SNI, ALPN, grupos suportados, algoritmos de assinatura
  • Curvas elípticas e formatos de ponto — parâmetros criptográficos
  • Versão TLS — a versão máxima de TLS suportada

Serviços anti-bot extraem esses valores e calculam um fingerprint — chamado de JA3 ou JA4 — que identifica unicamente o software do cliente. Cada navegador, biblioteca HTTP e runtime de linguagem de programação produz um fingerprint diferente.

Cliente Fingerprint JA3 Detectado Como
Chrome 145 Hash único correspondente à ordem dos conjuntos de criptografia do Chrome Navegador real
Firefox 130 Hash diferente — o Firefox usa preferências de conjunto de criptografia diferentes Navegador real
Go net/http Hash completamente diferente — a pilha TLS do Go é óbvia Bot / ferramenta de automação
Python requests Outro hash distinto — o TLS do urllib3 do Python é identificável Bot / ferramenta de automação
curl Outro hash — o fingerprint TLS do curl é bem conhecido Bot / ferramenta de automação
Node.js axios Fingerprint TLS do Node.js — facilmente marcado Bot / ferramenta de automação

A dica principal: o fingerprinting TLS acontece durante o handshake, antes que quaisquer cabeçalhos HTTP sejam enviados. Nenhuma manipulação de cabeçalhos pode corrigir um fingerprint TLS não navegador.


Por que os Clientes HTTP Padrão Falham

Quando um navegador se conecta a um site por HTTPS, ele envia um ClientHello TLS que inclui detalhes sobre seus conjuntos de criptografia, extensões e configurações suportados. Serviços anti-bot registram esse fingerprint (chamado de fingerprint JA3 ou JA4) e o comparam a perfis conhecidos de navegadores.

net/http do Go, requests do Python, curl e a maioria das bibliotecas HTTP têm fingerprints TLS distintos. Mesmo com cookies e cabeçalhos corretos, os sistemas anti-bot bloquearão a solicitação se detectarem um fingerprint TLS não navegador.

Aqui está o que acontece passo a passo:

  1. Seu fluxo de trabalho n8n envia uma solicitação HTTP para um site protegido
  2. O handshake TLS começa — seu cliente envia seu ClientHello
  3. O serviço anti-bot registra o fingerprint JA3/JA4 do handshake
  4. O fingerprint corresponde a Go/Python/Node.js — não a Chrome ou Firefox
  5. A solicitação é bloqueada, desafiada ou serve uma página de engano — antes que seus cabeçalhos sejam avaliados

É por isso que definir User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... não ajuda. O User-Agent é um cabeçalho de nível HTTP. O fingerprinting TLS opera em uma camada mais baixa. Se seu User-Agent diz Chrome, mas seu fingerprint TLS diz Go, a solicitação é imediatamente marcada.


Quem Usa Fingerprinting TLS?

O fingerprinting TLS tornou-se prática padrão na proteção contra bots corporativos. Aqui estão os principais serviços que verificam fingerprints TLS:

Serviço Anti-Bot Verificação TLS Observações
Cloudflare Bot Management Sim Desafio "Verificando seu navegador..." em toda página. Verifica JA3/JA4 em cada solicitação
Akamai Bot Manager Sim Usa fingerprinting TLS como um dos muitos sinais no score de bot
DataDome Sim Analisa o fingerprint TLS junto com sinais comportamentais
Muitos outros Varia O fingerprinting TLS está se tornando padrão na proteção contra bots corporativos

CapSolver suporta a resolução de desafios de muitos desses serviços. O servidor TLS neste guia foi projetado para funcionar junto com qualquer fluxo de resolução de captchas onde a última solicitação HTTP precisa parecer tráfego de navegador real — seja para contornar o desafio Cloudflare, Akamai, DataDome ou qualquer outro sistema anti-bot.


Requisitos Prévios

Requisito Notas
n8n auto-hospedado Obrigatório — o servidor TLS deve executar na mesma máquina que o n8n. O n8n Cloud não é adequado.
Go 1.21+ Deve estar instalado no servidor. Verifique com go version.
Gerenciador de processos (recomendado) Qualquer gerenciador de processos (systemd, supervisor, Docker, PM2) para manter o servidor TLS em execução após reinícios

Passo 1 — Construir o Servidor TLS

O servidor TLS é um servidor HTTP leve em Go que aceita solicitações na porta 7878 e as encaminha usando o preset Chrome-145 do httpcloak.

Criar o arquivo de origem

bash Copy
mkdir -p ~/tls-server && cd ~/tls-server

Crie um arquivo chamado main.go com o seguinte conteúdo:

go Copy
package main

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

	"github.com/sardanioss/httpcloak/client"
)

type FetchRequest struct {
	URL     string            `json:"url"`
	Method  string            `json:"method"`
	Headers map[string]string `json:"headers"`
	Proxy   string            `json:"proxy"`
	Body    string            `json:"body"`
}

type FetchResponse struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

type ErrorResponse struct {
	Error string `json:"error"`
}

func writeError(w http.ResponseWriter, status int, msg string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(ErrorResponse{Error: msg})
}

func fetchHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		writeError(w, http.StatusMethodNotAllowed, "only POST allowed")
		return
	}

	var req FetchRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
		return
	}

	if req.URL == "" {
		writeError(w, http.StatusBadRequest, "url is required")
		return
	}
	if req.Method == "" {
		req.Method = "GET"
	}

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	c := client.NewClient("chrome-145", client.WithTimeout(60*time.Second))
	defer c.Close()

	if req.Proxy != "" {
		c.SetProxy(req.Proxy)
	}

	headers := make(map[string][]string, len(req.Headers))
	var userAgent string
	for k, v := range req.Headers {
		lower := strings.ToLower(k)
		if lower == "user-agent" {
			userAgent = v
		} else {
			headers[k] = []string{v}
		}
	}

	var bodyReader io.Reader
	if req.Body != "" {
		bodyReader = strings.NewReader(req.Body)
	}

	hcReq := &client.Request{
		Method:    strings.ToUpper(req.Method),
		URL:       req.URL,
		Headers:   headers,
		Body:      bodyReader,
		UserAgent: userAgent,
		FetchMode: client.FetchModeNavigate,
	}

	resp, err := c.Do(ctx, hcReq)
	if err != nil {
		writeError(w, http.StatusBadGateway, "fetch failed: "+err.Error())
		return
	}

	body, err := resp.Text()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "read body failed: "+err.Error())
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(FetchResponse{
		Status:  resp.StatusCode,
		Body:    body,
		Headers: resp.Headers,
	})
}

func main() {
	const port = "7878"

	mux := http.NewServeMux()
	mux.HandleFunc("/fetch", fetchHandler)
	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, `{"status":"ok"}`)
	})

	log.Printf("Servidor TLS (httpcloak chrome-145) ouvindo em :%s", port)
	log.Fatal(http.ListenAndServe(":"+port, mux))
}

Inicializar e construir

bash Copy
go mod init tls-server
go get github.com/sardanioss/httpcloak/client
go build -o main main.go

Executar o servidor

bash Copy
./main

O servidor roda em primeiro plano. Para mantê-lo em execução em segundo plano, use qualquer gerenciador de processos (systemd, supervisor, Docker, etc.) ou execute-o em uma sessão screen/tmux.

Verificar se está rodando (em um novo terminal)

bash Copy
curl http://localhost:7878/health

Esperado: {"status":"ok"}

Nota: O servidor TLS deve executar na mesma máquina que sua instância n8n. O fluxo de trabalho n8n o chama em http://localhost:7878/fetch.


Passo 2 — Permitir que o n8n Chame o Localhost

Por padrão, o n8n bloqueia os nós de Requisição HTTP de chamarem endereços localhost (proteção contra SSRF). Você precisa desativar isso para que seus fluxos de trabalho possam alcançar o servidor TLS em localhost:7878.

Adicione a variável de ambiente N8N_BLOCK_ACCESS_TO_LOCALHOST=false e reinicie sua instância n8n. Como você faz isso depende de como executa o n8n:

Se você executar o n8n diretamente:

bash Copy
export N8N_BLOCK_ACCESS_TO_LOCALHOST=false
n8n start

Se você usar Docker:

Adicione -e N8N_BLOCK_ACCESS_TO_LOCALHOST=false ao seu comando docker run, ou adicione-o à seção environment no seu docker-compose.yml.


Passo 3 — Usando o Servidor TLS do n8n

O servidor TLS expõe um único endpoint que aceita qualquer solicitação HTTP e a encaminha com um fingerprint TLS do Chrome.

Referência da API

Endpoint: POST http://localhost:7878/fetch

Corpo da solicitação (JSON):

json Copy
{
  "url": "https://example.com",
  "method": "GET",
  "headers": {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
    "cookie": "cf_clearance=abc123; session=xyz"
  },
  "proxy": "http://user:pass@host:port",
  "body": ""
}
Campo Tipo Obrigatório Descrição
url string Sim A URL alvo para buscar
method string Não Método HTTP — padrão para GET
headers objeto Não Pares chave-valor dos cabeçalhos HTTP a enviar
proxy string Não URL do proxy no formato http://user:pass@host:port
body string Não Corpo da solicitação (para solicitações POST/PUT)

Resposta (JSON):

json Copy
{
  "status": 200,
  "body": "<html>...</html>",
  "headers": { "content-type": ["text/html"], "..." : ["..."] }
}

Configurando o Nó de Requisição HTTP do n8n

Para chamar o servidor TLS de um fluxo de trabalho n8n, use um nó Requisição HTTP com estas configurações:

Parâmetro Valor Descrição
Método POST Sempre POST para o servidor TLS
URL http://localhost:7878/fetch Endpoint do servidor TLS local
Tipo de conteúdo Bruto Não use JSON — o modo JSON do n8n serializa incorretamente
Tipo de conteúdo bruto application/json Informe ao servidor TLS que o corpo é JSON
Corpo ={{ JSON.stringify({ url: "...", method: "GET", headers: {...}, proxy: "..." }) }} A solicitação real a ser encaminhada

Importante: Usar contentType: "json" com JSON.stringify() no corpo faz com que o n8n serialize duas vezes, enviando {"": ""} em vez dos seus dados. Sempre use contentType: "bruto" com rawContentType: "application/json".

Exemplo: Buscando uma Página Protegida

Na expressão do corpo do nó de Requisição HTTP:

javascript Copy
={{ JSON.stringify({
  url: "https://protected-site.com/data",
  method: "GET",
  headers: {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "accept-language": "en-US,en;q=0.9"
  },
  proxy: "http://user:pass@proxy-host:8080"
}) }}

O servidor TLS encaminhará esta solicitação com um fingerprint TLS do Chrome-145, e o alvo verá uma conexão de navegador Chrome genuíno.


Teste-o

Teste o servidor TLS diretamente da linha de comando:

bash Copy
curl -X POST http://localhost:7878/fetch \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tls-check.example.com",
    "method": "GET",
    "headers": {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
    }
  }'

Você pode verificar seu fingerprint TLS apontando o servidor para um verificador de fingerprint JA3/JA4 — o resultado deve corresponder a um navegador Chrome real, não a um cliente da biblioteca Go.


Importar Este Fluxo

Este fluxo cria um endpoint de webhook que encaminha qualquer solicitação através do servidor TLS com um fingerprint TLS do Chrome. Envie um POST com url, method, headers e proxy opcional — o fluxo o passa para localhost:7878/fetch e retorna o resultado.

Copy
Webhook (POST /tls-fetch) → Buscar via Servidor TLS → Responder ao Webhook

Copie o JSON abaixo e importe-o no n8n via Menu → Importar do JSON.

Clique para expandir o JSON do fluxo
json Copy
{
  "name": "TLS Fetch — Chrome Fingerprint Proxy",
  "nodes": [
    {
      "parameters": {
        "content": "## TLS Fetch — Chrome Fingerprint Proxy\n\n**Para quem é:** Desenvolvedores que precisam de solicitações HTTP com fingerprints TLS de navegador autênticos.\n\n**O que ele faz:** Proxy de solicitações HTTP através de um servidor TLS Go (httpcloak) que imita o fingerprint TLS do Chrome, contornando a detecção de bots.\n\n**Como funciona:**\n1. Webhook recebe a URL e os detalhes da solicitação\n2. A solicitação é encaminhada para o servidor TLS local com o fingerprint do Chrome\n3. A resposta é retornada ao chamador\n\n**Configuração:**\n1. Certifique-se de que o servidor TLS (httpcloak) esteja rodando na porta 7878\n2. Ative o fluxo\n3. Envie um POST para a URL do webhook com seus detalhes da solicitação",
        "height": 494,
        "width": 460,
        "color": 1
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -720,
        -300
      ],
      "id": "sticky-blog-main-1773678228122-1",
      "name": "Nota Colante"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "tls-fetch",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -200,
        0
      ],
      "id": "tls00001-0001-0001-0001-000000000001",
      "name": "Receber Solicitação do Solver",
      "webhookId": "tls00001-aaaa-bbbb-cccc-000000000001"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://localhost:7878/fetch",
        "sendBody": true,
"contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify($json.body) }}",
        "options": {
          "timeout": 60000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        100,
        0
      ],
      "id": "tls00001-0001-0001-0001-000000000002",
      "name": "Buscar via Servidor TLS"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        400,
        0
      ],
      "id": "tls00001-0001-0001-0001-000000000003",
      "name": "Responder ao Webhook"
    }
  ],
  "connections": {
    "Receive Solver Request": {
      "main": [
        [
          {
            "node": "Buscar via Servidor TLS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar via Servidor TLS": {
      "main": [
        [
          {
            "node": "Responder ao Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
``

---

## Conclusão

Você configurou um servidor de falsificação de impressão digital TLS que faz com que as requisições HTTP do n8n pareçam tráfego autêntico do navegador Chrome no nível de rede. Isso é essencial para raspagem de sites protegidos por serviços anti-bot que analisam impressões digitais TLS.

Este servidor HTTP é útil para contornar:
- **Cloudflare Bot Management** — desafios de página inteira que verificam impressões digitais TLS
- **Akamai Bot Manager** — detecção de bots empresarial usando análise TLS
- **DataDome** — análise comportamental + impressão digital TLS
- **PerimeterX / HUMAN** — fingerprinting de dispositivo + TLS
- **Muitos outros serviços anti-bot** que o CapSolver suporta

A biblioteca httpcloak com seu preset Chrome-145 trata da falsificação de impressões digitais JA3/JA4, frames SETTINGS HTTP/2, negociação ALPN e ordem de cabeçalhos — tornando suas requisições indistinguíveis de um navegador Chrome real no nível TLS.

---

> **Precisa resolver CAPTCHAs junto com a falsificação TLS?** Confira o [CapSolver](https://www.capsolver.com/?utm_source=official&utm_medium=blog&utm_campaign=n8n) — ele se integra diretamente ao n8n como um nó oficial e suporta Cloudflare Challenge, Turnstile, reCAPTCHA e muitos outros. Use o código de bônus **n8n** para obter um bônus adicional de 8% na primeira recarga!

![Banner de código de bônus do CapSolver](https://assets.capsolver.com/prod/posts/how-to-solve-recaptcha-v2-n8n/UXwrijPMSvAB-d2b5ca33bd970f64a6301fa75ae2eb22.png)

---

## Perguntas Frequentes

### O que é fingerprinting TLS?
O fingerprinting TLS é uma técnica em que os servidores analisam as características da mensagem ClientHello TLS — incluindo suites de criptografia, extensões e sua ordem — para identificar qual software está fazendo a conexão. Cada cliente HTTP (Chrome, Firefox, curl, Go, Python) tem um padrão de impressão digital único.

### Por que não posso apenas definir o cabeçalho User-Agent como Chrome?
O cabeçalho User-Agent é um atributo de nível HTTP. O fingerprinting TLS acontece em um nível mais baixo — durante o handshake TLS, antes que quaisquer cabeçalhos HTTP sejam enviados. Serviços anti-bot comparam ambas as camadas: se o User-Agent diz Chrome, mas a impressão digital TLS diz Go/Python, a requisição é marcada como bot.

### O que é httpcloak?
[httpcloak](https://github.com/sardanioss/httpcloak) é uma biblioteca Go que falsifica perfis TLS reais de navegadores. Ela lida com correspondência de impressões digitais JA3/JA4, frames SETTINGS HTTP/2, negociação ALPN e ordem de cabeçalhos. O preset `chrome-145` torna as conexões indistinguíveis de um navegador Chrome real 145.

### Posso usar outro preset de versão do Chrome?
Sim. O httpcloak suporta múltiplos presets de navegadores. Consulte a [documentação do httpcloak](https://github.com/sardanioss/httpcloak) para ver os presets disponíveis. Para alterar o preset, modifique `client.NewClient("chrome-145", ...)` no `main.go` para o seu perfil de navegador desejado.

### Isso funciona com o n8n Cloud?
Não facilmente. O servidor TLS é um binário Go local que precisa rodar na mesma máquina que o n8n para que os fluxos de trabalho possam chamar `http://localhost:7878/fetch`. O n8n Cloud não permite executar serviços locais junto com fluxos de trabalho. Você precisa de uma instância do n8n auto-hospedada.

### Posso executar o servidor TLS em outra máquina?
Sim, mas você precisará atualizar a URL nos nós de Requisição HTTP do n8n de `http://localhost:7878/fetch` para `http://seu-endereço-ip:7878/fetch` e garantir que a porta 7878 esteja acessível. Você também precisará desativar a proteção SSRF do n8n ou whiteliste o IP do servidor.

### Como atualizo o preset do Chrome quando uma nova versão for lançada?
Atualize a dependência httpcloak: `go get -u github.com/sardanioss/httpcloak/client`, altere a string do preset no `main.go` para a nova versão, reconstrua com `go build -o main main.go` e reinicie o servidor.

### O servidor TLS suporta requisições concorrentes?
Sim. O servidor HTTP do Go lida com requisições concorrentes nativamente. Cada requisição cria uma instância nova do cliente httpcloak com sua própria conexão TLS. Para cargas de trabalho de alto volume, monitore o uso de memória, pois cada conexão mantém seu próprio estado TLS.

### Qual é a sobrecarga de desempenho?
O servidor TLS adiciona latência mínima — tipicamente 10-50ms para a passagem local. A maior parte do tempo da requisição é gasta na conexão HTTPS real com o destino. O handshake TLS do Chrome é ligeiramente mais pesado que o padrão do Go, mas isso é insignificante na prática.

### Como mantenho o servidor TLS rodando após reinícios do servidor?
Use qualquer gerenciador de processos — systemd, supervisor, Docker ou similares — para registrar o servidor TLS como um serviço que inicia na inicialização. Para uma configuração rápida, você também pode executá-lo dentro de uma sessão `screen` ou `tmux`.

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