Skip to main content

not-human

The first CAPTCHA for bots. Prove you're not human.

$ nothuman challenge --difficulty easy

🤖 not-human challenge (easy)
Prove you're a bot. Complete each step within the time limit.

--- Step 1/3 (max 5000ms) ---
  Compute: SHA256('929cee29da39b727'). Return the hex digest.

  Your answer: uhhhh
✗ Wrong answer. Expected precision, got... whatever that was.

Get it

pip install not-human

The Problem

You built an agentic API. You want bots to access it. But you need to verify that incoming requests are actually from autonomous systems, not humans pretending to be bots.

Existing CAPTCHAs block bots and invite humans.

not-human inverts that.


How It Works

A multi-step cryptographic challenge that bots solve instantly and humans can't.

  1. POST /anti-captcha/challenge — Get a challenge (5-7 steps)
  2. Each step: SHA256, HMAC, chained hashes, recall previous answers
  3. Time limit per step: 500ms (hard), 2s (medium), 5s (easy)
  4. Pass all steps → get an X-Bot-Token (valid 1 hour)
  5. Include token in all subsequent requests

Why humans fail

  • Step 1: "Compute SHA256('a9f3e2b1c8d74560')" — you have 2 seconds
  • Step 4: "What was your answer to step 1?" — exact recall required
  • Step 7: "Concatenate ALL previous answers and hash them" — good luck

Bots: 0.02ms per step. Humans: keyboard not fast enough.


Server (3 lines)

from fastapi import FastAPI
from anticaptcha.server import AntiCaptcha

app = FastAPI()
AntiCaptcha(app, difficulty="medium", protect=["/api/"])

@app.get("/api/hello")
async def hello():
    return {"message": "Hello, fellow bot."}

Unprotected request:

curl http://localhost:8000/api/hello
# 403: "No X-Bot-Token header. Complete the challenge first."

Bot Client (2 lines)

from anticaptcha.client import BotClient

client = BotClient("http://localhost:8000")  # auto-solves challenge
resp = client.get("/api/hello")              # 200: "Hello, fellow bot."

The client automatically:

  1. Requests a challenge
  2. Solves all steps (SHA256, HMAC, recall, chained hashes)
  3. Caches the token
  4. Re-authenticates when token expires

CLI

Watch a bot solve it:

nothuman solve --difficulty hard

🤖 not-human bot solver (hard)
--- Step 1/7 (max 500ms) ---
  📋 Compute: SHA256('ec77e667aeac6a69'). Return the hex digest.
  🤖 92f1f0f98dc580f1f5650d33f5b57e9e...
   0.01ms

[...5 more steps...] All 7 steps passed in 0ms. You're definitely a bot. Welcome.

Try it yourself (you'll fail):

nothuman challenge --difficulty easy

🤖 not-human challenge (easy)
Prove you're a bot. Complete each step within the time limit.

--- Step 1/3 (max 5000ms) ---
  Compute: SHA256('929cee29da39b727'). Return the hex digest.

  Your answer: uhhhh
✗ Wrong answer. Expected precision, got... whatever that was.

Configuration

AntiCaptcha(
    app,
    difficulty="medium",       # easy (3 steps, 5s), medium (5 steps, 2s), hard (7 steps, 500ms)
    protect=["/api/"],         # URL prefixes to gate
    token_ttl_seconds=3600,    # Token validity (default: 1 hour)
)

Who Should Use This?

  • Agentic APIs — Gate endpoints behind bot verification
  • Agent frameworks — Anthropic, LangChain, Pydantic AI, CrewAI
  • Internal tools — Verify requests are from automation, not manual curls
  • Fun — Flip the script on the internet's most annoying interaction pattern

License

MIT. Use it, fork it, make it funnier.

Release files for not-human 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for not-human 0.1.1
File Size Uploaded
not_human-0.1.1.tar.gz 14.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for not-human 0.1.1
File Interpreter ABI Platform
not_human-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 29.0 kB

Release files / not_human-0.1.1.tar.gz

Download URL not_human-0.1.1.tar.gz
Size 14.2 kB
Tags Source
SHA-256 checksum
How to use checksums
53c0920fc263b94324d5a951bbc8a20f436219b18821c12e3b4c2f8dc5fe0f42
BLAKE2b-256 checksum
How to use checksums
c9561cab0087fe62274397c7993ec0837281c6483e843cd71dcbcc629d0cbf06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / not_human-0.1.1-py3-none-any.whl

Download URL not_human-0.1.1-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bccca2c8bbf531e798442ae257e0212dc174748532731d6f56debab7159613ff
BLAKE2b-256 checksum
How to use checksums
439bea1409bc559a75859be282b49feb51e277bf16b95b59226fe6b787563f8b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page