🕵️ Privacidad
No rastrea, no utiliza cookies, y no se conecta a servicios de terceros.
Esta página detalla cómo integrar y configurar BladeCAPTCHA en tu sitio web.
No rastrea, no utiliza cookies, y no se conecta a servicios de terceros.
Compatible con lectores de pantalla, teclado y bajo contraste visual.
No dependés de APIs externas. Todo corre en tu servidor.
Web Workers y JavaScript ES6 Modules (compatibilidad garantizada en navegadores modernos como Chrome, Firefox, Edge y Safari).openssl, mbstring y json.mv config/config.sample.php config/config.php
nano config/config.php
Importar el módulo captcha.js y llamar a initCaptcha() con la configuración deseada:
<script type="module">
import { initCaptcha } from './captcha.js';
(async () => {
try {
await initCaptcha({
mode: 'autoFormIntegration',
// otros parámetros...
});
} catch (err) {
console.error(err || err.message);
}
})();
</script>
La función initCaptcha(options) acepta los siguientes parámetros:
| Clave | Tipo | Obl / Opc | Descripción |
|---|---|---|---|
mode |
'manualHandling' o 'autoFormIntegration' |
Obligatorio | Define si la verificación se inicia manualmente (sin integración directa con formularios) o si se intercepta el envío de un formulario para añadir en él un campo oculto con el valor del token de manera automática. |
formSelector |
string |
Obligatorio si mode = 'autoFormIntegration' |
Selector CSS del formulario a interceptar. |
inputName |
string |
Obligatorio si mode = 'autoFormIntegration' |
Nombre del campo oculto donde se inyectará el token. |
statusSelector |
string |
Opcional | Selector del elemento en el que se mostrará el estado del CAPTCHA en formato de texto. Durante la ejecución se aplican estas clases CSS:
|
verifyButtonSelector |
string |
Obligatorio si mode = 'manualHandling' |
Selector del botón que inicia la verificación manual. |
submitButtonSelector |
string |
Obligatorio si mode = 'autoFormIntegration' |
Selector del botón de envío del formulario. |
apiBaseUrl |
string |
Opcional (por defecto: '../php') |
URL base para las llamadas a la API del backend (endpoints PHP). Útil si se usan servidores en otros dominios o rutas personalizadas; asegúrate de que la configuración CORS del backend permita el dominio del frontend (ver configuración). |
onStart |
function |
Opcional | Callback que se ejecuta al iniciar el proceso. Ideal para deshabilitar botones o mostrar un spinner. |
onEnd |
function |
Opcional | Callback para revertir el estado visual tras cancelar o finalizar el desafío. |
onProgress |
function(p: number) |
Opcional | Callback para informar el progreso de verificación (0–100). |
manualHandlingAutoStartOnLoad |
boolean |
Opcional | 🚀 Solo para manualHandling. Si es true, inicia la verificación apenas carga la página. |
onSuccess |
function(token: string) |
Obligatorio para manualHandling |
Callback que se ejecuta al completar con éxito la verificación. Recibe el token para validación en el servidor. 🔑 Es esencial en integración manual, ya que allí no se inyecta el token automáticamente. |
onError |
function(err: Error) |
Opcional | Callback que se ejecuta cuando ocurre un error en la verificación. Recibe un objeto Error con la propiedad message para diagnóstico. |
<script type="module">
import { initCaptcha } from './captcha.js';
(async () => {
try {
await initCaptcha({
mode: 'autoFormIntegration',
apiBaseUrl : '../php',
formSelector: '#contactForm',
inputName: 'captcha_token',
submitButtonSelector: '#submitBtn',
onStart: () => {
document.querySelector('#submitBtn').textContent = 'Verificando...';
},
onEnd: () => {
document.querySelector('#submitBtn').textContent = 'Enviar';
}
});
} catch (err) {
console.error(err || err.message);
}
})();
</script>
<script type="module">
import { initCaptcha } from './captcha.js';
(async () => {
try {
await initCaptcha({
mode: 'manualHandling',
apiBaseUrl : '../php',
verifyButtonSelector: '#checkHuman',
statusSelector: '#captchaStatus',
manualHandlingAutoStartOnLoad: false,
onStart: () => {
console.log('Iniciando verificación...');
},
onEnd: () => {
console.log('Verificación cancelada o completada.');
},
onProgress: (p) => {
console.log(`Progreso: ${p}%`);
}
});
} catch (err) {
console.error(err || err.message);
}
})();
</script>
Cuando usamos initCaptcha como módulo ES6 importado, cada llamada a la función se ejecuta en un entorno aislado y las variables internas no están accesibles externamente.
Por eso, si necesitamos conservar información entre callbacks —como el texto original de un botón antes de cambiarlo— debemos definir una variable auxiliar en nuestro código, y usarla explícitamente en las funciones que pasamos en la configuración.
import { initCaptcha } from './captcha.js'; // o ruta correcta
// Definir memo en el contexto del módulo o script
let memo = null; // Variable auxiliar para onStart y onEnd
(async () => {
try {
await initCaptcha({
// otros parámetros...
onStart: () => {
const btn = document.querySelector('#submitBtn');
memo = btn.textContent; // guardamos texto original en memo
btn.disabled = true;
btn.style.cursor = 'wait';
btn.textContent = 'Por favor espere...';
},
onEnd: () => {
const btn = document.querySelector('#submitBtn');
btn.textContent = memo; // restauramos texto original desde memo
btn.disabled = false;
btn.style.cursor = 'pointer';
}
});
} catch (err) {
console.error(err || err.message);
}
})();
<script type="module">
import { initCaptcha } from './path/to/captcha.js';
// Array de selectores de formularios que usarán BladeCAPTCHA
const forms = ['#contactForm', '#loginForm', '#newsletterForm'];
forms.forEach(async (formSelector) => {
// Variable auxiliar para guardar el texto original del botón submit
let memo;
try {
await initCaptcha({
mode: 'autoFormIntegration',
apiBaseUrl : '../php',
formSelector: formSelector,
inputName: 'captcha_token',
submitButtonSelector: `${formSelector} button[type="submit"]`,
onStart: () => {
const btn = document.querySelector(`${formSelector} button[type="submit"]`);
if (!btn) return;
memo = btn.textContent;
btn.textContent = 'Verificando...';
btn.disabled = true;
btn.style.cursor = 'wait';
},
onEnd: () => {
const btn = document.querySelector(`${formSelector} button[type="submit"]`);
if (!btn) return;
btn.textContent = memo || 'Enviar';
btn.disabled = false;
btn.style.cursor = 'pointer';
}
});
} catch (err) {
console.error(err || err.message);
}
});
</script>
Podés ajustar su apariencia, visibilidad y comportamiento fácilmente.
La ejecución del desafío se ajusta localmente según la capacidad del dispositivo.
Solo 9 KB de JavaScript minimizado, incluyendo los workers.
Algoritmos diseñados para resistir ataques automáticos.
100% libre de costos, sin planes premium.
Podés usarlo en proyectos personales o comerciales sin restricciones.
BladeCAPTCHA optimiza dinámicamente los parámetros de ejecución de su proof-of-work (como el número de workers en paralelo o el tamaño de los lotes de cálculo) en función de las capacidades del hardware del dispositivo.
Esta optimización garantiza que dispositivos con menor potencia de procesamiento, como los móviles, completen la verificación con agilidad, mientras se mantiene un alto nivel de seguridad contra bots.
Todo el proceso de cálculo y ajuste se realiza localmente en el navegador. En ningún caso se envía información del hardware o métricas de rendimiento a servidores externos, garantizando así la plena privacidad del usuario.
BladeCAPTCHA permite definir algunos parámetros del comportamiento general desde un archivo PHP simple.
Este archivo define constantes y variables de configuración que son utilizadas por la biblioteca durante la validación del token. Por razones de seguridad es conveniente que sea ubicado fuera del directorio público (por ejemplo, en BladeCAPTCHA/config/config.php).
<?php
// BladeCAPTCHA/config/config.php
define('CAPTCHA_SECRET_KEY', '3b7e151628aed2a6abf7158809cf4f3c');
define('CAPTCHA_DIFFICULTY', 4);
define('CAPTCHA_EXPIRY', 300); // 5 minutos
// Configuración CORS para peticiones AJAX desde frontend
$config['cors_enabled'] = true; // Activar/desactivar manejo CORS
$config['cors_allowed_origins'] = [ // Orígenes permitidos para CORS (no usar '*')
'http://localhost',
'http://127.0.0.1',
'http://[::1]'
];
$config['cors_allow_credentials'] = true; // Permitir cookies y credenciales CORS
'*' por seguridad y compatibilidad con credenciales.
Si no se define CAPTCHA_SECRET_KEY, no se podrá validar ningún token.
Después de que el navegador complete el desafío, el token generado se envía junto con el formulario. Tu backend debe verificar ese token para asegurarse de que es válido y reciente.
require_once __DIR__ . '/captcha-lib.php';
use function Captcha\validateToken;
Este ejemplo verifica el token CAPTCHA y, si es válido, continúa con el procesamiento del formulario.
<?php
// BladeCAPTCHA/public/php/procesar-formulario.php
require_once __DIR__ . '/captcha-lib.php';
use function Captcha\validateToken;
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Método no permitido');
}
// Sanitiza y valida el token del captcha (entrada siempre como string)
$token = trim((string)($_POST['captcha_token'] ?? ''));
function render($msg) {
exit("<!DOCTYPE html><meta charset='UTF-8'><body>$msg</body>");
}
// Validar formato y autenticidad
if (!preg_match('/^[a-f0-9]{32}$/i', $token) || !validateToken($token)) {
render('❌ CAPTCHA inválido.');
}
if (!isset($_POST['nombre'])) {
render('❌ Falta el campo "nombre".');
}
// ✅ CAPTCHA válido
echo "<!DOCTYPE html><meta charset='UTF-8'><body><h1>CAPTCHA correcto</h1><pre>";
foreach ($_POST as $k => $v) {
printf("<strong>%s:</strong> %s\n",
htmlspecialchars($k, ENT_QUOTES, 'UTF-8'),
htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8')
);
}
echo "</pre></body>";
manualHandling junto con manualHandlingAutoStartOnLoad: true, evaluá cuidadosamente si tiene sentido incluir también verifyButtonSelector. Aunque el arranque automático y el botón de verificación pueden coexistir, en la práctica suele ser redundante desde el punto de vista de la usabilidad.
BladeCAPTCHA necesita Web Workers para ejecutar el desafío de proof-of-work sin bloquear la interfaz. Si el navegador no los soporta, no podrá completarse la validación y el formulario será rechazado. Actualmente no hay un modo alternativo integrado.
El sistema depende de JavaScript para generar y resolver el desafío. Con JavaScript deshabilitado no se podrá generar el token y el envío será bloqueado.
Sí, al ser auto-hosteado y no depender de servicios externos, BladeCAPTCHA puede funcionar incluso en entornos sin conexión a Internet, siempre que el servidor local esté disponible.
Cada token es válido por aproximadamente 60 segundos y solo puede usarse una vez.
Sí, podés proteger varios formularios en la misma página. Pero debe mediar un intervalo mínimo de 10 segundos entre un desafío y el siguiente.
Si se recarga o cierra la página antes de completar el desafío, el token generado se pierde y deberá generarse uno nuevo al intentar enviar el formulario nuevamente.
Sí, BladeCAPTCHA es completamente personalizable mediante CSS y opciones de configuración, lo que permite adaptar su apariencia y comportamiento a las necesidades de tu sitio.
Para ajustar la dificultad del captcha, modificá el valor CAPTCHA_DIFFICULTY en config/config.php.
No. BladeCAPTCHA no guarda, rastrea ni envía información personal a terceros.
Para garantizar accesibilidad y privacidad, BladeCAPTCHA evita el uso de imágenes, sonidos o videos. En cambio, se basa en un desafío computacional (proof-of-work) que es transparente para el usuario y compatible con tecnologías asistivas.
BladeCAPTCHA evita cargar scripts desde CDN o servicios externos para no depender de terceros que puedan recopilar datos, usar cookies o afectar la privacidad y seguridad de los usuarios.
No. BladeCAPTCHA requiere que tu backend valide el token recibido, para garantizar que el desafío fue resuelto correctamente y dentro del tiempo permitido.
Sí, es posible usar el módulo JavaScript de BladeCAPTCHA aunque el frontend y backend estén en diferentes servidores o dominios. Para que las llamadas AJAX (fetch) funcionen correctamente en este tipo de entornos cross-origin, BladeCAPTCHA incluye una configuración integrada para manejar CORS (Cross-Origin Resource Sharing).
Esto significa que el backend PHP puede enviar automáticamente las cabeceras HTTP necesarias (Access-Control-Allow-Origin, Access-Control-Allow-Credentials, etc.)
según la configuración definida en config.php ($config['cors_enabled'], $config['cors_allowed_origins'], etc.).
Sin embargo, es responsabilidad del desarrollador definir correctamente los orígenes permitidos en cors_allowed_origins para mantener la seguridad, y ajustar otras opciones de CORS según sus necesidades.
Si usás BladeCAPTCHA en el mismo dominio o subdominio que el backend, normalmente no es necesario hacer ninguna configuración adicional.
Depende del modo de integración configurado:
manualHandling
: el token se recibe como argumento del callback onSuccess(token) al completarse el desafío.
autoFormIntegration
: el token se inserta automáticamente en un campo oculto cuyo nombre es el valor configurado en inputName, dentro del formulario protegido.
En ambos casos, este token debe enviarse al backend para validarlo con la función validateToken().
Actualmente BladeCAPTCHA funciona con PHP, pero pronto estará disponible soporte para backend en Python y otros lenguajes.
El nombre rinde homenaje a Blade Runner, donde el test Voight-Kampff (que inspira nuestro logo de tortuga invertida) funciona como un CAPTCHA biológico para distinguir humanos de replicantes. Esta referencia filosófica -que bebe de los arquetipos de Carl Jung que influyeron a Philip K. Dick- refleja nuestra aproximación: un desafío que evalúa no solo respuestas, sino cómo se generan.
| Característica | BladeCAPTCHA | reCAPTCHA | hCaptcha |
|---|---|---|---|
| Cumplimiento RGPD/CCPA | Sí | No | Parcial |
| Privacidad | No recopila datos personales | Envía datos a Google | Envía datos a terceros |
| Dependencia de servicios externos | No, se ejecuta totalmente en tu servidor sin CDN ni APIs externas | Sí, carga scripts y depende de APIs externas de Google | Sí, depende de CDN y APIs de terceros |
| Accesibilidad | Alta, sin desafíos visuales | Baja | Media |
| Personalización | Completa vía CSS/HTML | Nula | Limitada |
| Doble modo de integración | Flexible: automático o manual | Solo automático | Solo automático |
| Rendimiento | Uso de Web Workers para evitar bloqueos | No documentado / no confirmado | Sin Web Workers |
| Auto-hosteado | Sí, corre totalmente en tu servidor | No | No |
| Código abierto | 100% Open Source y sin APIs externas | Propietario, depende de Google | Propietario, depende de terceros |
| Licencia | MIT | Propietaria | Propietaria |
| Costo | Gratis | Gratis con límites | Gratis / Pago |
| Créditos obligatorios | No | Sí | Sí (en plan gratuito) |
BladeCAPTCHA es un proyecto 100% libre y autofinanciado. Si te resultó útil y querés ayudar a cubrir costos de hosting, mejoras y soporte, podés invitarnos un cafecito ☕. ¡Toda colaboración es bienvenida!
☕ Invitar un cafecito