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

# Web Bot Auth

> Sign a session's requests with Web Bot Auth, and identify and verify the requests Hyperbrowser signs

Hyperbrowser runs cloud browsers that AI agents and automation tools use to browse the web. A session can sign the requests its browser makes with Web Bot Auth, so websites can verify that the requests come through Hyperbrowser.

Signing follows [Web Bot Auth](https://datatracker.ietf.org/doc/draft-ietf-webbotauth-httpsig-protocol/), which builds on [HTTP Message Signatures (RFC 9421)](https://www.rfc-editor.org/rfc/rfc9421).

## Get access

Web Bot Auth is enabled for Hyperbrowser teams on request. If you use Hyperbrowser and want your sessions to sign their requests, contact us at [info@hyperbrowser.ai](mailto:info@hyperbrowser.ai).

If a site still blocks a session that signs its requests, email us the URL and the session ID.

## Sign a session's requests

Set `webBotAuth` when you create a session, and the session signs its HTTPS requests:

<CodeGroup>
  ```typescript Node.js theme={null}
  import { Hyperbrowser } from "@hyperbrowser/sdk";

  const client = new Hyperbrowser({ apiKey: process.env.HYPERBROWSER_API_KEY });

  const session = await client.sessions.create({ webBotAuth: true });
  console.log(session.launchState?.webBotAuth?.signatureAgent); // https://www.hyperbrowser.ai
  ```

  ```python Python theme={null}
  import os
  from hyperbrowser import Hyperbrowser

  client = Hyperbrowser(api_key=os.environ["HYPERBROWSER_API_KEY"])

  session = client.sessions.create({"web_bot_auth": True})
  print(session.launch_state.web_bot_auth.signature_agent)  # https://www.hyperbrowser.ai
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/session \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"webBotAuth": true}'
  ```
</CodeGroup>

To sign only requests to some sites, pass `onlyDomains` (`only_domains` in Python). Each hostname also covers its subdomains, so `example.com` covers `shop.example.com`. You can list up to 50 hostnames, without a scheme, port, or path.

<CodeGroup>
  ```typescript Node.js theme={null}
  const session = await client.sessions.create({
    webBotAuth: { onlyDomains: ["example.com"] },
  });
  ```

  ```python Python theme={null}
  session = client.sessions.create({"web_bot_auth": {"only_domains": ["example.com"]}})
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/session \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"webBotAuth": {"onlyDomains": ["example.com"]}}'
  ```
</CodeGroup>

Agent tasks accept the same option in `sessionOptions` (`session_options` in Python). An agent task that runs in an existing session (`sessionId`) keeps that session's setting. Scrape, crawl, and extract requests don't accept `webBotAuth`.

### Requirements and errors

A session that asks for Web Bot Auth is either signed or refused; it never starts unsigned. You can't take a snapshot of a session that signs its requests.

| Status | Cause |
| - | - |
| `400` | `webBotAuth` is combined with `useUltraStealth` or `startFromSnapshot`, an `onlyDomains` entry isn't a hostname, the request is a scrape, crawl, or extract, or another session option can't be combined with it |
| `403` | Web Bot Auth isn't enabled for your team |
| `503` | Signing is temporarily unavailable. Retry after a few seconds |

The rest of this page is for website operators: it explains how to identify and verify the requests that Hyperbrowser signs.

## Identify signed requests

A signed request carries three headers:

```http theme={null}
Signature-Agent: "https://www.hyperbrowser.ai"
Signature-Input: sig1=("@authority" "signature-agent");created=1735689600;keyid="<key id>";alg="ed25519";expires=1735689720;tag="web-bot-auth"
Signature: sig1=:<signature>:
```

* `Signature-Agent` names the signer. For Hyperbrowser it is always `"https://www.hyperbrowser.ai"`.
* `Signature-Input` lists what is signed: the host the request is sent to (`@authority`) and the `Signature-Agent` header. `tag="web-bot-auth"` marks it as a Web Bot Auth signature, and `keyid` names the key that made it.
* `Signature` holds the Ed25519 signature.

<Warning>
  Anyone can send a `Signature-Agent` header. A request comes through Hyperbrowser only if its signature verifies against a key in the Hyperbrowser key directory.
</Warning>

Signed requests come from real browsers and usually carry a standard browser `User-Agent`, so identify them by their signature rather than by `User-Agent`.

## Verify a signature

Hyperbrowser publishes its public keys in a key directory:

```bash theme={null}
curl https://www.hyperbrowser.ai/.well-known/http-message-signatures-directory
```

The response is a JSON Web Key Set of Ed25519 keys:

```json theme={null}
{"keys":[{"kty":"OKP","crv":"Ed25519","kid":"<key id>","x":"<public key>","use":"sig"}]}
```

Each key's `kid` is its JWK thumbprint ([RFC 7638](https://www.rfc-editor.org/rfc/rfc7638)) and matches the `keyid` in `Signature-Input`. Every key also signs the directory response itself, which proves that Hyperbrowser holds the matching private keys.

To verify a request:

1. Check that `Signature-Agent` is `"https://www.hyperbrowser.ai"` and fetch the key directory above.
2. Check that `Signature-Input` has `tag="web-bot-auth"` and that the current time is between `created` and `expires`.
3. Find the key whose `kid` matches the `keyid`.
4. Rebuild the signature base from the covered components as RFC 9421 defines, and verify `Signature` against it with that key.

Cloudflare publishes open source [Web Bot Auth implementations](https://github.com/cloudflare/web-bot-auth) that you can use instead of writing the verification yourself.

<Note>
  Keys can change. Fetch the key directory instead of hard-coding keys, and cache it according to its `Cache-Control` header.
</Note>

## What a signature tells you

A valid signature tells you that Hyperbrowser signed the request for your host, and that the signature is within its validity window (between `created` and `expires`). It does not:

* Identify which Hyperbrowser customer sent the request.
* Grant the request any access. What you allow is up to you.
* Stop the same signature from being reused for other requests to your host until it expires. It covers your host and the `Signature-Agent` header, not the full request.

## Allow or block Hyperbrowser

* If you use a bot management provider that supports Web Bot Auth, such as [Cloudflare](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/), use its bot rules to allow or block Hyperbrowser.
* On your own infrastructure, verify the signature as described above, then allow or block requests whose `Signature-Agent` is `"https://www.hyperbrowser.ai"`.

## Troubleshooting

If signatures from Hyperbrowser don't verify:

* Check that no proxy, load balancer, or CDN in front of your server removes or rewrites the `Signature`, `Signature-Input`, or `Signature-Agent` headers.
* Check that your server's clock is accurate. Verification compares the current time with `created` and `expires`.

## Report a problem

If traffic from Hyperbrowser causes problems for your site, contact us at [info@hyperbrowser.ai](mailto:info@hyperbrowser.ai). Include the affected domain, when the requests happened, and the `Signature-Input` headers if you logged them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.