Skip to main content
OHTTP

Oblivious HTTP

Active

Oblivious HTTP (RFC 9458) is an IETF privacy protocol that prevents a server from linking HTTP requests to the client that made them. A client encrypts requests using the gateway's public key (HPKE), sends them through a relay (which sees the client IP but not the content), and the gateway decrypts and forwards to the target (which sees the content but not the client IP). Neither relay nor gateway alone can link requests to a client identity.

OHTTPPrivacyRFC 9458HPKERelayiCloud2023

In one line

Oblivious HTTP (RFC 9458, July 2023) separates the knowledge of who is making a request from what the request contains. The client encrypts the HTTP request using HPKE (RFC 9180) with the gateway's public key, sends it to a relay (which knows the client IP but cannot decrypt), and the relay forwards to the gateway (which decrypts but never sees the client IP). Deployed in Apple iCloud Private Relay, Cloudflare OHTTP gateway, and Google Safe Browsing v5 for privacy-preserving telemetry.

Quick Reference

FieldSizeDescription
Architecture3 partiesClient, Relay, Gateway (+ Target). Client encrypts for Gateway. Relay forwards without decrypting. Gateway decrypts, forwards to Target. Neither Relay nor Gateway alone can deanonymize.
EncryptionHPKE (RFC 9180)Hybrid Public Key Encryption. Client uses Gateway's public key (fetched via key configuration) to encapsulate a symmetric key. Inner request encrypted with that key. Response encrypted back with an ephemeral key.
Inner requestBinary HTTP (RFC 9292)The actual HTTP request is encoded as Binary HTTP (bhttp) inside the OHTTP encapsulation. Any HTTP method/path/headers/body.
Key configurationapplication/ohttp-keysGateway publishes its HPKE public key as application/ohttp-keys. Clients fetch it before sending requests. Key IDs enable rotation without downtime.
OHTTP requestapplication/ohttp-reqContent-Type for the outer encrypted request sent to the relay: application/ohttp-req.
OHTTP responseapplication/ohttp-resContent-Type for the encrypted response from the gateway back through the relay: application/ohttp-res.
DNS discoveryRFC 9540SVCB/HTTPS DNS records can advertise OHTTP gateway availability. Clients can discover OHTTP support automatically from DNS.
DeploymentsApple, Cloudflare, GoogleApple iCloud Private Relay uses OHTTP for DNS queries and some Safari browsing. Cloudflare operates public OHTTP relay/gateway. Google Safe Browsing v5 uses OHTTP for privacy-preserving malware lookups.

Key Characteristics

Request unlinkability

The gateway cannot link two requests from the same client because it never sees the client IP. The relay cannot read request content because it is encrypted. The target sees the gateway's IP, not the client.

Not a VPN

OHTTP provides per-request unlinkability, not general traffic anonymization. The relay still sees which gateway you are using. Use Tor or a VPN if full traffic anonymization is needed.

Low overhead

HPKE encapsulation adds ~60–100 bytes of overhead per request. Response adds ~48 bytes. Suitable for telemetry, Safe Browsing lookups, and DNS queries.

Stateless gateway

The gateway is stateless – it processes each request independently with no session state. This makes OHTTP gateways easy to scale horizontally and cache-friendly.

Message Format

Request
http
# OHTTP request flow

# 1. Client fetches gateway key configuration
GET /.well-known/ohttp-gateway HTTP/1.1
Host: gateway.example.com
Accept: application/ohttp-keys

# 2. Client encapsulates inner request using HPKE
# Inner request (Binary HTTP, RFC 9292):
#   GET /api/check-url HTTP/1.1
#   Host: target.example.com
#   [body if POST]

# 3. Client sends encrypted outer request to relay
POST /relay HTTP/1.1
Host: relay.example.net
Content-Type: application/ohttp-req

[HPKE-encapsulated binary: key_id || kem_id || kdf_id || aead_id || enc || ciphertext]
Response
http
# 4. Relay forwards to gateway (strips client IP)
POST /gateway HTTP/1.1
Host: gateway.example.com
Content-Type: application/ohttp-req
[same ciphertext, no client IP]

# 5. Gateway decrypts, executes inner request, encrypts response
HTTP/1.1 200 OK
Content-Type: application/ohttp-res
[AEAD-encrypted response ciphertext]

# 6. Relay forwards response to client
# Client decrypts with key material from step 2

# OHTTP key configuration format (application/ohttp-keys)
# key_config_id (1 byte) || kem_id (2 bytes) ||
# public_key (kem-specific) ||
# symmetric_algorithms: [(kdf_id, aead_id), ...]

Implementations

linuxsince cloudflare/go-ohttp (Go), martinthomson/ohttp (Rust), google/chrome (C++ for Safe Browsing)available
macossince Apple iCloud Private Relay uses OHTTP for Safari DNS. WebKit OHTTP client built-in Safari 17+.built-in
windowssince Chrome Safe Browsing v5 (Windows). .NET OHTTP libraries available.available
iossince iCloud Private Relay. Safari iOS 17+ OHTTP.built-in
androidsince Chrome Android Safe Browsing v5 uses OHTTP.available