The verifiable identity protocol
for the internet.
HTTP shipped with authentication. It never shipped with proof. x401 is the protocol that completes the challenge layer of the web.
Identity negotiation for the agentic web.
HTTP shipped in the nineties with a way to challenge a caller for credentials: 401 Unauthorized, WWW-Authenticate. For thirty years, that was enough. Every system that needed to know who the caller really was wrote its own answer in the app layer.
That model assumed a person at a browser. The agent era breaks the assumption. Calls now come from workloads, autonomous agents, and delegated service identities. The route on the other end needs to know what the caller can prove, not just what token it carries. x401 makes that proof a first-class part of the protocol.
Read the full specWhat can x401 do?
Now agents can respond to an identity challenge on behalf of the person they serve.
Banking
Open an account with an identity that satisfies KYC and AML.
Step-up auth
Change wire instructions, require additional proof not just a login.
Prescriptions
Refill a script tied to a verified patient identity, not typed in SSNs.
Organization Credentials
Verify an active board association before joining a meeting.
Age gate
Place a bet by answering “over 18”. No DOB ever leaves the wallet.
Ticketing
Sell concert tickets to people, not bots, with proof of personhood.
Travel
Request identity and a passport when booking travel.
See all demos
Try each scenario against a real 401 challenge.
A curated registry, not a research project.
x401 can ask for any claim. The registry curates the issuers the industry agrees to accept, so when a route demands proof there's already a trusted source for it. The same protocol works for age, identity, license, employment, or ownership. One handshake. Proof for anything.
When an agent makes a request that requires ID.
Four steps between the request and the response.
Proof requirement
The route says no, and says why. The response carries the proof requirement in the PROOF-REQUEST header: a complete credential request the verifier composed and signed — which credentials, which claims, which issuers.
Credential result
The agent doesn't build a request; it runs the verifier's. Natively via navigator.credentials.get(), relayed unchanged to a credential manager, or fulfilled remotely. The result comes back bound to the verifier.
Retry with proof
The agent packages the result as a Result Artifact and retries the route with the PROOF-RESPONSE header. The verifier checks four things: nonce match, verifier binding, credential satisfaction, issuer trust.
Token exchange
The agent trades the Result Artifact for a short-lived Bearer Verification Token. Every request after this one skips the proof step entirely.
On the wire.
A verifier returns 401 with a base64url-encoded x401 payload carrying a signed credential request. The agent decodes it, gets the request fulfilled by a credential manager, and retries with the result. The entire handshake runs over plain HTTP request and response headers.
HTTP/1.1 401 Unauthorized
PROOF-REQUEST: eyJzY2hlbWUiOiJ4NDAxIiwidmVyc2lvbiI6IjAuMi4wIi...
Cache-Control: no-store{
"scheme": "x401",
"version": "0.2.0",
"credential_requirements": {
"digital": {
"requests": [{
"protocol": "openid4vp-v1-signed",
"data": {
"request": "eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWF1dGh6LXJlcStqd3QifQ..."
}
}]
}
},
"oauth": { "token_endpoint": "https://research.example.com/oauth/token" },
"request_id": "proof-template-board-certified-doctor-v1",
"satisfied_requirements": ["urn:example:x401:satisfaction:board-certified-doctor:v1"]
}{
"response_type": "vp_token",
"response_mode": "dc_api",
"client_id": "x509_san_dns:research.example.com",
"expected_origins": ["https://research.example.com"],
"nonce": "uX7Vq3mZJH6MeN0qz2L7SQ",
"dcql_query": {
"credentials": [{
"id": "board_certification",
"format": "jwt_vc_json",
"meta": { "type_values": ["BoardCertificationCredential"] },
"claims": [
{ "path": ["credentialSubject", "boardCertification", "status"], "values": ["active"] }
],
"trusted_authorities": [
{ "type": "openid_federation", "values": ["https://trusted-issuer.example"] }
]
}]
},
"exp": 1746557100
}import { fetchWithX401 } from "@x401/client";
const res = await fetchWithX401("https://research.example.com/papers/medical-study-123", {
// The verifier composed and signed the request; the agent only gets it fulfilled.
// Invoke it natively, or relay payload.credential_requirements to a credential manager.
obtainResult: (payload) => navigator.credentials.get(payload.credential_requirements),
tokenExchange: true, // optional: trade the Result Artifact for a Bearer token
});
// Auto-handles: decode PROOF-REQUEST → obtain { protocol, data } →
// package Result Artifact → retry with PROOF-RESPONSE.
console.log(await res.json());GET /papers/medical-study-123 HTTP/1.1
Host: research.example.com
PROOF-RESPONSE: eyJyZXF1ZXN0X2lkIjoicHJvb2YtdGVtcGxhdGUtYm9hcmQtY2VydGlmaWVk...It composes. It doesn't compete.
x401 is a response format. It carries existing credential standards into a single HTTP challenge, so a route can declare its proof requirement. No new stack to invent.
x401 + x402.
Two protocols. One boundary. x402 lets agents pay. x401 lets agents prove who's paying. Stack the two and a single HTTP exchange handles every regulated payment flow on the web. KYC'd onboarding. Travel Rule transfers. Age-gated commerce. Sanctions screening. Anywhere money has to know your name.
Who are you?
The route asks the agent to reveal identity, organizational membership, or another credential. The agent presents a verifiable credential, the verifier validates it, the route opens.
HTTP/1.1 401 Unauthorized PROOF-REQUEST: <base64url-x401-payload>
Can you pay?
The route asks the agent to settle a payment. The agent presents a payment artifact, the verifier confirms it, the route opens.
HTTP/1.1 402 Payment Required Payment-Required: payment-object
Run them in sequence: prove first, then pay. Run them in parallel: both required, in any order. Or use either on its own. Neither artifact is accepted as the other.
Meet the creators
x401 is built in the open by Proof and a group of contributors from across the identity ecosystem. Want to talk through your use case, collaborate on the spec, or just say hello? The team would love to hear from you.