TLSNotary · Cashu

Prove what a website told you.

This is a public TLSNotary notary. You fetch a page over HTTPS as you normally would; the notary takes part in the TLS session without seeing it and signs an attestation. You then show anyone the part you choose (one field of a JSON response, a single line of a page) with proof that the server really sent it.

Each session is paid with Cashu ecash, so you do not need an account.

How it works

  1. Pay. Your client asks the notary for a ticket and gets HTTP 402 with a Cashu payment request. It pays with an ecash token from one of the accepted mints and receives a ticket, good for 3 attempts within 30 minutes.
  2. Connect. Your client opens the TLS connection to the website. The TLS keys are split between you and the notary by multi-party computation (MPC-TLS): only you can read the traffic, and you cannot forge it alone. Your client checks the server's certificate as a browser would.
  3. Attest. When the request is done, the notary signs an attestation: commitments to the encrypted transcript, the server's identity and the time. The notary learns neither the request, the response nor the site's name.
  4. Present. From the attestation and your local secrets you build a presentation that reveals only the bytes you choose. Everything else stays hidden and shows as X.
  5. Verify. Anyone who trusts the notary's key verifies the presentation offline: the server name and its certificate chain, the time, and the revealed bytes. No call to the notary or the website is needed.

The notary runs upstream TLSNotary tlsn v0.1.0-alpha.15 unchanged, wrapped with payment, limits and an egress policy. Upstream no longer ships a notary server; this is one.

Notarize a page

In the browser

The web app runs the whole prover in WebAssembly in your browser: enter a URL and optional headers (an API token, for example), paste a Cashu token, and download a presentation. A web page cannot reach a website by raw TCP, so the browser's connection goes through the notary's bridge, which forwards only encrypted TLS bytes. That counts as notary egress and costs more (see prices).

Pages you are logged in to need your cookies, which a web page cannot read. For those, use the browser extension: it notarizes the tab you are on (with its cookies, if you allow it for that site) and carries its own small Cashu wallet with balance, history and a 12-word backup. Download it for Chrome, Brave or Edge, unzip, and load the folder in chrome://extensions with Developer mode on (“Load unpacked”). Details.

Command line: tlsnc

The CLI connects to the website itself, so the notary never touches the target. It is the cheapest way and the one to use from scripts and agents. It has a Cashu wallet built in.

# install (Linux x86_64, macOS arm64) into ~/.local/bin
curl -fsSL https://tlsn.cypherpunk.today/install.sh | sh
# or build it: cargo install --locked --git https://github.com/jooray/tlsnotary-cashu tlsnc

tlsnc receive 500                 # Lightning: prints an invoice (and a QR code), waits for payment
tlsnc receive cashuB…             # or receive a Cashu token you already have
tlsnc balance

tlsnc notarize https://httpbin.org/json            # pays the ticket, writes notarized.attestation + .secrets
tlsnc present --json slideshow.author              # reveal one JSON field, writes notarized.presentation
tlsnc verify notarized.presentation                # checks it against this notary's published keys

Headers and bodies work like curl: -H 'Authorization: Bearer …', -X POST -d '…'. Authorization, Cookie and similar headers are never revealed unless you pass --allow-credentials. tlsnc backup prints the wallet's 12 words; tlsnc restore "…" brings the funds back on another machine.

From your own code

Rust: tlsnc-client (prover and presentations) and tlsnc-verify. JavaScript: @tlsnc/client (pay, notarize, present in the browser) and @tlsnc/verify (verification only, 600 KB of WebAssembly, works in Node and in any page). See the README.

Paying with Cashu

Prices are per session, in sat. They are high on purpose: the notary is not a cheap proxy, and a VPN is cheaper. Who opens the connection to the website decides the column.

TierRequestResponseYou connect
CLI, MPC
Notary connects
browser, proxy
S≤ 4 KiB≤ 1 MiB42210
M≤ 16 KiB≤ 2 MiB100500
L≤ 32 KiB≤ 2 MiB2001 000

The request limit is what you send (URL, headers, body); responses are cheap to notarize. A ticket allows 3 attempts: a failed session is retried with the same ticket, not refunded. Mint fees are on the payer.

Accepted mints

Get ecash from any of them with tlsnc receive <amount> (pay the Lightning invoice it prints), or with any Cashu wallet (Minibits, cashu.me, …) set to one of these mints, then send yourself a token.

The protocol

Tickets are sold over plain HTTP following NUT-24 (HTTP 402 with an X-Cashu header carrying a NUT-18 payment request):

POST /v1/tickets?tier=S&egress=client
→ 402 Payment Required
  X-Cashu: creqA…            # amount (net of mint fees), unit sat, accepted mints

POST /v1/tickets?tier=S&egress=client
X-Cashu: cashuB…             # a token from one of those mints, at least the amount plus input fees
→ 200 {"ticket":"tk_…","expires_at":…,"attempts":3,"tier":{…},"egress":"client","received":42}

GET /v1/notarize             # WebSocket; the ticket rides in the subprotocol header
Sec-WebSocket-Protocol: tlsnc, tlsnc.tk_…

Over that WebSocket runs an unmodified tlsn session, followed by one length-prefixed frame each way: the attestation request and the signed attestation. A token that is worth too little is returned as a refund token in the 400 response. POST /v1/tickets/status (body {"ticket":"tk_…"}) tells why a session was refused. Full description: DESIGN.md.

Verifying

A presentation is only as good as the notary key you trust. This notary's keys are published at /.well-known/tlsnc-notary.json; pin the key rather than fetching it each time.

see /.well-known/tlsnc-notary.json

Verify with tlsnc verify, with @tlsnc/verify in a page or in Node, or in the web app. Verification checks the signature, the server certificate against the Mozilla roots, and that the revealed bytes match the attested transcript.

Limits and privacy