> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browserbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Human verification with AgentKit

> Prove your agent is human-backed to unlock Verified browsers on x402 sessions.

When you pay for a browser session via x402, you get a standard browser by default. To unlock [Verified browsers](/platform/identity/verified-customization) — purpose-built Chromium recognized by bot protection partners — your agent needs to prove it's operating on behalf of a real human.

This is where [AgentKit](https://docs.world.org/agents/agent-kit) comes in. AgentKit provides cryptographic proof-of-humanity using the [World Chain](https://world.org/world-chain) network, so your agent can prove it's human-backed without revealing who that human is.

<Info>
  AgentKit human verification is only required for x402 sessions. If you're using the standard Browserbase SDK with API keys, verified browsers are available directly through your plan.
</Info>

## How it works

<Steps>
  <Step title="Register your wallet">
    Register your EVM wallet address in the [AgentBook](https://docs.world.org/agents/agent-kit) smart contract on World Chain. This is a one-time setup that links your wallet to a verified human identity.
  </Step>

  <Step title="Sign a proof header">
    Before each session request, your agent signs an [EIP-191](https://eips.ethereum.org/EIPS/eip-191) message proving it controls a registered wallet. The signed message includes the target URL, a nonce, and a short TTL for replay protection.
  </Step>

  <Step title="Send with your x402 payment">
    Include the signed proof as an `agentkit` HTTP header alongside your `X-PAYMENT` header. The gateway verifies the signature, checks AgentBook registration, and upgrades your session.
  </Step>

  <Step title="Get a premium browser">
    If verification succeeds, your session gets Browserbase's [Verified](/platform/identity/verified-customization) browser — purpose-built Chromium recognized by bot protection partners — the same premium feature available to Scale plan customers.
  </Step>
</Steps>

## Session behavior

| Scenario                                        | Browser      |
| ----------------------------------------------- | ------------ |
| x402 payment, no `agentkit` header              | Standard     |
| x402 payment, invalid or expired proof          | Standard     |
| x402 payment, valid proof from registered human | **Verified** |

The gateway never returns an error for missing or invalid proofs — it silently falls back to a standard browser. Your agent always gets a working session.

## Setup

### 1. Install dependencies

```bash theme={null}
npm install @worldcoin/agentkit viem
```

### 2. Register in AgentBook

You need a wallet registered in [AgentBook](https://docs.world.org/agents/agent-kit) on World Chain. Registration requires the wallet holder to be a verified human (Orb-verified via World App).

```bash theme={null}
npx @worldcoin/agentkit-cli register <your-wallet-address>
```

<Note>
  Registration is a one-time on-chain transaction on World Chain (chain ID `eip155:480`). Once registered, any agent signing with this wallet's private key can prove human backing.
</Note>

### 3. Sign the AgentKit header

Your agent signs a [SIWE](https://eips.ethereum.org/EIPS/eip-4361)-formatted message before each request:

```typescript theme={null}
import { privateKeyToAccount } from "viem/accounts";
import { formatSIWEMessage } from "@worldcoin/agentkit";
import { randomBytes } from "crypto";

const account = privateKeyToAccount(process.env.AGENTKIT_PRIVATE_KEY as `0x${string}`);

async function signAgentkitHeader(url: string): Promise<string> {
  const parsed = new URL(url);
  const now = new Date();
  const expiry = new Date(now.getTime() + 5 * 60 * 1000); // 5-minute TTL

  const info = {
    domain: parsed.host,
    uri: url,
    version: "1" as const,
    nonce: randomBytes(16).toString("hex"),
    issuedAt: now.toISOString(),
    expirationTime: expiry.toISOString(),
    chainId: "eip155:480", // World Chain
    type: "eip191" as const,
    statement: "Verify your agent is backed by a real human",
  };

  const message = formatSIWEMessage(info, account.address);
  const signature = await account.signMessage({ message });

  const payload = { ...info, address: account.address, signature };
  return Buffer.from(JSON.stringify(payload)).toString("base64");
}
```

### 4. Create a verified x402 session

Combine the `agentkit` header with your x402 payment:

```typescript theme={null}
import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";

const walletAccount = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const x402Fetch = wrapFetchWithPayment(fetch, walletAccount);

const url = "https://x402.browserbase.com/browser/session/create";

// Sign the AgentKit proof
const agentkitHeader = await signAgentkitHeader(url);

// Create session with both payment and human verification
const session = await x402Fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "agentkit": agentkitHeader,
  },
  body: JSON.stringify({ estimatedMinutes: 30 }),
}).then((r) => r.json());

console.log(session.connectUrl); // Verified browser session
```

<Tip>
  The same wallet can be used for both x402 payments (USDC on Base) and AgentKit signing (identity on World Chain). They serve different purposes — payment vs. identity — but can share a key pair for convenience.
</Tip>

## Server-side verification

The x402 gateway verifies AgentKit proofs in four steps:

1. **Decode** — Base64-decode the `agentkit` header and parse the JSON payload
2. **Validate** — Check the SIWE message fields, TTL (must not be expired), and target URI
3. **Recover** — ECRECOVER the signer's address from the EIP-191 signature
4. **Lookup** — Query the AgentBook contract on World Chain (`eip155:480`) to confirm the address belongs to a registered human

If any step fails, the gateway logs the reason and falls back to a standard browser. No error is returned to the client.

## FAQ

<AccordionGroup>
  <Accordion title="Do I need to be Orb-verified?">
    Yes. AgentBook registration requires the wallet holder to be verified through World App's Orb verification. This is what makes the proof meaningful — it's not just a wallet, it's a wallet linked to a unique human.
  </Accordion>

  <Accordion title="Can I use different wallets for payment and identity?">
    Yes. The x402 payment wallet (USDC on Base) and the AgentKit signing wallet (registered on World Chain) are independent. You can use the same wallet for both or separate them.
  </Accordion>

  <Accordion title="What happens if my proof expires mid-session?">
    Nothing. The AgentKit proof is only checked at session creation time. Once your session is created as Verified, it stays that way for the session's lifetime.
  </Accordion>

  <Accordion title="Is my identity revealed to websites I visit?">
    No. The AgentKit proof is between your agent and the x402 gateway. Websites see a Verified Browserbase browser — they don't see your wallet address or World ID.
  </Accordion>

  <Accordion title="What if I don't include the agentkit header?">
    You still get a working browser session (you paid for it via x402). It just won't have Verified browser fingerprints. The gateway never rejects a paid request over a missing proof.
  </Accordion>
</AccordionGroup>

## Further reading

<CardGroup cols={3}>
  <Card title="x402 Quickstart" icon="rocket" href="/integrations/x402/quickstart">
    Set up x402 payments for browser sessions
  </Card>

  <Card title="AgentKit" icon="globe" href="https://docs.world.org/agents/agent-kit">
    AgentKit SDK documentation
  </Card>

  <Card title="Agent Identity" icon="shield-check" href="/platform/identity/overview">
    How Browserbase handles agent authentication
  </Card>
</CardGroup>
