HTTP/1.0

After years of ad-hoc browser and server extensions to HTTP/0.9, HTTP/1.0 became the first formally documented version of the HyperText Transfer Protocol. Published in May 1996 as RFC 1945, the specification codified practices grown organically since 1991. RFC 1945 was authored by Tim Berners-Lee, Roy T. Fielding, and Henrik Frystyk Nielsen.

RFC 1945 is an Informational RFC, not a Standards Track document. The IESG note states: "The IESG has concerns about this protocol, and expects this document to be replaced relatively soon by a standards track document." The replacement arrived eight months later with HTTP/1.1 (RFC 2068).

History

Between 1991 and 1995, HTTP developed through a try-and-see approach. Browser and server developers added features (headers, status codes, new methods) and shipped them without formal coordination. Interoperability problems were common.

NCSA Mosaic (1993) and Netscape Navigator (1994) drove rapid adoption of the web. On the server side, CERN httpd and NCSA HTTPd introduced features like Content-Type and CGI scripting. Apache, forked from NCSA HTTPd in early 1995, quickly became the dominant server software.

RFC 1945 did not invent HTTP/1.0. The specification documented "features that seem to be consistently implemented in most HTTP/1.0 clients and servers." By the time the RFC was published, millions of requests per day already used the protocol the RFC described.

What HTTP/1.0 added

HTTP/0.9 had one method (GET), no headers, no status codes, and no content types. HTTP/1.0 changed the protocol fundamentally.

Request and response structure

The request line gained a version identifier:

GET /index.html HTTP/1.0

The response gained a status line with the protocol version, a numeric status code, and a reason phrase:

HTTP/1.0 200 OK

Both requests and responses gained HTTP headers for carrying metadata.

Methods

HTTP/1.0 defined three methods in the core specification:

  • GET: retrieve a resource
  • HEAD: retrieve headers only, no body
  • POST: send data to the server

Appendix D listed PUT, DELETE, LINK, and UNLINK as additional methods with inconsistent implementations.

Status codes

RFC 1945 defined 16 status codes across four active classes. The 1xx class was reserved but not used.

Class Codes
2xx 200, 201, 202, 204
3xx 300, 301, 302, 304
4xx 400, 401, 403, 404
5xx 500, 501, 502, 503

Headers

The specification defined 16 HTTP headers:

Category Headers
General Date, Pragma
Request Authorization, From, If-Modified-Since, Referer, User-Agent
Response Location, Server, WWW-Authenticate
Entity Allow, Content-Encoding, Content-Length, Content-Type, Expires, Last-Modified

Appendix D listed additional headers with inconsistent implementations, including Accept, Accept-Encoding, Accept-Language, and Content-Language.

Content types

HTTP/1.0 adopted the MIME media type system from email (RFC 1521). The Content-Type header enabled transmission of images, scripts, stylesheets, and any other file type, not HTML alone.

RFC 1945 Appendix C documented the differences between HTTP and MIME. HTTP does not use Content-Transfer-Encoding, and multipart body parts in HTTP carry full HTTP headers rather than only Content-* headers.

Authentication

Section 11 defined Basic Authentication using the Authorization and WWW-Authenticate headers. Credentials are Base64-encoded (not encrypted) and transmitted in cleartext.

Caching

HTTP/1.0 introduced a date-based Caching model using Expires, If-Modified-Since, Last-Modified, and Pragma: no-cache. The model had no Cache-Control directives, no ETags, and no revalidation mechanism beyond date comparison. Clock skew between client and server was a recurring problem.

Connection model

Each HTTP/1.0 request required a separate TCP connection. The server closed the connection after sending the response. A page with 10 images meant 11 TCP connections, each with a full three-way handshake.

This connection-per-request model was expensive. TCP slow start meant each new connection began with a small congestion window, and connections were closed before the window had time to grow. On high-latency networks, the overhead was significant.

The Keep-Alive extension

RFC 1945 did not define persistent connections. An unofficial Connection: Keep-Alive extension emerged around 1995, first implemented by Netscape Navigator. If the server echoed the header back, the TCP connection remained open for reuse.

Entity body length

RFC 1945 Section 7.2.2 defined two methods for determining body length:

  1. If Content-Length is present, its value defines the length in octets.
  2. Otherwise, the body ends when the server closes the connection.

POST requests required a Content-Length header because closing the connection prevented the server from sending a response. There was no chunked transfer encoding. Dynamic content of unknown length required either buffering the entire response before sending or relying on connection close.

Example

A complete HTTP/1.0 exchange. The client requests an HTML page, then opens a second TCP connection to fetch an image referenced in the page.

Initial request

GET /index.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
Accept: text/html

Response

HTTP/1.0 200 OK
Date: Sun, 01 Jan 1995 12:01:00 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
Content-Length: 72

<html>
Welcome to the <img src="/logo.gif"> example.re
homepage!
</html>

Second connection (to fetch the image)

GET /logo.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
Accept: image/gif

Response

HTTP/1.0 200 OK
Date: Sun, 01 Jan 1995 12:01:01 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: image/gif
Content-Length: 5000

<Encoded data of logo.gif>

Each request opens a new TCP connection. The server closes the connection after each response.

Limitations

HTTP/1.0 had significant constraints HTTP/1.1 addressed:

  • No mandatory Host header: a server listening on a single IP address had no way to distinguish between different domains. Virtual hosting was not possible with pure HTTP/1.0.
  • Connection per request: each request required a new TCP connection with full handshake overhead.
  • No chunked transfer encoding: dynamic content of unknown length had to be buffered completely or terminated by connection close.
  • Limited caching: only date-based, no ETags, no max-age, no revalidation beyond If-Modified-Since.
  • No persistent connections in the spec: Keep-Alive was a non-standard extension with proxy compatibility issues.
  • No content negotiation in core: Accept headers were in Appendix D with inconsistent implementations.
  • No range requests: no mechanism for resumable downloads or partial content retrieval.

See also

Last updated: August 11, 2026