
Adélia Cruz
Neural Network Developer

A proteção contra bots da Cloudflare vai muito além dos widgets CAPTCHA. O Cloudflare Challenge — a tela de "Verificando seu navegador…" em página cheia que bloqueia totalmente o acesso a um site — é uma das defesas contra bots mais agressivas na web. Ele executa um desafio JavaScript completo em um ambiente real de navegador, verifica sinais comportamentais e identifica digitalmente sua conexão TLS antes de permitir o acesso.
As ferramentas de automação padrão falham aqui. Não porque não consigam resolver o desafio, mas porque a Cloudflare faz a identificação digital do handshake TLS — e qualquer cliente HTTP não navegadore é bloqueado antes mesmo do desafio ser servido, ou é re-desafiado imediatamente depois, mesmo com um cookie válido cf_clearance.
Neste guia, você aprenderá como construir um scraper para o Cloudflare Challenge no n8n que realmente funciona — combinando o CapSolver para resolver o desafio, um servidor TLS local em Go para falsificar a digital TLS do Chrome, e um fluxo de trabalho n8n para integrar tudo.
O que você irá construir:
O Cloudflare Challenge (também chamado de desafio JS ou desafio de Bot Management) é um intersticial em página cheia que a Cloudflare injeta antes que um visitante possa acessar um site protegido. Você já deve ter visto: uma tela preta ou branca com "Verificando seu navegador…" ou "Só um momento…" com uma barra de carregamento ou o logo da Cloudflare.
Diferente do Turnstile — que é um pequeno widget embutido dentro de uma página — o Cloudflare Challenge ocupa a página inteira. Você não pode acessar qualquer conteúdo até que ele seja concluído.
| Cloudflare Challenge | Cloudflare Turnstile | |
|---|---|---|
| Onde aparece | Intersticial em página cheia — bloqueia o acesso ao site totalmente | Widget embutido dentro de uma página (ex: formulário de login) |
| Como é | Tela de carregamento "Verificando seu navegador…" | Uma pequena caixa de seleção ou widget invisível em um formulário |
| Quem adiciona | Cloudflare adiciona automaticamente baseado em regras de segurança | O dono do site embute no HTML |
| Abordagem para resolver | AntiCloudflareTask — requer proxy |
AntiTurnstileTaskProxyLess — não precisa proxy |
| Cookie retornado | cf_clearance (específico do domínio, ligado ao IP) |
Token Turnstile (curta duração, uso único) |
| Necessita proxy? | Sim — o mesmo IP deve ser usado para resolver e buscar | Não |
Se você vir uma caixa de seleção embutida ou widget dentro de um formulário, isso é Turnstile — não este desafio. Confira o guia CapSolver sobre como identificar tipos de desafio se estiver em dúvida.
Aqui está o problema que a maioria dos guias ignora: a Cloudflare verifica a sua digital TLS, não apenas seus cookies.
Quando um navegador conecta-se a um site via HTTPS, ele envia um TLS ClientHello que inclui detalhes sobre seus cipher suites suportados, extensões e configurações. A Cloudflare registra essa digital (chamada de digital JA3 ou JA4) e compara com perfis de navegadores conhecidos.
As bibliotecas net/http do Go, requests do Python, curl, e a maioria das bibliotecas HTTP possuem digitais TLS distintas. Mesmo que o CapSolver resolva o desafio com sucesso e retorne um cookie válido cf_clearance, a Cloudflare irá re-chamar o desafio ou bloquear a requisição se detectar uma digital TLS não navegadora na busca subsequente.
A solução: um servidor Go usando httpcloak — uma biblioteca que falsifica uma pilha TLS real do Chrome incluindo:
Isso faz a busca parecer exatamente como uma requisição de navegador Chrome no nível da rede.
| Requisito | Observações |
|---|---|
| n8n self-hosted | Necessário — o servidor TLS deve rodar na mesma máquina que o n8n. n8n Cloud não é adequado para esse caso. |
| Conta CapSolver | Cadastre-se aqui e obtenha sua chave API |
| Go 1.21+ | Deve estar instalado no servidor n8n. Verifique com go version. |
| Proxy residencial ou móvel | Proxies de datacenter falharão na maioria dos sites protegidos pela Cloudflare. Veja Requisitos de proxy abaixo. |
CapSolver está disponível como uma integração oficial no n8n — não é necessário instalar um nó da comunidade.
Vá para a sua instância n8n e navegue até Settings → Credentials.

AllVocê deverá ver a faixa verde "Connection tested successfully".

Importante: Cada nó CapSolver em seus fluxos referencia esta credencial. Você só precisa criá-la uma vez — todos os seus fluxos de solução compartilharão esta credencial.
Este servidor Go recebe requisições de fetch do n8n e as executa usando o perfil TLS do Chrome do httpcloak. É um binário pequeno e auto-contido que você roda junto do n8n.
Crie um diretório e salve o seguinte como main.go:
mkdir -p ~/tls-server && cd ~/tls-server
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)
}
// Extract user-agent separately so httpcloak uses it instead of its preset value.
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("TLS server (httpcloak chrome-145) listening on :%s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}
go mod init tls-server
go get github.com/sardanioss/httpcloak/client
go build -o main main.go
./main
curl http://localhost:7878/health
Esperado: {"status":"ok"}
Nota: O servidor TLS deve rodar na mesma máquina que sua instância n8n. O fluxo n8n o chama em
http://localhost:7878/fetch. Se você usa n8n Cloud, precisará de uma instalação self-hosted — este é um dos motivos pelos quais o n8n self-hosted é fortemente recomendado para scraping com Cloudflare Challenge.
Por padrão, o n8n bloqueia nodos HTTP Request de fazer chamadas para endereços localhost (proteção SSRF). Você precisa desabilitar essa restrição.
Adicione a variável de ambiente N8N_BLOCK_ACCESS_TO_LOCALHOST=false e reinicie sua instância n8n. Como fazer isso depende de como você roda o n8n:
Se você roda o n8n diretamente:
export N8N_BLOCK_ACCESS_TO_LOCALHOST=false
n8n start
Se você usa Docker:
Adicione -e N8N_BLOCK_ACCESS_TO_LOCALHOST=false ao comando docker run, ou adicione na seção environment do seu docker-compose.yml.
Este fluxo cria um endpoint POST que aceita uma URL protegida pela Cloudflare e proxy, resolve o desafio via CapSolver e retorna o cookie bruto cf_clearance e o userAgent. Nenhum servidor TLS necessário — sua aplicação faz o fetch.
Webhook (POST /solver-cloudflare-challenge) → Cloudflare Challenge (CapSolver)
→ Format Solution → Responder o Webhook
4 nós, apenas webhook, sem caminho de agendamento, sem dependência de servidor TLS.
websiteURL e proxyAntiCloudflareTaskcookies em string de cookie, trata erros com continueOnFailcf_clearance, string de cookie serializada, e userAgent### Configuração do Nó| Configuração | Valor |
|---|---|
| Método HTTP | POST |
| Caminho | solver-cloudflare-challenge |
| Responder | Response Node |
Isso cria um endpoint em: https://your-n8n-instance.com/webhook/solver-cloudflare-challenge
| Parâmetro | Valor | Descrição |
|---|---|---|
| Operação | Cloudflare Challenge |
Seleciona AntiCloudflareTask |
| Tipo | AntiCloudflareTask |
Desafio Cloudflare de página completa |
| URL do Site | ={{ $json.body.websiteURL }} |
A URL protegida pelo Cloudflare |
| Proxy | ={{ $json.body.proxy }} |
Proxy residencial no formato host:port:user:pass |
| Continuar em caso de Falha | true |
Retorna erros estruturados ao invés de travar |
O CapSolver lança um navegador real via seu proxy, carrega a URL alvo e resolve o desafio do Cloudflare. Quando bem-sucedido, retorna um objeto solution contendo:
cookies — um objeto { cf_clearance: "..." } com o cookie de permissãouserAgent — a string exata do User-Agent que o navegador usou durante a resoluçãoNota: O campo é
websiteURL(nãotargetURL) — combinando com o nome de campo usado por todas as outras APIs do Solver e pelo próprio nó CapSolver.
Este nó é necessário porque AntiCloudflareTask retorna cookies como um objeto ({ cf_clearance: "..." }), não uma simples string de token como reCAPTCHA ou Turnstile. Ele serializa o cookie, extrai cf_clearance e retorna um erro estruturado caso o CapSolver tenha falhado.
const input = $input.first().json;
if (input.error || !input.data || !input.data.solution) {
const errorMsg = input.error
? (input.error.message || JSON.stringify(input.error))
: 'Nenhuma solução retornada — o site pode não estar mostrando um desafio';
return [{ json: { success: false, error: errorMsg } }];
}
const solution = input.data.solution;
const cookies = solution.cookies;
const cfClearance = (cookies && typeof cookies === 'object')
? (cookies.cf_clearance || '') : '';
const cookieString = (cookies && typeof cookies === 'object')
? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')
: (cookies || '');
return [{ json: {
success: true,
cf_clearance: cfClearance,
cookies: cookieString,
userAgent: solution.userAgent || '',
solvedAt: new Date().toISOString()
}}];
| Configuração | Valor |
|---|---|
| Responder Com | JSON |
| Corpo da Resposta | ={{ JSON.stringify($json) }} |
curl -X POST https://your-n8n-instance.com/webhook/solver-cloudflare-challenge \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://protected-site.com",
"proxy": "host:port:user:pass"
}'
Resposta bem-sucedida:
{
"success": true,
"cf_clearance": "abc123...",
"cookies": "cf_clearance=abc123...",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/145.0.0.0 ...",
"solvedAt": "2026-03-11T12:00:00.000Z"
}
Resposta falha (nenhum desafio encontrado, proxy ruim, etc.):
{
"success": false,
"error": "Nenhuma solução retornada — o site pode não estar mostrando um desafio"
}
Copie o JSON abaixo e importe-o no n8n via Menu → Importar do JSON. Após importar, selecione suas credenciais CapSolver no nó Cloudflare Challenge.
{
"nodes": [
{
"parameters": {
"content": "## Cloudflare Challenge \u2014 Solver API\n\n### How it works\n\n1. Receives a request via webhook to solve a Cloudflare challenge.\n2. Uses the Cloudflare Challenge node to attempt solving the challenge.\n3. Formats the solved challenge token via custom code.\n4. Responds back to the original request with the solved token.\n\n### Setup steps\n\n- [ ] Configure the Webhook node to receive requests.\n- [ ] Set up CapSolver credentials to enable solving Cloudflare challenges.\n- [ ] Ensure the Response node is properly configured to send back the solved token.\n\n### Customization\n\nYou can customize the code in the 'Format Solution' node to change the formatting of the solved token response.",
"width": 480,
"height": 672
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-816,
-128
],
"id": "254f3829-0e6e-4ae3-bf83-85851be9a7bc",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Receive and solve challenge\n\nTriggers on a new request and attempts to solve the Cloudflare challenge.",
"width": 512,
"height": 304,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-256,
-128
],
"id": "44e79738-a2f0-41ec-8ff0-514afbd6cc45",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Format and return solution\n\nFormats the solution and responds back with the solved token.",
"width": 496,
"height": 304,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
352,
-128
],
"id": "fc40112d-389d-4d4e-8872-af2ae533c513",
"name": "Sticky Note2"
},
{
"parameters": {
"httpMethod": "POST",
"path": "solver-cloudflare-challenge",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-208,
0
],
"id": "cf770001-7777-7777-7777-777777777701",
"name": "Receive Solver Request",
"webhookId": "cf770001-aaaa-bbbb-cccc-777777777701",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.body.websiteURL }}",
"proxy": "={{ $json.body.proxy }}",
"userAgent": "={{ $json.body.userAgent }}",
"html": "={{ $json.body.html }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
112,
0
],
"id": "cf770001-7777-7777-7777-777777777702",
"name": "Cloudflare Challenge",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "CapSolver account"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const input = $input.first().json;\n\nif (input.error || !input.data || !input.data.solution) {\n const errorMsg = input.error\n ? (input.error.message || JSON.stringify(input.error))\n : 'No solution returned \u2014 site may not be showing a challenge';\n return [{ json: { success: false, error: errorMsg } }];\n}\n\nconst solution = input.data.solution;\nconst cookies = solution.cookies;\nconst cfClearance = (cookies && typeof cookies === 'object') ? (cookies.cf_clearance || '') : '';\nconst cookieString = (cookies && typeof cookies === 'object')\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n\nreturn [{ json: {\n success: true,\n cf_clearance: cfClearance,\n cookies: cookieString,\n userAgent: solution.userAgent || '',\n solvedAt: new Date().toISOString()\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
],
"id": "cf770001-7777-7777-7777-777777777703",
"name": "Format Solution"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
700,
0
],
"id": "cf770001-7777-7777-7777-777777777704",
"name": "Return Solved Token"
}
],
"connections": {
"Receive Solver Request": {
"main": [
[
{
"node": "Cloudflare Challenge",
"type": "main",
"index": 0
}
]
]
},
"Cloudflare Challenge": {
"main": [
[
{
"node": "Format Solution",
"type": "main",
"index": 0
}
]
]
},
"Format Solution": {
"main": [
[
{
"node": "Return Solved Token",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Até agora, a API do Solver acima mostra como obter um cookie cf_clearance resolvido e o userAgent. Mas o que você realmente faz com eles?
Ao contrário do reCAPTCHA ou Turnstile, onde você envia um token em um campo de formulário, o Desafio Cloudflare retorna um cookie (cf_clearance) que deve ser enviado como um cabeçalho em todas as requisições subsequentes. O cookie está vinculado ao IP do proxy e ao User-Agent usados durante a solução — ambos devem coincidir exatamente na requisição.
Aqui está o padrão geral:
cf_clearance e o userAgent do CapSolversec-ch-ua semelhantes ao Chromehttp://localhost:7878/fetch para combinar a impressão digital TLS do ChromeConceito chave: Clientes HTTP padrão falham aqui mesmo com um cookie
cf_clearanceválido — Cloudflare identifica a negociação TLS em si. O servidor Go TLS (httpcloak) faz a busca parecer exatamente o Chrome no nível da rede. Todo workflow que busca uma página protegida pelo Cloudflare deve passar pelo servidor TLS.### Exemplo: Raspador de Desafios Cloudflare

Caminho de agendamento:
A cada 6 horas → Definir Configuração do Alvo [Schedule] → Resolver Desafio Cloudflare
→ Preparar Requisição TLS → Buscar via Servidor TLS → Extrair Resultado
Caminho do webhook:
Gatilho do Webhook → Definir Configuração do Alvo [Webhook] → Resolver Desafio Cloudflare
→ Preparar Requisição TLS → Buscar via Servidor TLS → Extrair Resultado → Responder ao Webhook
targetURL e proxy (no formato host:port:user:pass). O caminho de agendamento usa valores codificados; o caminho do webhook os lê do corpo do POST.onError: "continueRegularOutput" — continua mesmo se a página não estiver exibindo um desafio no momento.host:port:user:pass para o formato de URL http://user:pass@host:port, serializa solution.cookies para uma string de cabeçalho de cookies e monta cabeçalhos de requisição semelhantes ao Chrome com o userAgent exato da resolução.http://localhost:7878/fetch usando contentType: "raw" (não "json" — o modo JSON do n8n corrompe o corpo).status, body e fetchedAt da resposta do servidor TLS.Por que
contentType: "raw"e não"json"? O modo de tipo de conteúdojsondo n8n espera parâmetros do corpo como pares de chave-valor. Se você passarJSON.stringify($json)como uma string, o n8n trata toda a string como um único parâmetro malformado e envia{"": ""}para o servidor. Usar o modorawenvia o corpo exatamente como a expressão é avaliada.
{
"nodes": [
{
"parameters": {
"content": "## Desafio Cloudflare — CapSolver + Schedule + Webhook\n\n### Como funciona\n\n1. Aciona agendamento a cada 6 horas para resolver desafios Cloudflare.\n2. Webhook é acionado em requisição para resolver desafios Cloudflare.\n3. Define configuração do alvo e proxy para requisições.\n4. Resolve o desafio Cloudflare usando CapSolver.\n5. Envia resultados via TLS e processa a resposta HTTP.\n\n### Passos de configuração\n\n- Certifique-se de que as credenciais do CapSolver estão configuradas.\n- Confirme que a URL do webhook está definida e acessível.\n- Verifique a configuração do agendamento para acionamento a cada 6 horas.\n- Verifique se o endpoint http://localhost:7878/fetch está disponível.\n\n### Personalização\n\nConsidere personalizar a URL do alvo ou as configurações do proxy dentro dos nós definidos.",
"width": 480,
"height": 688
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1008,
-112
],
"id": "3c1c3e96-631a-4cf6-bbff-85fd8b1a01e8",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Desafio Cloudflare Agendado\n\nAcionado a cada 6 horas para resolver o desafio Cloudflare.",
"width": 1696,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-448,
-112
],
"id": "e9187404-7818-4233-af66-091c90a40476",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Desafio Cloudflare via Webhook\n\nResponde às solicitações do resolvedor via webhook para resolver o desafio Cloudflare.",
"width": 2000,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-448,
304
],
"id": "b5d5ba23-8ed2-4afb-8113-3fa8f2fba51e",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-400,
0
],
"id": "cf111111-1111-1111-1111-111111111101",
"name": "A cada 6 Horas"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-s-001",
"name": "targetURL",
"value": "https://www.listaspam.com/busca.php?Telefono=671484239",
"type": "string"
},
{
"id": "cfg-s-002",
"name": "proxy",
"value": "YOUR_PROXY_HOST:PORT:USER:PASS",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-96,
0
],
"id": "cf111111-1111-1111-1111-111111111102",
"name": "Definir Configuração do Alvo [Schedule]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
208,
0
],
"id": "cf111111-1111-1111-1111-111111111103",
"name": "Resolver Desafio Cloudflare [Schedule]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const config = $('Set Target Config [Schedule]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'none',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.targetURL,\n method: 'GET',\n proxy: toProxyURL(config.proxy),\n headers\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
512,
0
],
"id": "cf111111-1111-1111-1111-111111111104",
"name": "Preparar Requisição TLS [Schedule]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
800,
0
],
"id": "cf111111-1111-1111-1111-111111111105",
"name": "Buscar via Servidor TLS [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "out-s-001",
"name": "status",
"value": "={{ $json.status }}",
"type": "number"
},
{
"id": "out-s-002",
"name": "body",
"value": "={{ $json.body }}",
"type": "string"
},
{
"id": "out-s-003",
"name": "fetchedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1104,
0
],
"id": "cf111111-1111-1111-1111-111111111106",
"name": "Extrair Resultado [Schedule]"
},
{
"parameters": {
"httpMethod": "POST",
"path": "cloudflare-scraper",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-400,
420
],
"id": "cf111111-1111-1111-1111-111111111107",
"name": "Receber Solicitação do Resolvedor",
"webhookId": "cf111111-aaaa-bbbb-cccc-111111111107",
"onError": "continueRegularOutput"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-w-001",
"name": "targetURL",
"value": "={{ $json.body.targetURL }}",
"type": "string"
},
{
"id": "cfg-w-002",
"name": "proxy",
"value": "={{ $json.body.proxy }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-96,
420
],
"id": "cf111111-1111-1111-1111-111111111108",
"name": "Definir Configuração do Alvo [Webhook]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
208,
420
],
"id": "cf111111-1111-1111-1111-111111111109",
"name": "Resolver Desafio Cloudflare [Webhook]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const config = $('Set Target Config [Webhook]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'none',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.targetURL,\n method: 'GET',\n proxy: toProxyURL(config.proxy),\n headers\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
512,
420
],
"id": "cf111111-1111-1111-1111-111111111110",
"name": "Preparar Requisição TLS [Webhook]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
800,
420
],
"id": "cf111111-1111-1111-1111-111111111111",
"name": "Buscar via Servidor TLS [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "out-w-001",
"name": "status",
"value": "={{ $json.status }}",
"type": "number"
},
{
"id": "out-w-002",
"name": "body",
"value": "={{ $json.body }}",
"type": "string"
},
{
"id": "out-w-003",
"name": "fetchedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1104,
420
],
"id": "cf111111-1111-1111-1111-111111111112",
"name": "Extrair Resultado [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1408,
420
],
"id": "cf111111-1111-1111-1111-111111111113",
"name": "Retornar Token Resolvido"
}
],
"connections": {
"A cada 6 Horas": {
"main": [
[
{
"node": "Definir Configuração do Alvo [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Definir Configuração do Alvo [Schedule]": {
"main": [
[
{
"node": "Resolver Desafio Cloudflare [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Resolver Desafio Cloudflare [Schedule]": {
"main": [
[
{
"node": "Preparar Requisição TLS [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Preparar Requisição TLS [Schedule]": {
"main": [
[
{
"node": "Buscar via Servidor TLS [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Buscar via Servidor TLS [Schedule]": {
"main": [
[
{
"node": "Extrair Resultado [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Receber Solicitação do Resolvedor": {
"main": [
[
{
"node": "Definir Configuração do Alvo [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Definir Configuração do Alvo [Webhook]": {
"main": [
[
{
"node": "Resolver Desafio Cloudflare [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Resolver Desafio Cloudflare [Webhook]": {
"main": [
[
{
"node": "Preparar Requisição TLS [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Preparar Requisição TLS [Webhook]": {
"main": [
[
{
"node": "Buscar via Servidor TLS [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Buscar via Servidor TLS [Webhook]": {
"main": [
[
{
"node": "Extrair Resultado [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Extrair Resultado [Webhook]": {
"main": [
[
{
"node": "Retornar Token Resolvido",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
---## Workflow: Exemplos de Casos de Uso
A API do Solver e o exemplo do scraper acima mostram o padrão principal: resolver o desafio, usar a solução para buscar via TLS. Os fluxos de trabalho a seguir estendem esse padrão para casos de uso prontos para produção — cada um com gatilhos duplos (agendamento + webhook), rastreamento persistente de estado e saída estruturada. Cada um requer os mesmos pré-requisitos: uma instância auto-hospedada do n8n, o servidor TLS rodando na porta 7878, um proxy residencial e uma credencial CapSolver.
| Workflow | Propósito |
|---|---|
Cloudflare Challenge Scraping — Price & Product Details — CapSolver + Schedule + Webhook |
Raspagem de preço e nome do produto de uma página protegida por CF a cada 6 horas, compara com valores anteriores e alerta em caso de mudanças |
Cloudflare Challenge Account Login — CapSolver + Schedule + Webhook |
Faz login na sua própria conta em um site protegido por CF resolvendo primeiro o desafio, depois enviando as credenciais via POST através do servidor TLS |
Turnstile — Solver API |
Expõe um webhook que resolve o Turnstile e retorna o token — não necessita proxy nem servidor TLS |
Turnstile Scraping — Price & Product Monitor |
Resolve o Turnstile, busca uma página de produto com o token, extrai preço e nome, e alerta sobre mudanças |
Turnstile Account Login |
Faz login na sua própria conta em um site protegido por Turnstile resolvendo primeiro o desafio, depois enviando as credenciais via POST com o token — não necessita proxy nem servidor TLS |
Este fluxo de trabalho faz scraping de uma página de produto a cada 6 horas (agendamento) ou sob demanda (webhook), extrai o preço usando o nó HTML e compara com o valor armazenado anteriormente.
Caminho do agendamento:
A cada 6 horas → Configurar alvo → Resolver desafio CF → Preparar requisição TLS
→ Buscar via servidor TLS → Extrair dados → Comparar dados
→ Dados alterados? → Construir alerta / Sem alteração
Tratamento de erros: Se o CapSolver falhar, o fluxo continua sem cookies (via
continueOnFail). A busca via servidor TLS ainda pode ter sucesso se a página não estiver exibindo um desafio no momento.
Comportamentos chave:
dataPropertyName: "body" (não "data") porque o servidor TLS retorna { status, body, headers }.product-price, h1)$workflow.staticData.lastPrice mantém o preço anterior entre execuçõesdeal) quanto aumentos (gravidade: info)host:port:user:pass → http://user:pass@host:port via helper toProxyURL(){
"nodes": [
{
"parameters": {
"content": "## Scraping de desafio do Cloudflare — Preço e detalhes do produto — CapSolver + Agendamento + Webhook\n\n### Como funciona\n\n1. Gatilhos são configurados para verificar periodicamente o site alvo ou em resposta a um webhook externo.\n2. Configurações para URL alvo e proxies são aplicadas.\n3. Os desafios do Cloudflare são resolvidos para navegar pelas proteções do site.\n4. Requisições seguras são feitas para buscar dados do servidor alvo.\n5. Dados extraídos são comparados para verificar alterações.\n6. Alertas são construídos e enviados ou os dados são retornados com base nas mudanças detectadas.\n\n### Passos de configuração\n\n- [ ] Configure a URL e as configurações de proxy nos nós 'Set Target Config'.\n- [ ] Conecte credenciais do CapSolver para resolver os desafios do Cloudflare.\n- [ ] Certifique-se de que a URL do webhook esteja configurada corretamente para receber requisições externas.\n\n### Personalização\n\nPara ajustar a frequência de monitoramento, modifique o intervalo no nó 'Every 6 Hours' ou nas configurações do gatilho webhook.",
"width": 480,
"height": 896
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1104,
-192
],
"id": "85c55c3d-335a-47e5-8721-82fa4d633033",
"name": "Nota Adesiva"
},
{
"parameters": {
"content": "## Configuração do gatilho agendado\n\nInicializa o agendamento a cada 6 horas para iniciar o processo de scraping de dados via agendamento.",
"width": 1392,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-544,
-112
],
"id": "6ac3bd35-66ef-43ed-a8b5-5d5f6d367fba",
"name": "Nota Adesiva1"
},
{
"parameters": {
"content": "## Processamento de dados agendado\n\nLida com a extração, comparação e construção de alertas após ser acionado pelo agendamento.",
"width": 1088,
"height": 480,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
960,
-192
],
"id": "a1c60513-ed8b-43f2-bff3-a7b19436337f",
"name": "Nota Adesiva2"
},
{
"parameters": {
"content": "## Configuração do gatilho webhook\n\nMonitora requisições externas via webhook para iniciar o processo de scraping.",
"width": 1392,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-544,
384
],
"id": "ee4d9a0d-3233-4b70-828b-078c9eee0086",
"name": "Nota Adesiva3"
},
{
"parameters": {
"content": "## Processamento e resposta de dados do webhook\n\nExtrai e compara dados do gatilho webhook; retorna respostas baseadas em mudanças.",
"width": 1392,
"height": 480,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
960,
336
],
"id": "4ad55fbf-2882-4c63-9e09-37e674b00145",
"name": "Nota Adesiva4"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-500,
0
],
"id": "cf333333-3333-3333-3333-333333333301",
"name": "A cada 6 Horas"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-s-001",
"name": "targetURL",
"value": "https://YOUR_CF_PROTECTED_SITE.com/product-page",
"type": "string"
},
{
"id": "cfg-s-002",
"name": "proxy",
"value": "YOUR_PROXY_HOST:PORT:USER:PASS",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-200,
0
],
"id": "cf333333-3333-3333-3333-333333333302",
"name": "Configurar Alvo [Agendamento]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
100,
0
],
"id": "cf333333-3333-3333-3333-333333333303",
"name": "Resolver Desafio Cloudflare [Agendamento]",
"onError": "continueRegularOutput",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
}
},
{
"parameters": {
"jsCode": "const config = $('Set Target Config [Schedule]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'none',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.targetURL,\n method: 'GET',\n proxy: toProxyURL(config.proxy),\n headers\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
],
"id": "cf333333-3333-3333-3333-333333333304",
"name": "Preparar Requisição TLS [Agendamento]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
700,
0
],
"id": "cf333333-3333-3333-3333-333333333305",
"name": "Buscar via Servidor TLS [Agendamento]"
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
1000,
0
],
"id": "cf333333-3333-3333-3333-333333333306",
"name": "Extrair Dados"
},
{
"parameters": {
"jsCode": "const staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Product';\n\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(',', '')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'dropped' : 'increased') : 'unchanged';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || 'first check',\n changed,\n direction,\n diff: changed ? `$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1300,
0
],
"id": "cf333333-3333-3333-3333-333333333307",
"name": "Comparar Dados"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-001",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1600,
0
],
"id": "cf333333-3333-3333-3333-333333333308",
"name": "Dados Alterados?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-001",
"name": "alert",
"value": "=Preço {{ $json.direction }} para {{ $json.productName }}: {{ $json.previousPrice }} \u2192 {{ $json.currentPrice }} ({{ $json.direction === 'dropped' ? '-' : '+' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-002",
"name": "severity",
"value": "={{ $json.direction === 'dropped' ? 'deal' : 'info' }}",
"type": "string"
},
{
"id": "alert-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1900,
-80
],
"id": "cf333333-3333-3333-3333-333333333309",
"name": "Construir Alerta"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-001",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-002",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-003",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1900,
128
],
"id": "cf333333-3333-3333-3333-333333333310",
"name": "Sem Alteração"
},
{
"parameters": {
"httpMethod": "POST",
"path": "cloudflare-price-monitor",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-500,
500
],
"id": "cf333333-3333-3333-3333-333333333311",
"name": "Receber Requisição de Monitoramento",
"webhookId": "cf333333-aaaa-bbbb-cccc-333333333311",
"onError": "continueRegularOutput"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-w-001",
"name": "targetURL",
"value": "={{ $json.body.targetURL }}",
"type": "string"
},
{
"id": "cfg-w-002",
"name": "proxy",
"value": "={{ $json.body.proxy }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-200,
500
],
"id": "cf333333-3333-3333-3333-333333333312",
"name": "Configurar Alvo [Webhook]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}"
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
100,
500
],
"id": "cf333333-3333-3333-3333-333333333313",
"name": "Resolver Desafio Cloudflare [Webhook]",
"onError": "continueRegularOutput",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
}
},
{
"parameters": {
"jsCode": "const config = $('Set Target Config [Webhook]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'none',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.targetURL,\n method: 'GET',\n proxy: toProxyURL(config.proxy),\n headers\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
500
],
"id": "cf333333-3333-3333-3333-333333333314",
"name": "Preparar Requisição TLS [Webhook]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
700,
500
],
"id": "cf333333-3333-3333-3333-333333333315",
"name": "Buscar via Servidor TLS [Webhook]"
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price",
"returnValue": "text",
"returnArray": false
},
{
"key": "productName",
"cssSelector": "h1, .product-title",
"returnValue": "text",
"returnArray": false
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
1008,
528
],
"id": "cf333333-3333-3333-3333-333333333316",
"name": "Extrair Dados [Webhook]"
},
{
"parameters": {
"jsCode": "const staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Product';\n\nconst parsePrice = (str) => {\n if (!str) return null;\n const match = str.match(/[\\d]+\\.?\\d*/);\n return match ? parseFloat(match[0].replace(',', '')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'dropped' : 'increased') : 'unchanged';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\n\nreturn [{\n json: {\n productName,\n currentPrice,\n previousPrice: previousPrice || 'first check',\n changed,\n direction,\n diff: changed ? `$${diff}` : null,\n checkedAt: new Date().toISOString()\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1296,
528
],
"id": "cf333333-3333-3333-3333-333333333317",
"name": "Comparar Dados [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "price-if-002",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1600,
528
],
"id": "cf333333-3333-3333-3333-333333333318",
"name": "Dados Alterados? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "alert-004",
"name": "alert",
"value": "=Preço {{ $json.direction }} para {{ $json.productName }}: {{ $json.previousPrice }} \u2192 {{ $json.currentPrice }} ({{ $json.direction === 'dropped' ? '-' : '+' }}{{ $json.diff }})",
"type": "string"
},
{
"id": "alert-005",
"name": "severity",
"value": "={{ $json.direction === 'dropped' ? 'deal' : 'info' }}",
"type": "string"
},
{
"id": "alert-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1904,
448
],
"id": "cf333333-3333-3333-3333-333333333319",
"name": "Construir Alerta [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "nc-004",
"name": "status",
"value": "no_change",
"type": "string"
},
{
"id": "nc-005",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
},
{
"id": "nc-006",
"name": "checkedAt",
"value": "={{ $json.checkedAt }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1904,
656
],
"id": "cf333333-3333-3333-3333-333333333320",
"name": "Sem Alteração [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
2208,
528
],
"id": "cf333333-3333-3333-3333-333333333321",
"name": "Retornar Dados Raspados"
}
],
"connections": {
"Every 6 Hours": {
"main": [
[
{
"node": "Set Target Config [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Set Target Config [Schedule]": {
"main": [
[
{
"node": "Solve Cloudflare Challenge [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Solve Cloudflare Challenge [Schedule]": {
"main": [
[
{
"node": "Prepare TLS Request [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Prepare TLS Request [Schedule]": {
"main": [
[
{
"node": "Fetch via TLS Server [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Fetch via TLS Server [Schedule]": {
"main": [
[
{
"node": "Extract Data",
"type": "main",
"index": 0
}
]
]
},
"Extract Data": {
"main": [
[
{
"node": "Compare Data",
"type": "main",
"index": 0
}
]
]
},
"Compare Data": {
"main": [
[
{
"node": "Data Changed?",
"type": "main",
"index": 0
}
]
]
},
"Data Changed?": {
"main": [
[
{
"node": "Build Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change",
"type": "main",
"index": 0
}
]
]
},
"Receive Monitor Request": {
"main": [
[
{
"node": "Set Target Config [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Set Target Config [Webhook]": {
"main": [
[
{
"node": "Solve Cloudflare Challenge [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve Cloudflare Challenge [Webhook]": {
"main": [
[
{
"node": "Prepare TLS Request [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Prepare TLS Request [Webhook]": {
"main": [
[
{
"node": "Fetch via TLS Server [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Fetch via TLS Server [Webhook]": {
"main": [
[
{
"node": "Extract Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Extract Data [Webhook]": {
"main": [
[
{
"node": "Compare Data [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Compare Data [Webhook]": {
"main": [
[
{
"node": "Data Changed? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Data Changed? [Webhook]": {
"main": [
[
{
"node": "Build Alert [Webhook]",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Build Alert [Webhook]": {
"main": [
[
{
"node": "Return Scraped Data",
"type": "main",
"index": 0
}
]
]
},
"No Change [Webhook]": {
"main": [
[
{
"node": "Return Scraped Data",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Este fluxo de trabalho automatiza o login em um site protegido pelo Cloudflare. Um nó Set Login Config centraliza todos os parâmetros — [Schedule] para o caminho da agenda e [Webhook] para o caminho do webhook sob demanda.
Caminho da agenda:
A cada 24 horas → Set Login Config → Solve CF Challenge
→ Prepare TLS Login Request → Submit Login via TLS Server
→ Login Successful? → Marcar Sucesso / Marcar Falha
Tratamento de erros: Se o CapSolver falhar, o fluxo de trabalho continua sem cookies (via
continueOnFail). A requisição de login provavelmente falhará, o que o nó Login Successful? detecta.
Comportamentos principais:
cf_clearance + userAgent como cabeçalhos HTTP (sem token no corpo do formulário — ao contrário do login reCAPTCHA que envia g-recaptcha-response)URLSearchParams — edite os nomes dos campos (usernameField, passwordField) no Set Login Config para corresponder ao seu sitestatus < 400 E successMarker no corpo da resposta{
"nodes": [
{
"parameters": {
"content": "## Cloudflare Challenge Account Login \u2014 CapSolver + Schedule + Webhook\n\n### How it works\n\n1. Schedule a login process every 24 hours and solve the Cloudflare challenge.\n2. Prepare and submit a TLS login request when initiated by schedule.\n3. Handle success or failure of the scheduled login including logging results.\n4. Receive login requests via webhook and solve the Cloudflare challenge.\n5. Prepare and submit a TLS login request when initiated by webhook.\n6. Handle success or failure of the webhook login and return results.\n\n### Setup steps\n\n- [ ] Ensure Cloudflare CapSolver API credentials are configured.\n- [ ] Set up locally running TLS server at http://localhost:7878.\n- [ ] Configure webhook URL to receive login requests.\n\n### Customization\n\nAdjust scheduled intervals to meet specific frequency needs.",
"width": 480,
"height": 896
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1248,
-320
],
"id": "ba1d6098-8cd2-40f1-b9ae-b945303e5d12",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Scheduled login start\n\nStarts the login process every 24 hours as a trigger point for further actions.",
"width": 240,
"height": 336,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-688,
-256
],
"id": "acc8f2a2-298f-4d1b-9db7-8a98fe626abb",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Scheduled login workflow\n\nHandles the Cloudflare challenge, prepares and submits the login request, and checks if it was successful every 24 hours.",
"width": 1328,
"height": 480,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-416,
-320
],
"id": "1259d9f4-0b54-4693-89af-193f3ccda6a0",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "## Webhook login start\n\nAccepts login requests via webhook to start the subsequent workflow.",
"width": 240,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-688,
272
],
"id": "e95374d2-4029-469d-8e8f-a9afb66ae2ed",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## Webhook login workflow\n\nProcesses received webhook login requests, handles Cloudflare challenge, prepares and submits the login request, checks for success, and logs results.",
"width": 1216,
"height": 528,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-416,
192
],
"id": "da56a87e-6675-439a-8c65-7da631a86df1",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "## Return webhook result\n\nResponds to the initial webhook request with the result of the login attempt.",
"width": 240,
"height": 320,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
832,
256
],
"id": "7a3f246c-ebd5-419f-a955-b01669743b31",
"name": "Sticky Note5"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-640,
-80
],
"id": "cf666666-6666-6666-6666-666666666601",
"name": "Every 24 Hours"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-001",
"name": "targetURL",
"value": "https://YOUR_CF_PROTECTED_SITE.com/login",
"type": "string"
},
{
"id": "login-002",
"name": "loginActionURL",
"value": "https://YOUR_CF_PROTECTED_SITE.com/login",
"type": "string"
},
{
"id": "login-003",
"name": "proxy",
"value": "YOUR_PROXY_HOST:PORT:USER:PASS",
"type": "string"
},
{
"id": "login-004",
"name": "usernameField",
"value": "email",
"type": "string"
},
{
"id": "login-005",
"name": "passwordField",
"value": "password",
"type": "string"
},
{
"id": "login-006",
"name": "usernameValue",
"value": "your-email@example.com",
"type": "string"
},
{
"id": "login-007",
"name": "passwordValue",
"value": "YOUR_ACCOUNT_PASSWORD",
"type": "string"
},
{
"id": "login-008",
"name": "successMarker",
"value": "account-dashboard",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-368,
-80
],
"id": "cf666666-6666-6666-6666-666666666602",
"name": "Set Login Config [Schedule]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-144,
-64
],
"id": "cf666666-6666-6666-6666-666666666603",
"name": "Solve Cloudflare Challenge [Schedule]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"jsCode": "const config = $('Set Login Config [Schedule]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst params = new URLSearchParams();\nparams.set(config.usernameField, config.usernameValue);\nparams.set(config.passwordField, config.passwordValue);\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'content-type': 'application/x-www-form-urlencoded',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'same-origin',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.loginActionURL,\n method: 'POST',\n proxy: toProxyURL(config.proxy),\n headers,\n body: params.toString()\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
48,
-64
],
"id": "cf666666-6666-6666-6666-666666666604",
"name": "Prepare TLS Login Request [Schedule]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
240,
-64
],
"id": "cf666666-6666-6666-6666-666666666605",
"name": "Submit Login via TLS Server [Schedule]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "login-if-001",
"leftValue": "={{ $json.status < 400 && String($json.body || '').includes($('Set Login Config [Schedule]').item.json.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
432,
-64
],
"id": "cf666666-6666-6666-6666-666666666606",
"name": "Login Successful? [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-010",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-011",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "login-012",
"name": "message",
"value": "Configured account login flow succeeded (via Cloudflare Challenge bypass)",
"type": "string"
},
{
"id": "login-013",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
768,
-208
],
"id": "cf666666-6666-6666-6666-666666666607",
"name": "Mark Login Success [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-014",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-015",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "login-016",
"name": "statusCode",
"value": "={{ $json.status }}",
"type": "number"
},
{
"id": "login-017",
"name": "message",
"value": "Login response did not match the configured success marker",
"type": "string"
},
{
"id": "login-018",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
768,
0
],
"id": "cf666666-6666-6666-6666-666666666608",
"name": "Mark Login Failed [Schedule]"
},
{
"parameters": {
"httpMethod": "POST",
"path": "cloudflare-account-login",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-640,
432
],
"id": "cf666666-6666-6666-6666-666666666609",
"name": "Receive Login Request",
"webhookId": "cf666666-aaaa-bbbb-cccc-666666666609"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-019",
"name": "targetURL",
"value": "={{ $json.body.targetURL }}",
"type": "string"
},
{
"id": "login-020",
"name": "loginActionURL",
"value": "={{ $json.body.loginActionURL }}",
"type": "string"
},
{
"id": "login-021",
"name": "proxy",
"value": "={{ $json.body.proxy }}",
"type": "string"
},
{
"id": "login-022",
"name": "usernameField",
"value": "={{ $json.body.usernameField }}",
"type": "string"
},
{
"id": "login-023",
"name": "passwordField",
"value": "={{ $json.body.passwordField }}",
"type": "string"
},
{
"id": "login-024",
"name": "usernameValue",
"value": "={{ $json.body.usernameValue }}",
"type": "string"
},
{
"id": "login-025",
"name": "passwordValue",
"value": "={{ $json.body.passwordValue }}",
"type": "string"
},
{
"id": "login-026",
"name": "successMarker",
"value": "={{ $json.body.successMarker }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-368,
480
],
"id": "cf666666-6666-6666-6666-666666666610",
"name": "Set Login Config [Webhook]"
},
{
"parameters": {
"operation": "Cloudflare Challenge",
"websiteURL": "={{ $json.targetURL }}",
"proxy": "={{ $json.proxy }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-144,
480
],
"id": "cf666666-6666-6666-6666-666666666611",
"name": "Solve Cloudflare Challenge [Webhook]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"jsCode": "const config = $('Set Login Config [Webhook]').first().json;\nconst capResult = $input.first().json;\n\nfunction toProxyURL(proxy) {\n if (!proxy) return '';\n if (proxy.startsWith('http')) return proxy;\n const parts = proxy.split(':');\n if (parts.length === 4) {\n return `http://${parts[2]}:${parts[3]}@${parts[0]}:${parts[1]}`;\n }\n return proxy;\n}\n\nlet cookieStr = '';\nlet ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36';\n\nif (capResult.data && capResult.data.solution) {\n const solution = capResult.data.solution;\n const cookies = solution.cookies;\n cookieStr = cookies && typeof cookies === 'object'\n ? Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ')\n : (cookies || '');\n if (solution.userAgent) ua = solution.userAgent;\n}\n\nconst chromeMatch = ua.match(/Chrome\\/(\\d+)/);\nconst chromeVer = chromeMatch ? chromeMatch[1] : '145';\nconst secChUa = `\"Chromium\";v=\"${chromeVer}\", \"Not A(Brand\";v=\"8\", \"Google Chrome\";v=\"${chromeVer}\"`;\n\nconst params = new URLSearchParams();\nparams.set(config.usernameField, config.usernameValue);\nparams.set(config.passwordField, config.passwordValue);\n\nconst headers = {\n 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',\n 'accept-language': 'en-US,en;q=0.9',\n 'content-type': 'application/x-www-form-urlencoded',\n 'sec-ch-ua': secChUa,\n 'sec-ch-ua-mobile': '?0',\n 'sec-ch-ua-platform': '\"Windows\"',\n 'sec-fetch-dest': 'document',\n 'sec-fetch-mode': 'navigate',\n 'sec-fetch-site': 'same-origin',\n 'sec-fetch-user': '?1',\n 'upgrade-insecure-requests': '1',\n 'user-agent': ua\n};\n\nif (cookieStr) headers['cookie'] = cookieStr;\n\nreturn [{ json: {\n url: config.loginActionURL,\n method: 'POST',\n proxy: toProxyURL(config.proxy),\n headers,\n body: params.toString()\n}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
48,
480
],
"id": "cf666666-6666-6666-6666-666666666612",
"name": "Prepare TLS Login Request [Webhook]"
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:7878/fetch",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 60000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
256,
480
],
"id": "cf666666-6666-6666-6666-666666666613",
"name": "Submit Login via TLS Server [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "login-if-002",
"leftValue": "={{ $json.status < 400 && String($json.body || '').includes($('Set Login Config [Webhook]').item.json.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
448,
496
],
"id": "cf666666-6666-6666-6666-666666666614",
"name": "Login Successful? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-028",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-029",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "login-030",
"name": "message",
"value": "Configured account login flow succeeded (via Cloudflare Challenge bypass)",
"type": "string"
},
{
"id": "login-031",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
640,
320
],
"id": "cf666666-6666-6666-6666-666666666615",
"name": "Mark Login Success [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "login-032",
"name": "action",
"value": "account_login",
"type": "string"
},
{
"id": "login-033",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "login-034",
"name": "statusCode",
"value": "={{ $json.status }}",
"type": "number"
},
{
"id": "login-035",
"name": "message",
"value": "Login response did not match the configured success marker",
"type": "string"
},
{
"id": "login-036",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
656,
544
],
"id": "cf666666-6666-6666-6666-666666666616",
"name": "Mark Login Failed [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
880,
416
],
"id": "cf666666-6666-6666-6666-666666666617",
"name": "Return Login Result"
}
],
"connections": {
"Every 24 Hours": {
"main": [
[
{
"node": "Set Login Config [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Set Login Config [Schedule]": {
"main": [
[
{
"node": "Solve Cloudflare Challenge [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Solve Cloudflare Challenge [Schedule]": {
"main": [
[
{
"node": "Prepare TLS Login Request [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Prepare TLS Login Request [Schedule]": {
"main": [
[
{
"node": "Submit Login via TLS Server [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login via TLS Server [Schedule]": {
"main": [
[
{
"node": "Login Successful? [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Login Successful? [Schedule]": {
"main": [
[
{
"node": "Mark Login Success [Schedule]",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Login Failed [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Receive Login Request": {
"main": [
[
{
"node": "Set Login Config [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Set Login Config [Webhook]": {
"main": [
[
{
"node": "Solve Cloudflare Challenge [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve Cloudflare Challenge [Webhook]": {
"main": [
[
{
"node": "Prepare TLS Login Request [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Prepare TLS Login Request [Webhook]": {
"main": [
[
{
"node": "Submit Login via TLS Server [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login via TLS Server [Webhook]": {
"main": [
[
{
"node": "Login Successful? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Login Successful? [Webhook]": {
"main": [
[
{
"node": "Mark Login Success [Webhook]",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Login Failed [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Mark Login Success [Webhook]": {
"main": [
[
{
"node": "Return Login Result",
"type": "main",
"index": 0
}
]
]
},
"Mark Login Failed [Webhook]": {
"main": [
[
{
"node": "Return Login Result",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Este fluxo cria um endpoint POST que resolve um desafio Cloudflare Turnstile e retorna o token. É o equivalente do Turnstile à Cloudflare Challenge Solver API acima — mas mais simples: sem proxy, sem servidor TLS, apenas 3 nós.
Fluxo:
Webhook (POST /solver-turnstile) → Resolver Turnstile (CapSolver) → Responder ao Webhook
websiteURL e websiteKeyAntiTurnstileTaskProxyLesstoken)Diferença chave em relação ao Cloudflare Challenge: Turnstile retorna uma string
token, e não um cookiecf_clearance. Você envia esse token como um cabeçalhocf-turnstile-response(ou campo de formulário, dependendo do site) nas requisições subsequentes. Nenhum proxy é necessário.
curl -X POST https://your-n8n-instance.com/webhook/solver-turnstile \
-H "Content-Type: application/json" \
-d '{
"websiteURL": "https://target-site.com/page",
"websiteKey": "0x4AAAAAAA..."
}'
Copie o JSON abaixo e importe-o no n8n via Menu → Importar do JSON. Após importar, selecione sua credencial CapSolver no nó Resolver Turnstile.
{
"nodes": [
{
"parameters": {
"content": "## Turnstile \u2014 Solver API\n\n### Como funciona\n\n1. Recebe uma solicitação de solver através de um webhook.\n2. Resolve o CAPTCHA Turnstile usando um nó solver especializado.\n3. Envia a resposta de volta via resposta do webhook.\n\n### Passos de configuração\n\n- [ ] Configure a URL do webhook para receber as solicitações.\n- [ ] Configure as credenciais para o nó capSolver.\n- [ ] Garanta que a URL de resposta do webhook esteja corretamente configurada.\n\n### Customização\n\nA configuração do nó solver pode ser ajustada para lidar com diferentes tipos de CAPTCHAs Turnstile.",
"width": 480,
"height": 560
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-848,
-80
],
"id": "d52f67cb-cb00-430f-bd76-b74cf4fe6184",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Gerenciar solicitação do solver\n\nRecebe e processa uma solicitação para resolver um CAPTCHA Turnstile, depois envia o resultado de volta.",
"width": 832,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-288,
-80
],
"id": "21f62617-eaa2-41ae-8fb8-c8502f21c275",
"name": "Sticky Note1"
},
{
"parameters": {
"httpMethod": "POST",
"path": "solver-turnstile",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-240,
32
],
"id": "ts-001",
"name": "Receber Solicitação do Solver",
"webhookId": "a7ef0297-8455-44bd-9305-26c179f040b5",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.body.websiteURL }}",
"websiteKey": "={{ $json.body.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
80,
32
],
"id": "ts-002",
"name": "Resolver Turnstile",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
}
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json.data) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
400,
32
],
"id": "ts-003",
"name": "Responder ao Webhook"
}
],
"connections": {
"Receber Solicitação do Solver": {
"main": [
[
{
"node": "Resolver Turnstile",
"type": "main",
"index": 0
}
]
]
},
"Resolver Turnstile": {
"main": [
[
{
"node": "Responder ao Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Este fluxo de trabalho resolve o Cloudflare Turnstile, acessa uma página de produto com o token resolvido, extrai o preço e o nome do produto, e compara com o valor anterior — emitindo alerta em caso de mudanças. Ele segue o mesmo padrão de gatilho duplo (agendamento + webhook) como o exemplo de raspagem do Cloudflare Challenge acima.
Diferença chave em relação à raspagem do Cloudflare Challenge: Sem servidor TLS, sem proxy, sem nó de código
Prepare TLS Request. O token Turnstile é enviado como um cabeçalhocf-turnstile-responsediretamente através do nó HTTP Request integrado do n8n.
Caminho pelo agendamento:
A cada 6 horas → Definir Config. Alvo → Resolver Turnstile → Buscar Página do Produto
→ Extrair Dados → Comparar Dados → Dados Alterados? → Construir Alerta / Sem Mudança
Caminho pelo webhook:
Gatilho Webhook → Resolver Turnstile → Buscar Página do Produto
→ Extrair Dados → Comparar Dados → Dados Alterados? → Construir Alerta / Sem Mudança
→ Responder ao Webhook
Comportamentos principais:
Cloudflare Turnstile (não Cloudflare Challenge) — usa AntiTurnstileTaskProxyLess internamentecf-turnstile-response na requisição de buscacf_clearance para emparelhar impressões digitais$workflow.staticData.lastPrice para persistência entre execuçõeswebsiteURL e websiteKey diretamente do corpo POST (não é necessário nó Set Target Config){
"nodes": [
{
"parameters": {
"content": "## Raspagem Turnstile — Monitor de Preço e Produto\n\n### Como funciona\n\n1. O fluxo é acionado a cada 6 horas ou via webhook.\n2. Configuração do alvo é definida, incluindo o URL do site e a chave.\n3. O captcha Turnstile é resolvido para acessar a página do produto.\n4. Dados do produto são buscados e dados relevantes são extraídos.\n5. Os dados extraídos são comparados aos dados anteriores para identificar mudanças.\n6. Alertas são gerados se houver mudanças, e uma resposta é enviada para requisições via webhook.\n\n### Etapas de configuração\n\n- [ ] Configurar intervalo do gatilho agendado conforme necessário.\n- [ ] Configurar URL do webhook para acionamento em tempo real.\n- [ ] Garantir que as credenciais do resolvedor de captcha estejam válidas.\n- [ ] Configurar URL do site alvo e chave do produto.\n\n### Personalização\n\nO intervalo do gatilho agendado pode ser ajustado com base nas necessidades de monitoramento.",
"width": 480,
"height": 896
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1184,
-240
],
"id": "1824aba9-471e-4052-912e-888d939349df",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Gatilho de raspagem agendada\n\nInicia o fluxo a cada 6 horas e define configurações do alvo.",
"width": 512,
"height": 304,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-624,
-80
],
"id": "89b7d6a2-b4bf-4a7d-8667-ce3f31d2eb92",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Captcha e busca agendada\n\nResolve o captcha e busca os dados da página do produto com base no agendamento.",
"width": 1472,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
16,
-64
],
"id": "f39fc94b-d0ae-4141-9491-fa82702a72fc",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "## Avaliação dos dados agendada\n\nCompara os dados recém-buscados com os anteriores para detectar mudanças e constrói alertas.",
"width": 240,
"height": 528,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1536,
-240
],
"id": "0d31be95-f94c-40fd-99cd-7d988109d3f4",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## Gatilho de raspagem por webhook\n\nAciona o fluxo de raspagem via webhook para atualizações em tempo real.",
"width": 240,
"height": 352,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-624,
256
],
"id": "e4a50f47-180c-484e-bf70-09a46543e01b",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "## Captcha e busca via webhook\n\nResolve o captcha e busca os dados da página do produto para o gatilho do webhook.",
"width": 1472,
"height": 272,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
16,
336
],
"id": "1167cf0e-d561-40fa-b366-331a20d99a31",
"name": "Sticky Note5"
},
{
"parameters": {
"content": "## Avaliação dos dados e resposta via webhook\n\nAvalia mudanças nos dados e responde ao webhook com os resultados.",
"width": 672,
"height": 432,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1536,
320
],
"id": "0dab95b9-d762-43cf-9a11-b92212a8c2a7",
"name": "Sticky Note6"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-576,
48
],
"id": "ts-s-01",
"name": "A cada 6 Horas"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-001",
"name": "websiteURL",
"value": "https://YOUR-TARGET-SITE.com/product-page",
"type": "string"
},
{
"id": "cfg-002",
"name": "websiteKey",
"value": "YOUR_SITE_KEY_HERE",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-256,
48
],
"id": "ts-s-02",
"name": "Definir Config. Alvo [Agendamento]"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.websiteURL }}",
"websiteKey": "={{ $json.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
64,
48
],
"id": "ts-s-03",
"name": "Resolver Turnstile",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
}
},
{
"parameters": {
"url": "={{ $('Set Target Config [Schedule]').first().json.websiteURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
384,
48
],
"id": "ts-s-04",
"name": "Buscar Página do Produto"
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price"
},
{
"key": "productName",
"cssSelector": "h1, .product-title"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
704,
48
],
"id": "ts-s-05",
"name": "Extrair Dados"
},
{
"parameters": {
"jsCode": "const staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Produto';\nconst parsePrice = (str) => { if (!str) return null; const match = str.match(/[\\d]+\\.?\\d*/); return match ? parseFloat(match[0].replace(',', '')) : null; };\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'diminuiu' : 'aumentou') : 'inalterado';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\nreturn [{ json: { productName, currentPrice, previousPrice: previousPrice || 'verificação inicial', changed, direction, diff: changed ? `$${diff}` : null, checkedAt: new Date().toISOString() } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1072,
48
],
"id": "ts-s-06",
"name": "Comparar Dados"
},
{
"parameters": {
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"id": "if-1",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1344,
48
],
"id": "ts-s-07",
"name": "Dados Alterados?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "a1",
"name": "alert",
"value": "=Preço {{ $json.direction }} para {{ $json.productName }}: {{ $json.previousPrice }} \u2192 {{ $json.currentPrice }}",
"type": "string"
},
{
"id": "a2",
"name": "severity",
"value": "={{ $json.direction === 'diminuiu' ? 'oferta' : 'info' }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1584,
-48
],
"id": "ts-s-08",
"name": "Construir Alerta"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "n1",
"name": "status",
"value": "sem_mudança",
"type": "string"
},
{
"id": "n2",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1584,
128
],
"id": "ts-s-09",
"name": "Sem Mudança"
},
{
"parameters": {
"httpMethod": "POST",
"path": "price-monitor-turnstile",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-576,
448
],
"id": "ts-s-10",
"name": "Gatilho Webhook",
"webhookId": "6a4f76c7-fc5c-440d-96cb-75c9c3bebcdb",
"onError": "continueRegularOutput"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.body.websiteURL }}",
"websiteKey": "={{ $json.body.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
64,
448
],
"id": "ts-s-11",
"name": "Resolver Turnstile [W]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Conta CapSolver"
}
}
},
{
"parameters": {
"url": "={{ $('Webhook Trigger').item.json.body.websiteURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
384,
448
],
"id": "ts-s-12",
"name": "Buscar Página do Produto [W]"
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".product-price, [data-price], .price"
},
{
"key": "productName",
"cssSelector": "h1, .product-title"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
704,
448
],
"id": "ts-s-13",
"name": "Extrair Dados [W]"
},
{
"parameters": {
"jsCode": "const staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || 'Produto';\nconst parsePrice = (str) => { if (!str) return null; const match = str.match(/[\\d]+\\.?\\d*/); return match ? parseFloat(match[0].replace(',', '')) : null; };\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? 'diminuiu' : 'aumentou') : 'inalterado';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : '0';\nreturn [{ json: { productName, currentPrice, previousPrice: previousPrice || 'verificação inicial', changed, direction, diff: changed ? `$${diff}` : null, checkedAt: new Date().toISOString() } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1040,
448
],
"id": "ts-s-14",
"name": "Comparar Dados [W]"
},
{
"parameters": {
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"id": "if-2",
"leftValue": "={{ $json.changed }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1344,
448
],
"id": "ts-s-15",
"name": "Dados Alterados? [W]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "a4",
"name": "alert",
"value": "=Preço {{ $json.direction }} para {{ $json.productName }}: {{ $json.previousPrice }} \u2192 {{ $json.currentPrice }}",
"type": "string"
},
{
"id": "a5",
"name": "severity",
"value": "={{ $json.direction === 'diminuiu' ? 'oferta' : 'info' }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1584,
432
],
"id": "ts-s-16",
"name": "Construir Alerta [W]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "n4",
"name": "status",
"value": "sem_mudança",
"type": "string"
},
{
"id": "n5",
"name": "currentPrice",
"value": "={{ $json.currentPrice }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1584,
592
],
"id": "ts-s-17",
"name": "Sem Mudança [W]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
2064,
544
],
"id": "ts-s-18",
"name": "Responder ao Webhook"
}
],
"connections": {
"Every 6 Hours": {
"main": [
[
{
"node": "Set Target Config [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Set Target Config [Schedule]": {
"main": [
[
{
"node": "Solve Turnstile",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile": {
"main": [
[
{
"node": "Fetch Product Page",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page": {
"main": [
[
{
"node": "Extract Data",
"type": "main",
"index": 0
}
]
]
},
"Extract Data": {
"main": [
[
{
"node": "Compare Data",
"type": "main",
"index": 0
}
]
]
},
"Compare Data": {
"main": [
[
{
"node": "Data Changed?",
"type": "main",
"index": 0
}
]
]
},
"Data Changed?": {
"main": [
[
{
"node": "Build Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Solve Turnstile [W]",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile [W]": {
"main": [
[
{
"node": "Fetch Product Page [W]",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Page [W]": {
"main": [
[
{
"node": "Extract Data [W]",
"type": "main",
"index": 0
}
]
]
},
"Extract Data [W]": {
"main": [
[
{
"node": "Compare Data [W]",
"type": "main",
"index": 0
}
]
]
},
"Compare Data [W]": {
"main": [
[
{
"node": "Data Changed? [W]",
"type": "main",
"index": 0
}
]
]
},
"Data Changed? [W]": {
"main": [
[
{
"node": "Build Alert [W]",
"type": "main",
"index": 0
}
],
[
{
"node": "No Change [W]",
"type": "main",
"index": 0
}
]
]
},
"Build Alert [W]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"No Change [W]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Este fluxo de trabalho automatiza o login em um site protegido pelo Turnstile. Ele segue o mesmo padrão de gatilho duplo (agenda + webhook) como o Login de Conta Cloudflare Challenge acima — mas sem o servidor TLS, proxy ou nó de código personalizado.
Diferença chave em relação ao login Cloudflare Challenge: Sem servidor TLS, sem proxy, sem nó de código
Prepare TLS Login Request. O token Turnstile é enviado como um campo de formuláriocf-turnstile-responsediretamente pelo nó HTTP Request integrado do n8n. As credenciais são enviadas como parâmetros padrão no corpoform-urlencoded.
Caminho da agenda:
A cada 24 horas → Definir Configuração de Login → Resolver Turnstile → Submeter Login
→ Login OK? → Marcar Sucesso / Marcar Falha
Caminho do webhook:
Gatilho Webhook → Resolver Turnstile → Submeter Login
→ Login OK? → Marcar Sucesso / Marcar Falha → Responder ao Webhook
Comportamentos principais:
Cloudflare Turnstile (não Cloudflare Challenge) — usa AntiTurnstileTaskProxyLess, não requer proxycf-turnstile-response no corpo POST (não como cookie header como no CF Challenge)email, password e cf-turnstile-responsestatusCode < 400 E successMarker no corpo da resposta — mesmo padrão do login CF ChallengeusernameValue, passwordValue, usernameField, passwordField, loginActionURL, successMarker do corpo POSTname de cada campo de formulário é uma expressão ($('Webhook Trigger').item.json.body.usernameField || 'email'), para que os chamadores possam especificar os nomes dos campos do site deles{
"nodes": [
{
"parameters": {
"content": "## Turnstile Account Login\n\n### How it works\n\n1. Triggers a login process every 24 hours using a schedule.\n2. Sets up the login configuration and solves Turnstile challenges.\n3. Submits the login form and checks if the login was successful.\n4. Marks the login attempt as success or failure in the schedule flow.\n5. Alternatively, starts a login process via a webhook trigger and executes similar steps for webhook-based logins.\n\n### Setup steps\n\n- [ ] Schedule a periodic execution by setting up a scheduler.\n- [ ] Configure webhook endpoint for external triggers.\n- [ ] Set login credentials and URL configurations.\n\n### Customization\n\nAdjust timing in the scheduler or modify webhook response handling as needed.",
"width": 480,
"height": 896
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1168,
-160
],
"id": "8ca80c21-2de5-41e7-b3e4-de184fc1d8fe",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Scheduled login flow\n\nTriggers every 24 hours to perform login steps",
"width": 1920,
"height": 448,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-608,
-160
],
"id": "533be07a-6fe7-4ada-a40c-7a7749ba968d",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Webhook login flow\n\nHandles login requests triggered by a webhook",
"width": 2288,
"height": 416,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-608,
320
],
"id": "c6a8e296-2bfb-4ffa-8819-aa420e936589",
"name": "Sticky Note2"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-560,
48
],
"id": "ts-l-01",
"name": "Every 24 Hours"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "l1",
"name": "websiteURL",
"value": "https://YOUR-LOGIN-PAGE.com",
"type": "string"
},
{
"id": "l2",
"name": "websiteKey",
"value": "YOUR_SITE_KEY_HERE",
"type": "string"
},
{
"id": "l3",
"name": "successMarker",
"value": "account-dashboard",
"type": "string"
},
{
"id": "l4",
"name": "userAgent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-240,
48
],
"id": "ts-l-02",
"name": "Set Login Config [Schedule]"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.websiteURL }}",
"websiteKey": "={{ $json.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
256,
48
],
"id": "ts-l-03",
"name": "Solve Turnstile [Schedule]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Login Config [Schedule]').item.json.websiteURL }}/login",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "user-agent",
"value": "={{ $('Set Login Config [Schedule]').item.json.userAgent }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "email",
"value": "your-email@example.com"
},
{
"name": "password",
"value": "YOUR_ACCOUNT_PASSWORD"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
576,
48
],
"id": "ts-l-04",
"name": "Submit Login [Schedule]"
},
{
"parameters": {
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"conditions": [
{
"id": "lif1",
"leftValue": "={{ $json.statusCode < 400 && String($json.body || $json.data || '').includes($('Set Login Config [Schedule]').item.json.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
896,
48
],
"id": "ts-l-05",
"name": "Login OK? [Schedule]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "s1",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "s2",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1168,
-48
],
"id": "ts-l-06",
"name": "Mark Success"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "f1",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "f2",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
},
{
"id": "f3",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1168,
128
],
"id": "ts-l-07",
"name": "Mark Failed"
},
{
"parameters": {
"httpMethod": "POST",
"path": "account-login-turnstile",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-560,
544
],
"id": "ts-l-08",
"name": "Webhook Trigger",
"webhookId": "9c7a53a4-d3ee-495b-9381-3a9425bb1b36"
},
{
"parameters": {
"operation": "Cloudflare Turnstile",
"websiteURL": "={{ $json.body.websiteURL }}",
"websiteKey": "={{ $json.body.websiteKey }}",
"optional": {}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
256,
544
],
"id": "ts-l-09",
"name": "Solve Turnstile [Webhook]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "CapSolver account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Webhook Trigger').item.json.body.loginActionURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "content-type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "user-agent",
"value": "={{ $('Webhook Trigger').item.json.body.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' }}"
}
]
},
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {
"parameters": [
{
"name": "={{ $('Webhook Trigger').item.json.body.usernameField || 'email' }}",
"value": "={{ $('Webhook Trigger').item.json.body.usernameValue }}"
},
{
"name": "={{ $('Webhook Trigger').item.json.body.passwordField || 'password' }}",
"value": "={{ $('Webhook Trigger').item.json.body.passwordValue }}"
},
{
"name": "cf-turnstile-response",
"value": "={{ $json.data.solution.token }}"
}
]
},
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
576,
544
],
"id": "ts-l-10",
"name": "Submit Login [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"conditions": [
{
"id": "lif2",
"leftValue": "={{ $json.statusCode < 400 && String($json.body || $json.data || '').includes($('Webhook Trigger').item.json.body.successMarker) }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
896,
544
],
"id": "ts-l-11",
"name": "Login OK? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "ws1",
"name": "status",
"value": "success",
"type": "string"
},
{
"id": "ws2",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1168,
432
],
"id": "ts-l-12",
"name": "Mark Success [W]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "wf1",
"name": "status",
"value": "failed",
"type": "string"
},
{
"id": "wf2",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
},
{
"id": "wf3",
"name": "checkedAt",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1168,
576
],
"id": "ts-l-13",
"name": "Mark Failed [W]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1536,
544
],
"id": "ts-l-14",
"name": "Respond to Webhook"
}
],
"connections": {
"Every 24 Hours": {
"main": [
[
{
"node": "Set Login Config [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Set Login Config [Schedule]": {
"main": [
[
{
"node": "Solve Turnstile [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile [Schedule]": {
"main": [
[
{
"node": "Submit Login [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login [Schedule]": {
"main": [
[
{
"node": "Login OK? [Schedule]",
"type": "main",
"index": 0
}
]
]
},
"Login OK? [Schedule]": {
"main": [
[
{
"node": "Mark Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Failed",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Solve Turnstile [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Solve Turnstile [Webhook]": {
"main": [
[
{
"node": "Submit Login [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Submit Login [Webhook]": {
"main": [
[
{
"node": "Login OK? [Webhook]",
"type": "main",
"index": 0
}
]
]
},
"Login OK? [Webhook]": {
"main": [
[
{
"node": "Mark Success [W]",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Failed [W]",
"type": "main",
"index": 0
}
]
]
},
"Mark Success [W]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Mark Failed [W]": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
Você construiu uma pipeline completa para contornar o Cloudflare Challenge no n8n — sem automação de navegador, sem Puppeteer, sem Playwright. Apenas três componentes trabalhando juntos: CapSolver para resolver o desafio, um servidor TLS em Go para falsificar a impressão digital de rede do Chrome, e um fluxo de trabalho n8n para orquestrar tudo.
A chave é que resolver o desafio é apenas metade do problema. Sem corresponder as impressões digitais TLS na busca subsequente, o cf_clearance é inútil — o Cloudflare inspeciona o handshake, não só o cookie. O servidor TLS httpcloak lida com essa camada, fazendo com que a busca seja indistinguível de um navegador Chrome real em nível de rede.
O repositório agora oferece templates reais para sites protegidos pelo Cloudflare:
cf_clearance bruto + userAgent para aplicações externasA Solver API é o ponto de entrada mais simples — 4 nós, sem necessidade de servidor TLS. Os fluxos Turnstile são ainda mais simples — não há necessidade de proxy ou servidor TLS, pois o Turnstile retorna um token (não um cookie vinculado a IP) e não faz fingerprint TLS. Para fluxos Cloudflare Challenge que buscam páginas diretamente, o CapSolver resolve o desafio e o servidor TLS faz a requisição real. Configure os placeholders, mantenha os fluxos inativos até que estejam adaptados ao seu alvo, e então ative.
Dica: Esses fluxos usam triggers Schedule + Webhook, mas você pode trocar o nó trigger para qualquer gatilho do n8n — manual, evento de app, submissão de formulário, etc. Depois de buscar os dados, use os nós internos do n8n para salvar resultados no Google Sheets, bancos de dados, armazenamento em nuvem, ou enviar alertas via Telegram/Slack/Email.
Pronto para começar? Cadastre-se no CapSolver e use o código bônus n8n para um bônus extra de 8% no seu primeiro recarregamento!

AntiCloudflareTask resolve o desafio completo de Bot Management do Cloudflare — a tela "Just a moment…" que bloqueia totalmente o acesso ao site. Ele requer um proxy porque o CapSolver precisa carregar a página protegida real através de um navegador. AntiTurnstileTaskProxyLess resolve widgets Turnstile embutidos em páginas (formulários de login, cadastro) e não requer proxy. Desafios diferentes, tipos de tarefas diferentes.
O nó HTTP Request do n8n usa a biblioteca padrão Go net/http, que tem uma impressão digital TLS distinta que o Cloudflare detecta. Mesmo com um cookie cf_clearance válido, o Cloudflare vai desafiar novamente qualquer requisição que não combine com um perfil TLS conhecido de navegador. O servidor TLS resolve isso usando o httpcloak para falsificar a pilha TLS de um Chrome real.
A pontuação de bots do Cloudflare atribui scores de risco a endereços IP. IPs de datacenter (AWS, GCP, provedores VPS etc.) são bem conhecidos e recebem scores altos de risco. O AntiCloudflareTask usa seu proxy para carregar a página do desafio, e se o Cloudflare detecta que o IP é de datacenter, ele serve um desafio mais difícil que o CapSolver não consegue resolver, ou falha completamente. IPs residenciais e móveis têm scores de risco mais baixos e passam com mais confiabilidade.
Não. Turnstile é fundamentalmente diferente do Cloudflare Challenge. Turnstile retorna um token de curta duração que você envia como header ou campo de formulário — não está vinculado a um IP ou impressão digital TLS. O CapSolver resolve Turnstile usando AntiTurnstileTaskProxyLess, que não requer proxy. E como você envia um token (não um cookie vinculado a IP), o nó HTTP Request embutido do n8n funciona bem — não é necessário falsificação da impressão digital TLS.
cf_clearance expira?Sim. O prazo depende da configuração do Cloudflare do site — pode variar de alguns minutos até 24 horas. Para trabalhos recorrentes de scraping, o fluxo agendado (a cada 6 horas) resolve o desafio regularmente. Para scraping sob demanda, o caminho webhook resolve um novo desafio a cada requisição.
Aprenda arquitetura de raspagem web escalável em Rust com reqwest, scraper, raspagem assíncrona, raspagem de navegador headless, rotação de proxies e tratamento de CAPTCHA compatível.

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.

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.

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.
