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
-
Pay. Your client asks the notary for a ticket and gets HTTP
402with 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. - 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.
- 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.
-
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. - 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.
| Tier | Request | Response | You connect CLI, MPC | Notary connects browser, proxy |
|---|---|---|---|---|
| S | ≤ 4 KiB | ≤ 1 MiB | 42 | 210 |
| M | ≤ 16 KiB | ≤ 2 MiB | 100 | 500 |
| L | ≤ 32 KiB | ≤ 2 MiB | 200 | 1 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
- https://mint.mountainlake.io
- https://21mint.me
- https://mint.coinos.io
- https://mint.minibits.cash/Bitcoin
- https://cashu.cz
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
- MPC-TLS needs a server that speaks TLS 1.2 (most do, alongside 1.3).
- The notary sees neither your request nor the response nor, with the CLI, the website's name. The browser bridge has to know the host it connects to; it forwards only encrypted bytes.
- The notary connects only to public internet addresses, port 443, a limited number of times per host per hour. It refuses private, local and its own operator's networks.
- Payments are ecash: the notary learns that a token was redeemed, not who paid. Tickets never appear in URLs; the web server's access log keeps IP addresses for abuse handling, without query strings.
- Keep the
.secretsfile private: anyone with it can build presentations of your session.