Non-Authoritative Information
ActiveHTTP 203 Non-Authoritative Information means the request succeeded but the enclosed payload has been modified by a transforming proxy from the origin server's original 200 response. Defined in RFC 9110 §15.3.4. The client is receiving transformed content — compressed, reformatted, translated, or filtered — not the origin's exact response.
Description
The 203 Non-Authoritative Information status code indicates that the request was successful but the enclosed payload has been modified from the origin server's 200 OK response by a transforming proxy. The proxy is transparently informing the client that the content it receives is NOT byte-for-byte what the origin server sent — something in the chain altered it.
This status exists because HTTP intermediaries (transparent proxies, CDN edge nodes, content-optimizing gateways) frequently modify responses in transit. They might compress images to WebP, minify HTML/CSS/JS, strip unnecessary headers, inject tracking scripts, translate content into a different language, or reformat data for mobile devices. When an intermediary does this AND wants to be honest about it, it returns 203 instead of 200.
The critical distinction from 200: a 200 response means the content is exactly what the origin server generated. A 203 response means an intermediary transformed it. The metadata (headers, content-type, content-length) might not match what the origin originally sent. Caches receiving a 203 should be aware that the stored representation is a transformation, not the canonical version.
In practice, 203 is rarely seen in the wild. Most transforming proxies silently return 200 after modifying content, because clients and applications almost never differentiate behavior based on 203 vs 200. The status code exists as a transparency mechanism — a way for honest intermediaries to signal that transformation occurred — but the ecosystem largely ignores it.
The original design intent was to allow clients to detect when response metadata (headers like Content-Type, Content-Language, Last-Modified) might not reflect the origin's actual values. A proxy that translates English content to French could signal this with 203, letting the client know that Content-Language: fr was set by the proxy, not the origin. Similarly, a proxy that strips Set-Cookie headers or modifies Cache-Control directives could use 203 to indicate the headers are non-authoritative.
Examples
GET /images/hero.png HTTP/1.1
Host: www.example.com
Accept: image/webp, image/png, image/*
Via: 1.1 optimize-proxy.cdn.netHTTP/1.1 203 Non-Authoritative Information
Content-Type: image/webp
Content-Length: 24580
Via: 1.1 optimize-proxy.cdn.net
Warning: 214 optimize-proxy.cdn.net "Transformation applied"
X-Original-Content-Type: image/png
X-Original-Content-Length: 89120
[WebP binary data]GET /page/article HTTP/1.1
Host: www.example.com
Accept: text/html
Accept-Encoding: gzip, deflate, brHTTP/1.1 203 Non-Authoritative Information
Content-Type: text/html; charset=utf-8
Content-Length: 4210
Via: 1.1 minifier.edge.net
X-Transform: html-minify, comment-strip, whitespace-collapse
X-Original-Content-Length: 7890
<!doctype html><html><head><title>Article</title></head><body><h1>Hello</h1></body></html>GET /docs/getting-started HTTP/1.1
Host: api.example.com
Accept-Language: fr-FR
Via: 1.1 translate-proxy.internalHTTP/1.1 203 Non-Authoritative Information
Content-Type: text/html; charset=utf-8
Content-Language: fr
Via: 1.1 translate-proxy.internal
X-Original-Language: en
X-Transform: machine-translation
<html><body><h1>Commencer</h1><p>Bienvenue dans la documentation...</p></body></html>Edge Cases
- •Most transforming proxies return 200 instead of 203 because virtually no client logic differentiates between the two — making 203 an honesty signal with no practical enforcement.
- •A 203 response is still cacheable by default (it's a successful response), but caches should note that the stored representation is a transformation, not the origin's canonical response.
- •The Warning header (now deprecated in RFC 9111) with code 214 'Transformation Applied' was the companion signal to 203 — both are transparency mechanisms that the ecosystem largely ignores.
- •If a client sends Cache-Control: no-transform, the proxy MUST NOT transform the response. If the proxy cannot serve untransformed content, it should forward directly to origin rather than returning 203.
- •A proxy chain (client → proxy A → proxy B → origin) might produce 203 at any hop. The Via header tracks which intermediaries were involved, but doesn't specify which one performed the transformation.
- •203 does NOT mean the content is wrong or degraded — a WebP conversion might be smaller AND higher quality than the original PNG at that size. The signal is about provenance, not quality.
- •Mobile optimization proxies (like Opera Mini's server-side rendering) are a canonical use case but they typically return 200 to avoid confusing mobile apps that might treat non-200 as errors.
When You'll See This
- →ISP transparent proxy compresses images to reduce bandwidth for mobile users
- →CDN edge node converts PNG/JPEG to WebP/AVIF based on client Accept header
- →Enterprise proxy strips tracking scripts or ad content from HTML responses
- →Translation gateway converts English API documentation to the user's preferred language
- →Mobile optimization proxy (Opera Mini-style) re-renders pages server-side and serves simplified HTML
- →Content-filtering proxy removes adult content or blocked domains from HTML
- →API gateway reformats XML responses from legacy backends into JSON for modern clients
- →Security proxy strips potentially dangerous headers (X-Powered-By, Server version) from responses
Implementation References
| Language | Constant |
|---|---|
| Go | http.StatusNonAuthoritativeInfo |
| Rust | http::StatusCode::NON_AUTHORITATIVE_INFORMATION |
| Python | http.HTTPStatus.NON_AUTHORITATIVE_INFORMATION |
| Node.js | http.STATUS_CODES[203] |
| .NET | HttpStatusCode.NonAuthoritativeInformation |
| Java | HttpURLConnection.HTTP_NOT_AUTHORITATIVE |
| PHP | Response::HTTP_NON_AUTHORITATIVE_INFORMATION (Symfony) |
| Ruby | :non_authoritative_information (Rack) |
History
Introduced in HTTP/1.1 (RFC 2068, 1997) alongside the proxy architecture that defined transparent and non-transparent intermediaries. The status was designed for an internet where transforming proxies were expected to be common — ISPs compressing images to save bandwidth, enterprise proxies stripping content, translation gateways serving multilingual content. In practice, the ecosystem evolved differently: proxies transform silently (returning 200), clients don't check for 203, and the rise of HTTPS made transparent proxy transformation much harder (you can't modify what you can't decrypt). RFC 9110 (2022) retained 203 but it remains one of the least-used standardized status codes. The related Warning header mechanism was deprecated entirely in RFC 9111.
Related Status Codes
Related Headers
FAQ
What is the difference between HTTP 200 and HTTP 203?
200 OK means the response body is exactly what the origin server generated — untouched, authoritative content. 203 Non-Authoritative Information means the request succeeded but an intermediary (proxy, CDN, gateway) modified the response before delivering it to you. The content might be compressed, reformatted, translated, or filtered. The key distinction is provenance: 200 = origin's exact response, 203 = transformed by a middleman. In practice, most clients treat them identically since both indicate success.
Why is HTTP 203 so rarely seen in practice?
Three reasons. First, most transforming proxies return 200 because clients and applications almost never differentiate behavior based on 203 vs 200 — there's no incentive to be transparent. Second, the rise of HTTPS (TLS) means proxies can't inspect or modify encrypted traffic without breaking the certificate chain, eliminating the most common transformation scenarios. Third, when content optimization moved to CDN edge nodes controlled by the site owner (Cloudflare, Fastly), it's treated as part of the origin's delivery infrastructure rather than an external intermediary — so 200 is appropriate.
Should my API or proxy return 203 when transforming responses?
It depends on your architecture. If you're building a transparent proxy that modifies responses from origins you don't control, 203 is semantically correct — you're signaling that the content isn't authoritative. However, be aware that some clients, SDKs, and monitoring tools may treat non-200 success codes as unusual or even log them as warnings. If you control both the origin and the transformation layer (like a CDN you configured), returning 200 is standard practice since the transformation is part of your intended delivery pipeline. Use 203 when transparency to the end-client about content provenance genuinely matters.