Telnet has been around since before the dawn of Unix time, yet surprisingly few people know how to wield this tremendously useful debugging tool. A few seconds with telnet can save you hours of frustrated searching, trial-and-error config changes, and shouting at your monitor.
Telnet lets you speak plain-text protocols by hand. I've used it to talk to MySQL, Memcached, and Postfix. Here I'll show you how to use it to verify that an HTTP server can serve content over HTTP/1.1.
What is HTTP?
Before we can simulate HTTP with telnet, we need a quick refresher on how the protocol works.
HTTP/1.1 — the HyperText Transfer Protocol — is a plain-text protocol defined in RFC 2616. It's used for all sorts of things, but the most visible use for most people is fetching web pages.
When you request a webpage, your browser connects to the web server and sends a request. A typical one looks like this:
GET / HTTP/1.1
Host: example.com
The format is:
[METHOD] [PATH] HTTP/1.1
Host: [HOSTNAME]
[BLANK LINE]
The server responds with something like this — headers first, then a blank line, then the page content:
HTTP/1.1 200 OK
Server: Apache/2.2.3 (Red Hat)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
ETag: "b300b4-1b6-4059a80bfd280"
Accept-Ranges: bytes
Content-Type: text/html; charset=UTF-8
Connection: close
Date: Thu, 10 Dec 2009 10:37:33 GMT
Age: 7114
Content-Length: 438
<HTML>
<HEAD>
<TITLE>Example Web Page</TITLE>
</HEAD>
<body>
<p>You have reached this web page by typing "example.com",
"example.net",
or "example.org" into your web browser.</p>
<p>These domain names are reserved for use in documentation and are not available
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
2606</a>, Section 3.</p>
</BODY>
</HTML>
The response format is:
HTTP/1.1 [STATUS CODE AND REASON]
[HEADERS]
[BLANK LINE]
[BODY]
There's a lot more to HTTP, all documented in rather dry detail in RFC 2616. Mostly you can skim it for the parts you need.
Trying it with telnet
Now that we know how HTTP requests look, let's use telnet to make one by hand.
The telnet man page tells us the command accepts a host and a port. We want to talk to example.com on port 80 (the standard HTTP port):
telnet example.com 80
You'll see output like this as it connects:
Trying 192.0.32.10...
Connected to example.com.
Escape character is '^]'.
Now your cursor is sitting on a blank line. This is where you become the browser. Type the GET request from above (including the blank line at the end), and after a short pause you should get the example.com web page back.
Why is this useful?
Manually requesting a page like this can quickly expose several common problems:
- Firewall issues — if telnet can't connect, you know the problem is at the network level, not in your application.
- Status codes — the response code tells you exactly what the server did with your request. RFC 2616, Section 10 has the full list.
- No caching surprises — unlike a browser, telnet won't serve you a stale cached version of the page.
- Header inspection — you can see every header the server returns, which is invaluable for debugging.
- Compression testing — add an Accept-Encoding header to verify your assets are being served gzipped.
And telnet isn't limited to HTTP. SMTP, IMAP, POP, and many other plain-text protocols can all be explored this way. It's not a silver bullet, but it's one of the most useful tools you'll find already installed on your machine.