v154 · privacy · anti-fraud

Proving you are a person, without saying which one

Automated traffic is answered with friction: a puzzle, a challenge, an interstitial. It falls hardest on the people least able to look normal — private browsing, an unusual network, an assistive setup. A verification token lets a site that has already decided you are a person say so to another site, carrying almost no information beyond that.

concepts

  1. What is already here

    Private State Tokens are the shipping relative of this proposal, and both of their document methods are callable right now. Call them for real against valid and invalid issuers and read what comes back.

  2. The request option, validated

    fetch carries token operations in an options-bag member. Which operations and versions it accepts is measurable without a token or an issuer, and the rejections are specific.

  3. The friction it replaces

    Solve a challenge, and the page times you. Then time the token check. The gap is not the argument on its own — who bears it is — and the page makes both halves concrete.

why it shipped

A site that suspects automation has two options: let it through, or make everyone prove themselves. The second is the common choice and its cost is unevenly distributed — a user in a private window, on a VPN, with an ad blocker, or using a screen reader looks more like a bot to most heuristics than a signed-in user on a residential connection does, and is asked to prove themselves more often.

Private Verification Tokens move the proof rather than repeating it. A site that already knows you are a person issues a token; another site redeems it and skips its own challenge. The tokens are deliberately low-entropy, because a token that carried enough information to identify you would be a tracking cookie with better manners.

the API shape

// Ask whether this browser holds tokens from an issuer.
const has = await document.hasPrivateToken("https://issuer.example");

// Redeem one as part of a request.
await fetch("/protected", {
  privateToken: {
    version: 1,
    operation: "send-redemption-record",
    issuers: ["https://issuer.example"],
  },
});

enabling it now

Private Verification Tokens have no web-facing API on the Chrome 150 these pages were built with. What is here is Private State Tokens, the shipping mechanism this proposal builds on: document.hasPrivateToken and document.hasRedemptionRecord are functions, and fetch's privateToken option is read and validated. Measured: a valid https issuer resolves false, an insecure or malformed issuer rejects with a TypeError, and an unknown operation is rejected at the options-bag conversion.

await document.hasPrivateToken("https://issuer.example")  // false
await document.hasPrivateToken("http://insecure.example") // TypeError
new Request("/", { privateToken: { version: 1, operation: "bogus" } })
// TypeError: Failed to read the 'privateToken' property…

So these pages exercise the mechanism that exists and are explicit that the newer proposal is not part of what they measure.

references