Três decisões resolvem quase todo problema de SOCKS5 com a CaptchaAI: usar socks5h:// em vez de socks5://, para que o DNS seja resolvido no servidor do proxy; autenticar o navegador por biblioteca, não pela linha de comando; e enviar o proxy junto com a tarefa (proxytype=SOCKS5) só quando o formulário avaliar o IP de origem. O resto é encanamento — mostrado aqui em Python, Node.js, Selenium e Puppeteer.
O cenário típico: um time de QA valida um formulário na janela de manutenção, o egress de rede é autorizado e fixo, e a página exibe reCAPTCHA v2. Sem SOCKS5, o teste morre na camada de rede; com SOCKS5 mal configurado, morre por vazamento de DNS — e ninguém entende por que o mesmo script passa na máquina do dev e falha no runner.
SOCKS5 ou proxy HTTP: quando cada um faz sentido
O SOCKS5 encaminha qualquer tráfego TCP/UDP sem reescrever a requisição, evitando os cabeçalhos que um proxy HTTP acrescenta. A escolha depende de duas perguntas: você precisa de WebSocket, e onde o DNS deve ser resolvido?
| Característica | Proxy HTTP/HTTPS | Proxy SOCKS5 |
|---|---|---|
| Suporte de protocolo | Somente HTTP/HTTPS | Qualquer TCP/UDP |
| Modificação de cabeçalho | Pode adicionar X-Forwarded-For |
Sem modificação |
| Detecção | Mais fácil (vazamento de cabeçalhos) | Mais difícil |
| Velocidade | Rápido | Um pouco mais lento |
| Autenticação | Basic/Digest | Usuário e senha |
| Resolução DNS | No cliente | No servidor (SOCKS5h) |
| Suporte WebSocket | Limitado | Completo |
A diferença de latência é pequena: a análise HTTP que o SOCKS5 economiza custa menos que o RTT até o host. Com workers em sa-east-1 e proxy na Europa, a distância pesa muito mais que o protocolo.
Configuração em Python
requests + PySocks
Instale o extra socks do requests, que traz o PySocks:
pip install requests[socks] pysocks
O bloco a seguir faz o ciclo completo: busca a página pelo proxy, extrai a sitekey (chave pública do widget), envia a tarefa e consulta até o token chegar.
import requests
import time
SOCKS5_HOST = "proxy.example.com"
SOCKS5_PORT = 1080
SOCKS5_USER = "proxyuser"
SOCKS5_PASS = "proxypass"
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
# SOCKS5 proxy configuration
proxies = {
"http": f"socks5h://{SOCKS5_USER}:{SOCKS5_PASS}@{SOCKS5_HOST}:{SOCKS5_PORT}",
"https": f"socks5h://{SOCKS5_USER}:{SOCKS5_PASS}@{SOCKS5_HOST}:{SOCKS5_PORT}",
}
# socks5h = DNS resolved by proxy server (recommended)
# socks5 = DNS resolved locally
def fetch_through_socks(url):
"""Fetch URL through SOCKS5 proxy."""
return requests.get(
url,
proxies=proxies,
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36"
},
timeout=30,
)
def solve_captcha(site_url, sitekey):
"""Solve CAPTCHA via CaptchaAI (direct, no proxy needed)."""
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": site_url,
"json": 1,
})
data = resp.json()
if data["status"] != 1:
raise Exception(f"Submit: {data['request']}")
task_id = data["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
data = resp.json()
if data["request"] == "CAPCHA_NOT_READY":
continue
if data["status"] == 1:
return data["request"]
raise Exception(f"Solve: {data['request']}")
raise TimeoutError("Timeout")
# Full workflow
resp = fetch_through_socks("https://staging.example.com/qa-form")
import re
match = re.search(r'data-sitekey="([^"]+)"', resp.text)
if match:
token = solve_captcha("https://staging.example.com/qa-form", match.group(1))
# Submit with token through same proxy
resp = requests.post(
"https://target.com/submit",
data={"g-recaptcha-response": token},
proxies=proxies,
)
Dois detalhes merecem atenção. O socks5h:// do dicionário proxies garante que o domínio seja resolvido pelo servidor do proxy; socks5:// faz o DNS sair pela rede local e é a causa mais comum de divergência entre ambientes. E as chamadas a in.php e res.php seguem pela rota direta: a API não precisa do seu egress. O polling usa intervalo de 5 s com teto de 60 iterações, para que um worker preso não segure a thread.
aiohttp para cargas assíncronas
Se o pipeline já é assíncrono, o aiohttp_socks fornece um connector pronto e evita bloqueio no loop de eventos:
import aiohttp
import aiohttp_socks
import asyncio
async def fetch_async(url):
connector = aiohttp_socks.ProxyConnector.from_url(
f"socks5://{SOCKS5_USER}:{SOCKS5_PASS}@{SOCKS5_HOST}:{SOCKS5_PORT}"
)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get(url) as resp:
return await resp.text()
asyncio.run(fetch_async("https://staging.example.com/qa-form"))
Selenium + SOCKS5
O Chrome aceita --proxy-server=socks5://host:porta, mas não aceita credenciais nessa string. Para SOCKS5 autenticado, use o Selenium Wire, que sobe um proxy local e cuida da autenticação. A função abaixo cobre os dois casos:
from selenium import webdriver
from selenium.webdriver.common.by import By
def create_socks5_driver(host, port, username=None, password=None):
options = webdriver.ChromeOptions()
# SOCKS5 proxy (no auth via command line)
options.add_argument(f"--proxy-server=socks5://{host}:{port}")
# DNS through proxy
options.add_argument("--host-resolver-rules=MAP * ~NOTFOUND, EXCLUDE 127.0.0.1")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=options)
return driver
# For authenticated SOCKS5, use seleniumwire
from seleniumwire import webdriver as sw_webdriver
def create_auth_socks5_driver():
options = {
"proxy": {
"http": f"socks5h://{SOCKS5_USER}:{SOCKS5_PASS}@{SOCKS5_HOST}:{SOCKS5_PORT}",
"https": f"socks5h://{SOCKS5_USER}:{SOCKS5_PASS}@{SOCKS5_HOST}:{SOCKS5_PORT}",
}
}
chrome_options = sw_webdriver.ChromeOptions()
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
return sw_webdriver.Chrome(
seleniumwire_options=options,
options=chrome_options,
)
# Usage
driver = create_auth_socks5_driver()
driver.get("https://staging.example.com/qa-form")
time.sleep(3)
sitekey = driver.execute_script(
"return document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')"
)
if sitekey:
token = solve_captcha("https://staging.example.com/qa-form", sitekey)
driver.execute_script(f"""
document.querySelector('#g-recaptcha-response').value = '{token}';
""")
driver.find_element(By.CSS_SELECTOR, "form").submit()
driver.quit()
Com o driver de pé, o fluxo repete o do exemplo em requests: leia a sitekey, envie à CaptchaAI, escreva o token em #g-recaptcha-response e faça o submit. Se o widget usa callback, escrever o token não basta — é preciso disparar a função de callback registrada pelo widget.
Node.js + SOCKS5
No Node, o socks-proxy-agent cria um agent que serve para httpAgent e httpsAgent no Axios. A URL aceita usuário e senha embutidos, o que simplifica em relação ao Chrome:
const { SocksProxyAgent } = require("socks-proxy-agent");
const axios = require("axios");
const CAPTCHAAI_KEY = "YOUR_API_KEY";
const socksAgent = new SocksProxyAgent(
"socks5h://proxyuser:[email protected]:1080"
);
async function fetchViaSocks(url) {
return axios.get(url, {
httpsAgent: socksAgent,
httpAgent: socksAgent,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0",
},
});
}
async function solveCaptcha(siteUrl, sitekey) {
// CaptchaAI calls don't go through SOCKS proxy
const submit = await axios.post(
"https://ocr.captchaai.com/in.php",
null,
{
params: {
key: CAPTCHAAI_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: siteUrl,
json: 1,
},
}
);
const taskId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: CAPTCHAAI_KEY, action: "get", id: taskId, json: 1 },
});
if (result.data.request === "CAPCHA_NOT_READY") continue;
if (result.data.status === 1) return result.data.request;
}
throw new Error("Timeout");
}
Como no Python, solveCaptcha não usa o agent: as requisições à CaptchaAI seguem pela rota padrão.
Puppeteer + SOCKS5
O Puppeteer herda a limitação do Chrome — --proxy-server não carrega credenciais —, mas page.authenticate() resolve isso no nível da página:
const puppeteer = require("puppeteer");
async function launchWithSocks5() {
const browser = await puppeteer.launch({
args: [
"--proxy-server=socks5://proxy.example.com:1080",
"--no-sandbox",
"--window-size=1920,1080",
],
});
const page = await browser.newPage();
// Authenticate if needed
await page.authenticate({
username: "proxyuser",
password: "proxypass",
});
await page.goto("https://staging.example.com/qa-form", { waitUntil: "networkidle0" });
const sitekey = await page.evaluate(() =>
document.querySelector("[data-sitekey]")?.getAttribute("data-sitekey")
);
if (sitekey) {
const token = await solveCaptcha(page.url(), sitekey);
await page.evaluate((t) => {
document.querySelector("#g-recaptcha-response").value = t;
}, token);
}
await browser.close();
}
Enviando o proxy SOCKS5 na tarefa da CaptchaAI
Alguns formulários avaliam o IP que originou a resolução. Nesses casos, envie o proxy com a tarefa: a CaptchaAI resolve a partir do seu endereço, não do dela. O formato é tipo:host:porta:usuário:senha, com proxytype=SOCKS5:
def solve_with_proxy(site_url, sitekey, proxy_url):
"""Pass proxy to CaptchaAI for IP-matched solving."""
# Format: type:host:port:user:pass
proxy_param = f"socks5:{SOCKS5_HOST}:{SOCKS5_PORT}:{SOCKS5_USER}:{SOCKS5_PASS}"
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": site_url,
"proxy": proxy_param,
"proxytype": "SOCKS5",
"json": 1,
})
data = resp.json()
if data["status"] != 1:
raise Exception(f"Submit: {data['request']}")
task_id = data["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Timeout")
Use esse modo só quando necessário: um proxy lento no caminho aumenta o tempo de resolução e gera mais retentativas.
Sobre threads: os planos são cobrados por thread concorrente, com resoluções ilimitadas no mês. Uma suíte noturna de QA costuma caber em BASIC (US$ 15/mês, 5 threads); pipelines de CI com várias branches em paralelo pedem STANDARD (US$ 30/mês, 15 threads) ou ADVANCE (US$ 90/mês, 50 threads). O que ocupa thread é a tarefa em voo, não a conexão de rede.
Diagnóstico: os erros que aparecem de verdade
| Problema | Causa | Correção |
|---|---|---|
| Conexão recusada | Porta ou host errado | Verifique se o servidor SOCKS5 está em execução |
| Vazamento de DNS | Uso de socks5:// em vez de socks5h:// |
Use socks5h:// para DNS remoto |
| Falha na autenticação | Credenciais erradas | Teste isoladamente com curl --socks5 |
| Conexões lentas | Servidor de proxy distante | Escolha um proxy geograficamente mais próximo |
| WebSocket falha | O servidor SOCKS5 não suporta UDP | Use um servidor SOCKS5 com suporte a UDP |
Antes de culpar o CAPTCHA, isole a camada: rode curl --socks5-hostname contra a URL de staging e veja se o HTML volta inteiro. Se chega mas o token é recusado no envio, o problema está na integração e não na rede.
Sobre escopo: mantenha os testes em ambiente próprio ou staging, com dados fictícios, e considere as obrigações da LGPD (RGPD, em Portugal) quando houver dado pessoal nos logs de requisição.
Perguntas frequentes
Qual a diferença prática entre socks5:// e socks5h://?
O h indica que o domínio é resolvido pelo servidor do proxy. Com socks5://, sua máquina resolve o DNS localmente e envia só o IP pelo túnel. Em automação, use sempre socks5h://.
Preciso mandar as chamadas da CaptchaAI pelo proxy também?
Não. O in.php e o res.php funcionam pela rota direta; passá-los pelo proxy só acrescenta latência. O parâmetro proxy no envio é outra coisa: ele diz de qual IP a CaptchaAI deve resolver.
Um proxy SOCKS5 melhora a taxa de resolução?
Não por si só. Ele define de onde a requisição sai; a resolução depende do tipo de CAPTCHA e da qualidade do envio. Um proxy ruim só soma timeout e retentativa. Meça no seu ambiente.
O hCaptcha funciona se eu passar um proxy SOCKS5?
Não. O hCaptcha não é suportado, com ou sem proxy — o mesmo vale para o FunCaptcha e para o GeeTest v4, que consta apenas como em breve. Os tipos cobertos incluem reCAPTCHA v2 e v3, Cloudflare Turnstile e Challenge, GeeTest v3, imagem/OCR e grade, além de CaptchaFox (beta), Friendly Captcha (beta) e Lemin (beta).
Quantas threads a minha suíte precisa se ela usa SOCKS5?
Conte os desafios simultâneos, não os proxies. Se a suíte dispara no máximo cinco formulários ao mesmo tempo, BASIC (US$ 15/mês, 5 threads) atende.
Guias relacionados
- Métodos de autenticação em proxy
- Rotação de proxies na resolução de CAPTCHA
- Como a qualidade do proxy afeta a taxa de resolução
Configure o SOCKS5 uma vez e tire o CAPTCHA do caminho da sua suíte — obtenha sua chave de API.