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:
- Install in observation mode. Proof of Actor changes nothing. Your allowlist keeps working.
- Compare. For each route, see which allowlisted requests carry verified evidence, which carry only a declaration, and which end up Unknown.
- Preview policies. Draft a policy that treats verified agents, declared agents and Unknown differently, and preview its effect on real traffic.
- Enforce route by route. Start with the routes where a spoofed name would matter most.
- 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.