DevTcha

Stop form spam without tracking your visitors

DevTcha is a proof-of-work bot protection that runs on your own server. No cookie, no third-party request, nothing to click or decipher: the browser solves a small computation in the background, and bots pay for every submission.

Try the demo npm install devtcha

Why DevTcha

A lightweight alternative to reCAPTCHA and hCaptcha for contact, sign-up and comment forms.

No cookie, no third party

Challenges and checks stay between your visitors and your server. Nothing to declare to an external provider.

Nothing to solve

No images, no checkbox. The computation starts when the form is displayed and usually ends before it is filled in.

Accessible

A polite role="status" message announces each state to screen readers. Texts can be translated with attributes.

Four server languages

Node.js (TypeScript), PHP, Python and Go, all checked against the same shared test vectors.

Small and dependency-free

The browser script weighs 5.7 KB minified. Each server uses only its standard library.

Single-use tokens

Signed challenges, expiry date, replay protection with a pluggable store (memory, files, Redis, SQL).

How it works

The server issues a signed challenge; the browser finds the secret number by brute force; the server checks the answer once.

The browser asks your server for a challenge, solves it in a Web Worker, then sends the token with the form; the server checks it.

Live demo

The real <dev-tcha> widget, running in this page. Send the form, then try to replay the same token.

Server side (simulated in this page)

    To work without a server, this demo creates and checks challenges in the page itself, with a secret stored in the browser. It shows the behavior, it protects nothing. In production, both steps stay on your server.

    Measured on a 2021 laptop (Ryzen 7 5700U, Chromium, default difficulty): median 637 ms per challenge, 1.3 s to scan the whole range (worst case). Not measured on phones, where it is probably slower.

    What visitors see

    Solving in progress
    Solving in progress
    Ready to send
    Ready to send
    Sent before the end of the computation
    Sent before the end of the computation
    Challenge unavailable
    Challenge unavailable

    Integration

    Two server calls and one HTML element. npm install devtcha

    <script src="/devtcha.js" defer></script>
    
    <form method="post" action="/contact">
      <textarea name="message" required></textarea>
      <dev-tcha challengeurl="/api/devtcha"></dev-tcha>
      <button type="submit">Send</button>
    </form>

    Without a build tool, serve dist/devtcha.js from your own domain. With Vite, webpack or Next.js: import "devtcha/client".

    import { createChallenge, verifySolution } from 'devtcha/server';
    
    const secret = process.env.DEVTCHA_SECRET; // 32+ random characters
    
    // GET /api/devtcha (Cache-Control: no-store)
    res.json(createChallenge({ secret }));
    
    // POST /contact
    const result = await verifySolution(req.body.devtcha, { secret });
    if (result !== 'ok') return res.status(400).end(); // invalid, expired, reused
    require 'devtcha.php';
    
    // GET /api/devtcha
    header('Content-Type: application/json');
    header('Cache-Control: no-store');
    echo json_encode(devtcha_create_challenge($secret));
    
    // POST /contact
    $result = devtcha_verify($_POST['devtcha'] ?? null, $secret);
    if ($result !== 'ok') { http_response_code(400); exit; }

    The PHP version ships with the npm package (node_modules/devtcha/php/devtcha.php): a single file, PHP 7.4 or later, standard extensions only.

    Full documentation

    FAQ

    Does it stop every bot?

    No. It makes bulk submissions expensive, but a bot that runs JavaScript will get through after paying the computation. Combine it with rate limiting and a honeypot field.

    Do I need a cookie banner for it?

    DevTcha sets no cookie, uses no browser storage and contacts no third party: it adds no reason to show a consent banner.

    Does it work without JavaScript?

    No: without JavaScript no token is computed and the server rejects the form. Add a <noscript> message and offer another way to contact you.

    Is it a hosted service?

    No. It is a library: each site serves its own challenges and checks its own tokens.