En este artículo hemos intentado responder a todas las preguntas clave. Para empezar a resolver la tarea, primero hay que determinar qué sistema de protección se está utilizando. Para ello, puedes consultar la lista de captchas y sistemas de protección antibot más populares, donde se muestran ejemplos visuales y señales clave que te ayudarán a identificar rápidamente con qué estás tratando.
Si descubres que tu sitio web utiliza TenDI (Tencent), el siguiente paso será analizar con más detalle sus propiedades y su funcionamiento. En este mismo artículo también puedes consultar la guía de integración de TenDI (Tencent) para comprender por completo cómo funciona en tu sitio. Esto te permitirá no solo entender la protección actual, sino también planificar correctamente su mantenimiento.
Trabajar con CapMonster Cloud mediante la API suele implicar los siguientes pasos:
type - CustomTask
class - TenDI
websiteURL - la dirección de la página donde se resuelve el captcha.
websiteKey - captchaAppId. Por ejemplo, "websiteKey": "189123456" — un parámetro único para su sitio web.
captchaUrl (dentro de metadata) - enlace al script del captcha. Normalmente termina en TCaptcha.js o TCaptcha-global.js;
websiteURL - dirección de la página donde se resuelve el captcha;
userAgent (opcional) - User-Agent del navegador. Pase solo un UA válido y actualizado desde 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';
// Reemplace con sus propios 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. Abrir la página
await page.goto(WEBSITE_URL, { waitUntil: 'networkidle' });
// 2. Esperar a que aparezca el captcha (por ejemplo, input o iframe)
await page.waitForSelector('#tendi_response, iframe[src*="tendi"], input[name="tendi_response"]', { timeout: 15000 });
// Si es necesario, se puede extraer el websiteKey directamente de la página
const WEBSITE_KEY = await page.evaluate(() => {
// Ejemplo: el sitekey puede estar en un atributo data o en una variable 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. Crear una tarea TenDI
const tenDIRequest = new TenDIRequest({
websiteURL: page.url(),
websiteKey: WEBSITE_KEY,
});
const balance = await client.getBalance();
console.log("Balance:", balance);
// 4. Resolver el captcha
const solution = await client.Solve(tenDIRequest);
console.log("Solution:", solution);
const { ticket, randstr } = solution.solution.data;
// 5. Formas de insertar el resultado
await page.evaluate(({ ticket, randstr }) => {
// Insertar en un campo 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;
}
}
// Función callback en JS
if (typeof window.onCaptchaSolved === 'function') {
window.onCaptchaSolved(ticket, randstr);
inserted = true;
}
// Si no hay input ni 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);
Recibirá dos parámetros: CaptchaAppId y AppSecretKey. Se usan en el frontend y en el servidor.
Al hacer clic, aparece el captcha y tras completarlo se muestra el resultado en la consola.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Captcha Example</title>
// Carga obligatoria del JavaScript del 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>
// Procesamiento del resultado
function callback(res) {
console.log("callback:", res);
if (res.ret === 0) {
// Verificación exitosa
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 y randstr copiados al portapapeles.");
}
}
// Manejo de errores al cargar el script del captcha
function loadErrorCallback() {
const appid = "CaptchaAppId";
const ticket = `trerror_1001_${appid}_1769260300`;
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>
Cómo funciona la integración
Paso 1: Cargar el JavaScript del captcha
El script debe cargarse dinámicamente:
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>Si el script se carga de forma no estándar o se cachea, el captcha puede funcionar incorrectamente.
Paso 2: Crear un objeto TencentCaptcha
Después de cargar el JS, estará disponible una clase global:
<script src="new TencentCaptcha(domElement, CaptchaAppId, callback, options);"></script>Parámetros:
domElement - Contenedor donde se incrusta el checkbox/iframe
CaptchaAppId - Su ID
callback - Acción después de la verificación
options - Configuración visual (opcional)
Paso 3: Llamar al método .show()
captcha.show();Muestra el captcha. Se puede llamar varias veces.
Paso 4: Procesar el resultado
El callback recibe un objeto:
{
ret: 0, // 0 -- éxito, 2 -- usuario cerró la ventana
ticket: "...", // requerido por el servidor
randstr: "...", // también requerido por el servidor
errorCode: 1001, // si el captcha no se cargó
errorMessage: "..." // mensaje de error
}En el servidor siempre se debe realizar una verificación secundaria del ticket.
Modo "Recuperación ante Desastres"
Si el captcha no se carga (por ejemplo, si el CDN no está disponible), se puede emitir automáticamente un ticket de emergencia para no interrumpir los procesos de negocio.
Escenario:
trerror_<errorcode>_<appid>_<timestamp>Cifrado de AppId (opcional)
Si se requiere protección máxima, puede pasar a la captcha una versión cifrada del AppId en lugar del original:
aidEncrypted = Base64(IV + AES256(AppId & timestamp & ttl))Requerido:
Ejemplo de cifrado en el servidor (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")Validación del servidor
Paso 1. Configurar acceso API
En el panel de gestión de claves (CAM / API Key Management), obtenga SecretId y SecretKey para la API. Estas claves son necesarias para solicitudes API firmadas.
Paso 2. Llamar a la API DescribeCaptchaResult
Después de que el cliente devuelva ticket y randstr, el servidor debe enviar la siguiente solicitud:
Parámetros:
CaptchaType - 9 (valor fijo)
Ticket - cadena — ticket devuelta por el cliente
Randstr - cadena — randstr devuelta por el cliente
CaptchaAppId - su AppId
AppSecretKey - su clave secreta
UserIp - IP del usuario (recomendado)
Paso 3. Procesar la respuesta
La API devuelve:
Si CaptchaCode === OK, el usuario se considera verificado. De lo contrario, rechazar.
Ejemplo — verificación del ticket en 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ón, si es necesario
});
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;
}Puede encontrar más información sobre cómo integrar Tencent CAPTCHA en su sitio web en la documentación oficial.
Si has heredado un sitio web que ya tiene un captcha u otro sistema de protección instalado y no tienes acceso al código, no pasa nada. Identificar qué tecnología se está utilizando es bastante sencillo. Para comprobar que todo funciona correctamente, puedes usar el servicio de reconocimiento CapMonster Cloud en un entorno de pruebas aislado, para asegurarte de que el mecanismo de procesamiento de tokens y la lógica de verificación funcionan correctamente.
En el caso de TenDI (Tencent), basta con detectar el sistema, analizar su comportamiento y confirmar que la protección funciona correctamente. En el artículo hemos mostrado cómo identificar TenDI (Tencent) y dónde encontrar las instrucciones para su integración o reconfiguración, de modo que puedas mantener la protección con confianza y controlar su funcionamiento.