DEV Community

Francisco López
Francisco López

Posted on

Stop Using CAPTCHA. Start Measuring Entropy.

Stop Using CAPTCHA. Start Measuring Entropy.

In late 2024, researchers at ETH Zurich quietly published an obituary for the web as we know it. They didn't call it that, of course. They called it "Breaking reCAPTCHAv2."

Their findings were stark: modern AI models (specifically YOLO-based vision models) can now solve Google's image CAPTCHAs with 100% accuracy.

Read that again. 100%.

The Turing Test hasn't just been passed; it’s been automated, containerized, and scaled. The "I am not a robot" checkbox is now effectively a "Welcome" mat for bots.

According to the 2025 Imperva Bad Bot Report, automated traffic has officially surpassed human traffic, accounting for 51% of all internet activity. We are effectively the minority on our own network.

If we want to save the web from becoming a "Dead Internet" of bots talking to bots, we need to stop asking users to identify traffic lights and start listening to their heartbeat.

The Hypothesis: Identity vs. Humanity

The current knee-jerk reaction is "Proof of Personhood" (scanning your ID or face to use the web). I believe this is a dystopian overcorrection.

We don't need to know who you are (Identity). We just need to know what you are (Biology).

  • Identity is static data (Names, IDs).
  • Humanity is dynamic behavior (Reaction times, hesitation, errors).

Humans are messy. We are beautifully, consistently imperfect. When you type, you don't hit keys at a perfect 150ms interval. You "rollover" keys. You pause to think. You speed up on common bigrams like "th" or "er."

This is your Keystroke Dynamics signature. It is a behavioral biometric that is incredibly hard for bots to fake convincingly without slowing them down to useless human speeds.

Enter isHumanCadence

I built isHumanCadence as a Proof of Concept (PoC) to test this hypothesis.

It is a lightweight, privacy-focused library that analyzes the timing of keystrokes—not the content. It runs entirely in the browser, sends no data to a server, and doesn't know what you typed, only how you typed it.

How It Works (The Technical Deep Dive)

Bots are deterministic. Even when programmed with Math.random() delays, they tend to follow a uniform or Gaussian distribution that is statistically "too clean."

isHumanCadence measures four primary biological constraints:

  1. Dwell Time: The duration a key is physically depressed. Humans rarely tap keys for exactly 50ms every time.
  2. Flight Time: The time between releasing one key and pressing the next.
  3. Rollover Rate: The overlap where Key B is pressed before Key A is released. This is a high-signal human trait; simple bots often type strictly sequentially (Key A down -> Key A up -> Key B down).
  4. Entropy: The statistical variance of the timing deltas.

The "Secret Sauce": Hysteresis

One major challenge with heuristic analysis is "flickering." A user might type one word rhythmically (High Human Score) and then pause abruptly to think (Score drops). You don't want the UI to flash "BOT DETECTED" instantly.

I implemented a Schmitt Trigger (Hysteresis) to stabilize the classification. We use different thresholds for entering and exiting states:

  • To become Human: Score must exceed 0.70.
  • To drop to Unknown: Score must fall below 0.60.
  • To become Bot: Score must fall below 0.35.

This creates a "dead zone" where the state remains stable, preventing false positives during natural cognitive pauses.

Implementation

The library attaches non-intrusive listeners to the target input field. It uses performance.now() for sub-millisecond precision.

1. Install the package:

npm install @rolobits/is-human-cadence
Enter fullscreen mode Exit fullscreen mode

2. Attach it to an input:

import { createCadence } from '@rolobits/is-human-cadence';

// Select any textarea or input on your page
// We use a broad selector here to ensure we find *something*
const input = document.querySelector('textarea, input');

if (input) {
  const cadence = createCadence(input, {
    // Wait for 20 keystrokes before making a confident judgment
    minSamples: 20, 

    onScore: (result) => {
      console.log(`Score: ${result.score}`); // 0.0 (Bot) -> 1.0 (Human)
      console.log(`Status: ${result.classification}`); // 'bot' | 'human' | 'unknown'
    }
  });

  // Start listening
  cadence.start();
  console.log("isHumanCadence: Listening for keystrokes...");
} else {
  console.warn("isHumanCadence: No input element found on this page.");
}
Enter fullscreen mode Exit fullscreen mode

The Reality Check: A Proof of Concept

Right now, this library detects standard scripts and even sophisticated bots using randomized delays. But "Generative Keystrokes" are the next frontier. Eventually, AI agents will be trained on massive datasets of human typing patterns to spoof these very metrics. They will learn to "stumble" on purpose.

Furthermore, client-side security is inherently trustless. If the browser can measure it, a determined attacker can eventually spoof the environment to fake it.

This package is not a silver bullet. It is a conversation starter.

Join

The web is drowning in AI noise. If we want to keep a space for human connection, we need to build filters that recognize us not by our passwords, but by our rhythm.

👉 GitHub: RoloBits/isHumanCadence

Top comments (1)

Collapse
 
xwero profile image
david duymelinck

While they try to humanize machines, we need to find out what make us human.