Oblivious HTTP
ActiveOblivious 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.
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
| Field | Size | Description |
|---|---|---|
| Architecture | 3 parties | Client, Relay, Gateway (+ Target). Client encrypts for Gateway. Relay forwards without decrypting. Gateway decrypts, forwards to Target. Neither Relay nor Gateway alone can deanonymize. |
| Encryption | HPKE (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 request | Binary HTTP (RFC 9292) | The actual HTTP request is encoded as Binary HTTP (bhttp) inside the OHTTP encapsulation. Any HTTP method/path/headers/body. |
| Key configuration | application/ohttp-keys | Gateway publishes its HPKE public key as application/ohttp-keys. Clients fetch it before sending requests. Key IDs enable rotation without downtime. |
| OHTTP request | application/ohttp-req | Content-Type for the outer encrypted request sent to the relay: application/ohttp-req. |
| OHTTP response | application/ohttp-res | Content-Type for the encrypted response from the gateway back through the relay: application/ohttp-res. |
| DNS discovery | RFC 9540 | SVCB/HTTPS DNS records can advertise OHTTP gateway availability. Clients can discover OHTTP support automatically from DNS. |
| Deployments | Apple, Cloudflare, Google | Apple 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
# 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]# 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), ...]