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 evolving 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 evolved 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
Status#2xx-Success 2xx
Status#3xx-Redirection 3xx
Status#4xx-Client-Error 4xx
Status#5xx-Server-Error 5xx

Headers

The specification defined 16 HTTP headers:

Category Headers
General 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.

Security

Basic authentication provides no confidentiality. Credentials are trivially reversible from the Base64 encoding. Without TLS, both credentials and response data travel over the network in plaintext.

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.

Proxy problem

A proxy unaware of Keep-Alive forwarded the Connection: Keep-Alive header verbatim to the origin server. Both sides kept their connections open, but the proxy itself did not reuse them, resulting in hung connections. HTTP/1.1 solved this by making persistent connections the default and defining Connection as a hop-by-hop header.

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: 80

<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: April 4, 2026