Visão geral
Suas métricas de captcha em tempo real
Sites ativos
—
Verificações totais
—
Sucesso
—
Falhas
—
Taxa de sucesso
—
Sites recentes
Meus sites
Gerencie suas site keys e domínios
Documentação
Integre o PikaCaptcha em qualquer projeto
Como funciona
O PikaCaptcha usa Proof of Work (PoW) — o frontend resolve um desafio SHA256 antes de submeter o formulário. O resultado é verificado pelo seu backend via /api/siteverify, exatamente como o reCAPTCHA.
1
Frontend: GET /api/challenge
Busca um desafio usando a
siteKey pública2
Frontend: resolve o PoW + POST /api/verify
Resolve SHA256 e envia o nonce. Recebe um
token3
Backend: POST /api/siteverify
Valida o token com a
secretKey. Nunca exponha no frontend!GET /api/challenge
| Parâmetro | Tipo | Descrição |
|---|---|---|
| sitekey | string | Sua site key pública (pk_...) obrigatório |
Resposta:
{ "id": "abc123", "challenge": "deadbeef...", "difficulty": 4, "algorithm": "sha256", "expires_in": 300 }
POST /api/verify
| Parâmetro | Tipo | Descrição |
|---|---|---|
| id | string | ID do challenge obrigatório |
| nonce | number | Nonce encontrado no PoW obrigatório |
| sitekey | string | Sua site key (pk_...) obrigatório |
| fingerprint | object | Dados de fingerprint (opcional, aumenta score) |
Resposta:
{ "success": true, "token": "eyJ...", "score": 0.9, "expires_in": 120 }
POST /api/siteverify (backend only)
| Parâmetro | Tipo | Descrição |
|---|---|---|
| secret | string | Sua secret key (sk_...) obrigatório |
| token | string | Token recebido do /api/verify obrigatório |
| remoteip | string | IP do usuário (opcional) |
Resposta:
{ "success": true, "score": 0.9, "flags": [], "challenge_ts": "2024-01-01T00:00:00.000Z", "hostname": "seusite.com" }
SDK & Exemplos
Copie e cole no seu projeto
Frontend — JavaScript (vanilla)
// Full SDK — cole no seu frontend async function getPikaToken(siteKey) { // 1. Buscar challenge const r1 = await fetch(`/api/challenge?sitekey=${siteKey}`) const { id, challenge, difficulty, sig } = await r1.json() // 2. Resolver PoW (medir tempo para scoring) const t0 = performance.now() const nonce = await solvePoW(challenge, difficulty) const solveTimeMs = Math.round(performance.now() - t0) // 3. Coletar fingerprint const fingerprint = await collectFingerprint(solveTimeMs) // 4. Verificar e obter token const r2 = await fetch('/api/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id, nonce, sitekey: siteKey, sig, fingerprint, honeypot: '' // sempre string vazia — bots preenchem }) }) const { token } = await r2.json() return token } // PoW usando Web Workers (não trava a UI) function solvePoW(challenge, difficulty) { return new Promise(resolve => { const prefix = '0'.repeat(difficulty) let nonce = 0 function tick() { for (let i = 0; i < 5000; i++) { if (sha256hex(challenge + nonce).startsWith(prefix)) return resolve(nonce) nonce++ } setTimeout(tick, 0) // yield para não travar UI } tick() }) } // Coleta ~12 sinais para scoring anti-bot async function collectFingerprint(solveTimeMs) { let canvasHash = '', webglRenderer = '' try { const c = document.createElement('canvas') c.getContext('2d').fillText('pika', 2, 15) canvasHash = c.toDataURL().slice(-32) const gl = c.getContext('webgl') webglRenderer = gl?.getParameter(gl.getExtension('WEBGL_debug_renderer_info') ?.UNMASKED_RENDERER_WEBGL) || '' } catch {} return { userAgent: navigator.userAgent, language: navigator.language, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, screen: `${screen.width}x${screen.height}`, colorDepth: screen.colorDepth, pluginCount: navigator.plugins?.length ?? 0, canvasHash, webglRenderer, solveTimeMs, mouseEvents: window._pikaMouseCount || 0 } } // Rastrear movimento de mouse (cole no <body> uma vez) let _pikaMouseCount = 0 document.addEventListener('mousemove', () => _pikaMouseCount++, { passive: true }) window._pikaMouseCount = _pikaMouseCount
Backend — Node.js / Express
app.post('/submit', async (req, res) => { const { pikaToken, ...formData } = req.body const verify = await fetch('https://SEU_SITE.netlify.app/api/siteverify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ secret: process.env.PIKA_SECRET_KEY, // sk_xxx — nunca no frontend! token: pikaToken, remoteip: req.ip }) }) const result = await verify.json() if (!result.success || result.score < 0.5) { return res.status(403).json({ error: 'Captcha falhou' }) } // Processar formulário normalmente... })
Backend — Python / Flask
import requests def verify_captcha(token): r = requests.post('https://SEU_SITE.netlify.app/api/siteverify', json={ 'secret': os.environ['PIKA_SECRET_KEY'], 'token': token }) data = r.json() return data.get('success') and data.get('score', 0) >= 0.5