Skip to main content
COMPARISON

Proof of Actor vs user agent allowlists: a name is a claim, not proof

Allowlisting by User-Agent string is quick to set up and easy to understand. It is also easy to fool, because the header is whatever the client chooses to send. Here is what a user agent allowlist actually tells you, where network checks help, and how Proof of Actor separates declarations from verified evidence.

Toshendra Sharma

By Toshendra SharmaFounder & CEO, AgentCredia · Updated November 13, 2026

The user agent allowlist is one of the oldest patterns on the web. You keep a list of crawler and client names you trust. When a request arrives with a matching User-Agent header, you let it through, skip a challenge, or serve it a lighter page. It takes minutes to set up and everyone on the team understands it.

The pattern made more sense when the main automated visitors were a handful of search crawlers and a few monitoring tools. Today, AI agents, assistants and automated clients reach applications in growing numbers, and many of them announce a name. Some of those names are real. Some are copied. The header cannot tell you which.

Proof of Actor takes a different approach. It treats a User-Agent string as what it is, a declaration, and reports it alongside stronger evidence when that evidence exists. This page explains the limits of allowlisting by name, where network-level checks help, and how verified signatures and an explicit Unknown class change the picture.

The short version

User agent allowlist Proof of Actor
Main evidence A name in the User-Agent header Signatures, declarations and signals, each labeled with its basis
Can a client fake it? Yes, by sending the same string A declared basis can be claimed; a verified basis requires the signing key
Output On the list or not Human, Human + AI, Agent or Unknown, plus a basis
Unclear traffic Treated as not allowlisted, or allowed by default Unknown, with a fallback you choose per route
AI-assisted people Invisible; they use ordinary browsers A distinct class, Human + AI, when declared or observed
Maintenance Manual list updates as names change Keys published by agent operators; policies in your code
Default on install Whatever the list allows Observation; nothing changes until you add a policy
Best at Cheap routing of well-behaved, known clients Evidence-based actor context for product and policy decisions

The rest of the page explains each row.

Why allowlisting by User-Agent is spoofable

The User-Agent header is set by the client. A browser sets it, a script sets it, and an agent framework sets it. Nothing in HTTP checks that the value is true. If your allowlist trusts a string, anyone who copies that string gets the same treatment.

This is called user agent spoofing, and it is common for a simple reason: it costs nothing. A scraper that wants to avoid a challenge only needs to borrow the name of a crawler you trust. A misbehaving client can claim to be a popular assistant. A legitimate tool can even send a generic browser string because a library default did it.

The result is that a user agent allowlist has two failure modes:

  • False trust: an untrusted client claims a trusted name and passes.
  • False doubt: a legitimate client sends an unexpected or generic string and fails.

Neither failure is visible from the header alone. That is the core limitation, and no amount of list maintenance removes it.

What the header is still good for

None of this means you should ignore User-Agent strings. Well-behaved crawlers and agents announce themselves honestly, and the name is a useful hint for routing, analytics and debugging. It tells you what a client says it is.

The right place for that information is as a declaration, weighed alongside other evidence, not as a key that unlocks access on its own. Proof of Actor records it exactly that way.

Reverse DNS and IP lists: partial measures

Many teams strengthen an allowlist with network checks. They help, and they are worth understanding precisely.

Reverse DNS verification

Some crawler operators document a verification process: look up the hostname for the request's IP address, check that it belongs to the operator's domain, then look up that hostname and confirm it resolves back to the same IP. When this round trip succeeds, you have real evidence that the request came from the operator's infrastructure.

The limits are practical. It only works for operators that document and support it. It adds DNS lookups that you need to cache. And it tells you about the network, not about which product or agent made the request on that network.

Published IP ranges

Other operators publish the IP ranges their automated clients use. Matching a request against those ranges is fast and gives similar evidence to reverse DNS. There is ongoing IETF discussion on a standard format for publishing these ranges, but as of November 2026 there is no settled standard, and coverage depends on each operator choosing to publish.

IP evidence also weakens as more agents run on shared cloud infrastructure, behind proxies, or from a user's own device. A cloud address can host many unrelated clients, and an agent acting from a person's browser looks like that person's network.

What network checks add up to

Reverse DNS and IP lists turn some declarations into something stronger for a subset of well-known operators. They do not cover the long tail of agents and tools, and they do not help at all with people working alongside AI. They are partial measures: worth using, not enough on their own.

Signatures versus declarations

The stronger form of evidence is a cryptographic signature. With HTTP Message Signatures, defined in RFC 9421, a client signs selected parts of each request with a private key. The verifier fetches the operator's published public key and checks the signature. If it verifies, the request was signed by the holder of that key, and the signed parts were not altered on the way.

The IETF Web Bot Auth working group is standardizing how automated clients use these signatures and how they publish their keys. Our explainer on Web Bot Auth for product teams covers the current status.

Proof of Actor uses a valid signature as verified evidence. A User-Agent string, a client hint or a self-description in a request body counts as declared. Behavioral and contextual signals count as inferred, and are labeled that way. Every result states which basis it rests on, so your team never confuses a claim with a check. See the evidence basis entry for the full definitions.

One limit applies even to verified evidence. A valid signature proves which key signed the request. It does not prove the agent is allowed to do what it is asking to do. That is an agent authorization question, and it stays in your application.

Handling Unknown instead of guessing

An allowlist forces every request into one of two buckets: on the list or not. In practice that means unclear traffic gets whatever your default is, and the default is usually chosen once for the whole site.

Proof of Actor treats Unknown as a first-class result. When the evidence does not support a reliable determination, it says so instead of guessing. Your policies then decide what Unknown means on each route:

  • On public documentation or marketing pages, allow it.
  • On search or listing endpoints, allow it with your normal rate limits.
  • On account changes, keep your existing checks.
  • On high-impact actions, send it to review or ask for a stronger signal.

The guide on handling Unknown traffic and the unknown classification entry walk through the patterns. Tracking your Unknown rate over time also tells you how much of your traffic still rests on weak evidence.

What about AI-assisted people?

A user agent allowlist has nothing to say about a person who uses an AI assistant inside an ordinary browser. Their User-Agent is a normal browser string. Yet many products want to recognize that interaction, for example to label AI-drafted submissions or understand how AI-assisted users move through onboarding.

Proof of Actor reports these interactions as Human + AI when the assistance is declared or observed through a supported integration. It does not guess from writing style alone. Read more in AI-assisted interaction.

Moving from an allowlist to evidence-based policies

You do not need to remove your allowlist on day one. A safe path looks like this:

  1. Install in observation mode. Proof of Actor changes nothing. Your allowlist keeps working.
  2. Compare. For each route, see which allowlisted requests carry verified evidence, which carry only a declaration, and which end up Unknown.
  3. Preview policies. Draft a policy that treats verified agents, declared agents and Unknown differently, and preview its effect on real traffic.
  4. Enforce route by route. Start with the routes where a spoofed name would matter most.
  5. Keep the allowlist as a hint. Names remain useful for routing and analytics, now with their basis visible.

The guide on rolling out actor-aware policies safely covers each step, and verified automated requests explains how signed clients fit in.

When an allowlist is enough

For low-stakes routing, such as serving a lighter page to a known crawler on public content, a user agent allowlist is often fine. The cost of a spoofed name is small.

When the decision has consequences, such as skipping a challenge, exposing richer data, or allowing a write, you want evidence you can check. That is where Proof of Actor belongs, working alongside the network checks and edge controls you already run.

Get started

Proof of Actor is in private beta. Selected founding developer teams can receive up to 12 months of free access within agreed usage limits, with no automatic billing. Apply for early access and tell us which clients you allowlist today and which routes you want to protect with better evidence.

FOR DEVELOPERS

What your code receives

Every interaction resolves to one result record. Your application reads the class and the basis and applies its own policy.

Result record
{
  "route": "GET /api/v1/catalog",
  "class": "agent",
  "basis": "verified",
  "evidence": [
    { "signal": "http_message_signature", "result": "valid", "keyid": "assistant.example" },
    { "signal": "client_declaration", "value": "assistant.example" }
  ],
  "observed_at": "2026-11-13T10:42:07Z"
}
class
Human, Human + AI, Agent or Unknown.
basis
How strong the evidence is: verified, declared, inferred or unknown.
evidence
The signals behind the result, so your team can see why.

Start in observation mode: record results next to your logs and change nothing until you choose a policy. Read the Node.js integration guide

Frequently asked questions

Is a user agent allowlist useless?

No. It is a useful declaration from well-behaved clients and a cheap way to route known crawlers. The problem is treating it as proof. Any client can send any User-Agent string, so an allowlist alone should never unlock sensitive actions.

Does reverse DNS verification fix User-Agent spoofing?

It helps for operators that document it. A reverse lookup followed by a matching forward lookup ties an IP address to the operator's domain. It only works for operators that support it, and it says nothing about traffic from shared cloud or residential addresses.

How does Proof of Actor treat the User-Agent header?

As a declaration. It contributes to the result with a declared basis, never a verified one. A verified basis requires evidence such as an HTTP Message Signature checked against a published key.

What does a verified signature prove?

It proves which key signed the request and that the signed parts were not changed. It does not prove the agent is authorized to perform the action. Authorization stays in your application.

What happens to clients that claim to be a known agent but cannot be verified?

Proof of Actor reports what the evidence supports, often a declared or inferred result, or Unknown. Your policy chooses the fallback for that route instead of trusting the claimed name.

Will adding Proof of Actor change my current allowlist behavior?

No. It starts in observation mode. You can compare its results with your allowlist decisions on real traffic before changing anything.

Know who's using your app.

Private beta for a small group of founding developers.

Prefer to talk first? Talk to the founders