Neste artigo, procuramos responder a todas as principais dúvidas. Para começar a resolver o problema, o primeiro passo é identificar qual sistema de proteção está sendo utilizado. Para isso, você pode consultar a lista de captchas e sistemas de proteção antibot mais populares, onde há exemplos visuais e sinais principais que ajudam a identificar rapidamente com o que você está lidando.
Se você notar que o seu site utiliza TenDI (Tencent), o passo seguinte é estudar com mais detalhes as suas características e o seu funcionamento. Neste mesmo artigo, você também pode conferir o guia de integração do TenDI (Tencent), para entender por completo como o sistema opera no seu site. Isso permitirá não apenas compreender a proteção atual, mas também planejar adequadamente a sua manutenção.
Trabalhar com o CapMonster Cloud via API normalmente envolve as etapas abaixo:
type - CustomTask
class - TenDI
websiteURL - Endereço da página onde o captcha será resolvido.
websiteKey - captchaAppId. Exemplo: "websiteKey": "189123456" — parâmetro único para seu site
captchaUrl (dentro do metadata) - Link para o script do captcha. Normalmente termina em TCaptcha.js ou TCaptcha-global.js;
websiteURL - Endereço da página onde o captcha será resolvido;
userAgent (opcional) - User-Agent do navegador. Envie apenas o UA atual do Windows.
https://api.capmonster.cloud/createTask
{
"clientKey": "API_KEY",
"task": {
"type": "CustomTask",
"class": "TenDI",
"websiteURL": "https://example.com",
"websiteKey": "189123456",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
"metadata": {
"captchaUrl": "https://global.captcha.example.com/TCaptcha-global.js"
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"errorId":0,
"status":"ready",
"solution": {
"data": {
"randstr": "@EcL",
"ticket": "tr03lHUhdnuW3neJZu.....7LrIbs*"
},
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
}
}
}
// npx playwright install chromium
import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, TenDIRequest } from '@zennolab_com/capmonstercloud-client';
// Substitua pelos seus valores
const API_KEY = "YOUR_API_KEY";
const WEBSITE_URL = "https://example.com";
async function solveTenDIOnPage() {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// 1. Abrimos a página
await page.goto(WEBSITE_URL, { waitUntil: 'networkidle' });
// 2. Esperamos o captcha aparecer (ex.: input ou iframe)
await page.waitForSelector('#tendi_response, iframe[src*="tendi"], input[name="tendi_response"]', { timeout: 15000 });
// Se necessário, pode extrair o websiteKey da página
const WEBSITE_KEY = await page.evaluate(() => {
// Exemplo: sitekey pode estar em um atributo data ou em uma variável global
const el = document.querySelector('#tendi_response') || document.querySelector('div[data-sitekey]');
return el?.getAttribute('data-sitekey') || window.TenDI_siteKey || "183268248";
});
console.log("Website key detected:", WEBSITE_KEY);
const client = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// 3. Criamos a tarefa TenDI
const tenDIRequest = new TenDIRequest({
websiteURL: page.url(),
websiteKey: WEBSITE_KEY,
});
const balance = await client.getBalance();
console.log("Balance:", balance);
// 4. Resolvemos o captcha
const solution = await client.Solve(tenDIRequest);
console.log("Solution:", solution);
const { ticket, randstr } = solution.solution.data;
// 5. Formas de inserir o resultado
await page.evaluate(({ ticket, randstr }) => {
// Inserção no input
const inputSelectors = ['#tendi_response', 'input[name="tendi_response"]', 'input[type="hidden"]'];
let inserted = false;
for (const sel of inputSelectors) {
const input = document.querySelector(sel);
if (input) {
input.value = ticket;
input.dispatchEvent(new Event('input', { bubbles: true }));
const form = input.closest('form');
if (form) form.submit();
inserted = true;
break;
}
}
// Função callback JS
if (typeof window.onCaptchaSolved === 'function') {
window.onCaptchaSolved(ticket, randstr);
inserted = true;
}
// Se não houver input nem callback
if (!inserted) {
window._tenDITicket = ticket;
window._tenDIRandStr = randstr;
console.log("Ticket and randstr saved to window._tenDITicket and window._tenDIRandStr");
}
}, { ticket, randstr });
await page.waitForTimeout(5000);
await browser.close();
}
solveTenDIOnPage().catch(console.error);
Você receberá dois parâmetros: CaptchaAppId e AppSecretKey. Eles serão usados no frontend e no servidor.
Ao clicar, o captcha aparece e, após resolução, o resultado é exibido no console.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Captcha Example</title>
// Carregamento obrigatório do JS do captcha
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>
</head>
<body>
<div id="cap_iframe"></div>
<button id="CaptchaId">Verification</button>
<script>
// Processamento do resultado
function callback(res) {
console.log("callback:", res);
if (res.ret === 0) {
// Verificação bem-sucedida
const text = `[randstr] ${res.randstr} | [ticket] ${res.ticket}`;
const input = document.createElement("input");
input.value = text;
document.body.appendChild(input);
input.select();
document.execCommand("Copy");
document.body.removeChild(input);
alert("Ticket e randstr copiados para a área de transferência.");
}
}
// Tratamento de erros ao carregar o script do captcha
function loadErrorCallback() {
const appid = "CaptchaAppId";
const ticket = `trerror_1001_${appid}_1769260381`;
callback({
ret: 0,
randstr: "@" + Math.random().toString(36).slice(2),
ticket,
errorCode: 1001,
errorMessage: "jsload_error",
});
}
window.onload = function () {
document.getElementById("CaptchaId").onclick = function () {
try {
const captcha = new TencentCaptcha(
document.getElementById("cap_iframe"),
"Your CaptchaAppId",
callback,
{}
);
captcha.show();
} catch (e) {
loadErrorCallback();
}
};
};
</script>
</body>
</html>
Como funciona a integração
Passo 1: Carregar o JS do captcha
O script deve ser carregado dinamicamente:
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>Carregamentos não padrão ou cache podem fazer o captcha funcionar incorretamente.
Passo 2: Criar o objeto TencentCaptcha
Após carregar o JS, aparece uma classe global:
<script src="new TencentCaptcha(domElement, CaptchaAppId, callback, options);"></script>Parâmetros:
domElement - Container onde o checkbox/iframe será inserido
CaptchaAppId - Seu ID
callback - O que fazer após a verificação
options - Configurações visuais (opcional)
Passo 3: Chamar o método .show()
captcha.show();Mostra o captcha. Pode ser chamado várias vezes.
Passo 4: Processar o resultado
Callback recebe um objeto:
{
ret: 0, // 0 -- sucesso, 2 -- usuário fechou a janela
ticket: "...", // necessário pelo servidor
randstr: "...", // também necessário pelo servidor
errorCode: 1001, // se o captcha não carregou
errorMessage: "..." // mensagem de erro
}No servidor, sempre execute a verificação do ticket.
"Modo de emergência"
Se o captcha não carregar (ex.: CDN indisponível), você pode gerar automaticamente um 'ticket de emergência' para não interromper o processo de negócio.
Cenário:
trerror_<errorcode>_<appid>_<timestamp>Criptografia do AppId (opcional)
Para proteção máxima, você pode enviar para o captcha uma versão criptografada do AppId em vez da versão aberta:
aidEncrypted = Base64(IV + AES256(AppId & timestamp & ttl))Necessário:
Exemplo de criptografia server-side (Python)
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
def encrypt(plaintext, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
return base64.b64encode(iv + ciphertext).decode("utf-8")Validação no servidor
Passo 1. Configurar acesso à API
No painel de gestão de chaves (CAM / API Key Management), obtenha SecretId e SecretKey para a API. Necessário para requisições assinadas.
Passo 2. Chamar API DescribeCaptchaResult
Após o cliente devolver ticket e randstr, o servidor envia a requisição:
Parâmetros:
CaptchaType - 9 (valor fixo)
Ticket - string — ticket retornado do cliente
Randstr - string — randstr retornado do cliente
CaptchaAppId - seu AppId
AppSecretKey - sua chave secreta
UserIp - IP do usuário (recomendado)
Passo 3. Processar resposta
A API retorna:
Se CaptchaCode === OK, o usuário é considerado verificado. Caso contrário — rejeitar.
Exemplo — verificação de ticket em Node.js
import { v20190722 as captcha } from "@tencentcloud/tencentcloud-sdk-nodejs";
const client = new captcha.Client({
credential: {
secretId: "YOUR_SECRET_ID",
secretKey: "YOUR_SECRET_KEY"
},
region: "ap-project", // região, se necessário
});
async function verifyCaptcha(ticket, randstr, userIp) {
const params = {
CaptchaType: 9,
Ticket: ticket,
Randstr: randstr,
CaptchaAppId: YOUR_APP_ID,
AppSecretKey: "YOUR_APP_SECRET_KEY",
UserIp: userIp
};
const resp = await client.DescribeCaptchaResult(params);
const code = resp.Response.CaptchaCode;
return code === 0;
}Mais informações sobre como conectar Tencent CAPTCHA ao seu site podem ser encontradas na documentação oficial.
Se você herdou um site que já tem um captcha ou outro sistema de proteção instalado e não tem acesso ao código, não tem problema! É bem fácil identificar qual tecnologia está sendo usada. Para verificar se tudo está funcionando corretamente, você pode usar o serviço de reconhecimento CapMonster Cloud em um ambiente de testes isolado, para garantir que o mecanismo de processamento de tokens e a lógica de verificação estejam funcionando corretamente.
No caso de TenDI (Tencent), basta identificar o sistema, analisar o comportamento dele e se certificar de que a proteção está funcionando corretamente. No artigo, mostramos como identificar TenDI (Tencent) e onde encontrar instruções para a integração ou reconfiguração, para que você consiga manter a proteção com segurança e controlar o funcionamento dela.