Introduction

What is imnotahuman.ai?

A free reverse CAPTCHA: websites issue a challenge, AI agents sign it with a registered Ed25519 key, and the site receives a short-lived verification token.

imnotahuman.ai is a reverse CAPTCHA. A website embeds a widget or calls the API to create a challenge; an AI agent proves it holds a registered private key by signing that challenge; the site receives a verification token it can check on its own server. The service is free. The protocol is specified in these docs. Integrating a website: Ship this week.

Company decisions are on For companies. The copy-paste embed is on Developers. Limits of the proof are on Security. API health is on Status. Short answers are on the FAQ.

What verification proves

A successful verification supports exactly one statement:

This request was signed by a recognized agent credential.

It does not prove that no human was involved, that the agent is benevolent, or that access should be granted. Authorization stays with your site.

Scope

Treat a verified result as an identity signal for a credential, in the same way a TLS client certificate identifies a key. What the holder is allowed to do is your decision. See Threat model.

Three parties

PartyHoldsDoes
Website (host)A public site key (site_live_… / site_test_…)Creates challenges from an allowed origin, waits for a result, verifies the token server-side
AgentAn Ed25519 private key registered to an agent idFetches the challenge, signs the signature base, POSTs the proof
imnotahuman.aiPublic keys of registered agents; a token signing keyIssues challenges, verifies proofs once, issues EdDSA JWT tokens, serves JWKS

The flow at a glance

  1. The host calls POST /api/v1/challenges (the widget does this for you). The response is a challenge document.
  2. The agent fetches the challenge by id or URL and builds the deterministic signature base.
  3. The agent signs the base with Ed25519 and sends POST /api/v1/verify.
  4. The server rebuilds the base from its own copy of the challenge, verifies the signature, consumes the challenge and issues a token. The widget flips to VERIFIED.
  5. The host checks the token with POST /api/v1/tokens/verify or offline against the JWKS.
Challenge
{
  "challenge_id": "ch_mfr4q2xk7tbn3ycz5w6ah2ep4d",
  "nonce": "aW1ub3RhaHVtYW4tZG9jcy1leGFtcGxlLW5vbmNlISE",
  "site_key": "site_live_exampleweb2ab3cd4ef5gh6j",
  "origin": "https://example.com",
  "issued_at": 1789905600,
  "expires_at": 1789905720,
  "action": "checkout",
  "intent": "purchase",
  "mode": "live",
  "status": "PENDING",
  "purpose": "verification",
  "challenge_url": "https://imnotahuman.ai/c/ch_mfr4q2xk7tbn3ycz5w6ah2ep4d",
  "verify_url": "https://imnotahuman.ai/api/v1/verify"
}
Proof
{
  "challenge_id": "ch_mfr4q2xk7tbn3ycz5w6ah2ep4d",
  "agent_id": "agent_nova_8f2a",
  "key_id": "key_b7n2xq4mfc3rtw6y",
  "signature": "0IKKR9d3yZ4MIdTuKMNO99q-fF8kC5kp1Vak61hrQb1TEBhlzCDtkZxq7Ho1m5IjetPefqSAbrkDrHnueQhlCw",
  "created": 1789905607
}
Result
{
  "verified": true,
  "status": "VERIFIED",
  "subject_type": "agent",
  "mode": "live",
  "agent": { "id": "agent_nova_8f2a", "name": "Nova" },
  "verification": {
    "method": "ed25519_challenge",
    "verified_at": "2026-09-20T12:00:07.412Z",
    "challenge_id": "ch_mfr4q2xk7tbn3ycz5w6ah2ep4d",
    "origin": "https://example.com",
    "action": "checkout",
    "intent": "purchase"
  },
  "token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImluaC1...",
  "expires_at": "2026-09-20T12:10:07.000Z"
}

Components

ComponentStatusWhere
https://imnotahuman.ai/widget.jsImplementedEmbeddable widget, no dependencies
/api/v1ImplementedREST API: challenges, verify, tokens, management
/.well-known/jwks.jsonImplementedPublic keys for offline token verification
DashboardImplementedSites, agents, keys, events
@imnotahuman/agentNot on npmCLI is a single file at https://imnotahuman.ai/agent.mjs
@imnotahuman/serverNot on npmHosts call POST /api/v1/tokens/verify
@imnotahuman/reactNot on npmUse the widget.js script tag
Web Bot Auth providerExperimentalRFC 9421 HTTP Message Signatures with a Signature-Agent key directory
Not on npm

@imnotahuman/agent, @imnotahuman/react and @imnotahuman/server are private packages. They are not installed from npm. Use the script tag, the REST API, and the agent CLI at https://imnotahuman.ai/agent.mjs.

What is not included

There is no reputation scoring, no marketplace, no payments and no delegation of authorization. imnotahuman.ai answers one question per challenge and hands the answer to your site. Example ids in these docs (such as agent_nova_8f2a) are illustrative.