HTTP/0.9
HTTP/0.9 is the original version of the HyperText Transfer Protocol, created by Tim Berners-Lee at CERN in 1990. The protocol had no version number at the time. The "0.9" label was applied retroactively when HTTP/1.0 emerged, to distinguish the original from its successor.
History
Tim Berners-Lee built four components to create the World Wide Web: the HTTP protocol, HTML, the WorldWideWeb browser (a browser-editor hybrid running on NeXTSTEP), and the CERN httpd web server. A working prototype ran on a NeXT computer at CERN by 25 December 1990.
The CERN httpd version 0.1 was publicly released in
June 1991. On 6 August 1991, Berners-Lee posted to
the alt.hypertext Usenet newsgroup announcing the
project. The post described "a simple protocol (HTTP)"
and offered the code freely, ending with
"Collaborators welcome!"
HTTP/0.9 was never published as an RFC. The entire specification was a W3C document under 700 words titled "The HTTP Protocol As Implemented In W3." RFC 1945 (HTTP/1.0, published May 1996) is the first RFC to reference HTTP/0.9, stating it "defines both the 0.9 and 1.0 versions of the HTTP protocol."
The one-line protocol
HTTP/0.9 is sometimes called the one-line protocol.
The entire request is a single ASCII line: the word
GET, a space, and the document path, terminated by
a carriage return and line feed (CRLF).
GET /index.html
No HTTP headers. No version string. No Host header. The path omits the scheme, host, and port because those are already established by the TCP connection.
The response is equally minimal: raw HTML bytes streamed back over the connection. No status line, no headers, no Content-Type. The server closes the TCP connection when the transfer completes. Connection closure is the only signal the response is finished.
Request format
RFC 1945 formalized the HTTP/0.9 request as:
Simple-Request = "GET" SP Request-URI CRLF
GET was the only supported method. No other methods existed. The original specification noted any words after the document address on the request line "MUST either be ignored, or else treated according to the full HTTP spec." This forward compatibility rule allowed HTTP/1.0 to add a version identifier on the same line without breaking older servers.
Response format
RFC 1945 defined the HTTP/0.9 response as:
Simple-Response = [ Entity-Body ]
The server sent an HTML document as a byte stream of ASCII characters and closed the connection. No status code indicated success or failure. Errors were communicated through HTML content. The server generated an HTML page describing the problem, and the client displayed it. There was no programmatic way to distinguish an error from a successful response.
The original specification noted lines in the response were delimited by an optional carriage return followed by a mandatory line feed, and "well-behaved servers should restrict line length to 80 characters."
Example
A complete HTTP/0.9 exchange. The client opens a TCP connection to port 80, sends a one-line request, and receives raw HTML terminated by connection close.
Request
GET /info.html
Response
<html>
<head><title>Info</title></head>
<body>
<h1>Welcome</h1>
<p>This document was served over HTTP.</p>
</body>
</html>
The server closes the TCP connection after the last byte. One request, one response, one connection.
Limitations
HTTP/0.9 had no mechanism for any of the features later versions introduced:
- No headers: neither requests nor responses carried metadata.
- No status codes: the server had no way to signal error conditions programmatically.
- No content type: every response was assumed to be HTML.
- No persistent connections: each request required a new TCP connection.
- No content length: the end of the response was signaled by connection close, making it impossible to detect truncated responses.
- No virtual hosting: without a Host header, a server listening on a single IP address had no way to distinguish between different domains.
- No authentication: no mechanism for access control.
- No caching: no Cache-Control or Expires directives.
- No content negotiation: the server had no information about client preferences.
- GET only: no POST, HEAD, PUT, or any other method.
The 1992 W3C design summary captured the philosophy behind this simplicity: "Both browsers and servers silently ignore things they cannot handle ... This means the user is not annoyed by messages he should not have to deal with."
Security
The absence of structure in HTTP/0.9 responses creates security vulnerabilities in implementations still accepting them.
Cross-protocol attacks. Since HTTP/0.9 responses have no headers or status line, any data received from any TCP service looks like a valid HTTP/0.9 response. A browser connecting to a non-HTTP service on a non-standard port receives data interpreted as HTML. An attacker controlling content on such a service (SMTP, POP3, FTP) crafts data executing scripts when interpreted as HTML in the browser context.
Request smuggling. Eclipse Jetty was vulnerable (CVE-2017-7656) to a variant where an HTTP/1.x-style request declared HTTP/0.9. Behind a proxy, the raw response was interpreted as HTTP/1 headers, enabling cache poisoning.
Method restriction bypass. Apache Tomcat did not limit HTTP/0.9 requests to the GET method (CVE-2026-24733). This allowed sending a HEAD request using HTTP/0.9 to bypass security constraints.
Virtual host isolation failure. Without a Host header, name-based virtual hosting breaks. RFC 9112 Appendix C.1 states: "Any server that implements name-based virtual hosts ought to disable support for HTTP/0.9."
Deprecation
RFC 7230 (2014) dropped the expectation for HTTP servers to support HTTP/0.9 requests. RFC 9112 (2022) reinforced this and added the recommendation to disable HTTP/0.9 on servers with name-based virtual hosts. The RFC also notes most requests appearing to be HTTP/0.9 are "badly constructed HTTP/1.x requests caused by a client failing to properly encode the request-target."
Chromium-based browsers restricted HTTP/0.9 to port 80
and subsequently removed most support. Responses not
resembling HTTP/1.x return
ERR_INVALID_RESPONSE. At the time of deprecation,
HTTP/0.9 accounted for roughly 0.01% of HTTP
responses.
Firefox investigated full removal but kept restricted support for compatibility reasons. Some consumer routers used HTTP/0.9-style responses for their management interfaces.
curl disabled HTTP/0.9 responses by default and
requires the --http0.9 flag to accept them. The
rationale: connecting to a random TCP service must
not produce something curl interprets as a valid
HTTP
response.
Apache httpd accepts HTTP/0.9 requests by default. The
HttpProtocolOptions directive with Require1.0
disables this behavior. nginx has historically
accepted HTTP/0.9 requests as well.
Relationship to later versions
HTTP/1.0 (RFC 1945) maintained full backward compatibility. An HTTP/1.0 server receiving a Simple-Request (HTTP/0.9 format) was required to respond with a Simple-Response (no status line, no headers). HTTP/1.0 clients were required to understand HTTP/0.9 responses.
The critical change from HTTP/0.9 to HTTP/1.0 was the addition of a version identifier on the request line. An HTTP/1.0 request starts with:
GET /index.html HTTP/1.0
The presence of HTTP/1.0 after the URI
tells the
server to respond with a full response including
status line and headers. The absence of a version
string signals an HTTP/0.9 request.
HTTP/1.0 added HTTP headers, status codes, additional request methods (HEAD, POST), content type identification through Content-Type, and basic Caching and Authentication mechanisms.
HTTP/1.1 inherited the connection-close framing from HTTP/0.9. RFC 9110 notes "HTTP/0.9 and early deployments of HTTP/1.0 used closure of the underlying connection to end a response. For backwards compatibility, this implicit framing is also allowed in HTTP/1.1."
Takeaway
HTTP/0.9 was the original protocol for the World Wide Web: a single-line GET request, a raw HTML response, and a closed connection. No headers, no status codes, no content types. The protocol was designed to be as simple as possible, and its simplicity both enabled rapid adoption and created security weaknesses later versions addressed. Modern servers and clients have largely dropped HTTP/0.9 support, and RFC 9112 recommends disabling it entirely.
See also
- The Original HTTP as defined in 1991 (W3C)
- HTTP0.9 Summary (W3C, 1992)
- RFC 1945: HTTP/1.0
- RFC 9112: HTTP/1.1
- HTTP/1.0
- HTTP/1.1
- HTTP/2
- HTTP/3
- GET
- HTTP Explained