TheAnig

Back

I stumbled across the Gopher protocol while reading about pre-web Internet history, and it immediately grabbed my attention. Here was this entire system for organizing information online that predated the World Wide Web, yet I’d never heard of it. The University of Minnesota developed it in 1991 as a way to make Internet resources easier to find and browse. For a brief moment in the early 90s, it looked like Gopher might become the primary way people navigated the Internet. Then the Web happened.

What makes Gopher interesting isn’t just its history though. It’s the design philosophy behind it. Where the Web gave us hyperlinks that could connect anything to anything else (creating what’s essentially a graph structure), Gopher organized everything into hierarchical menus, like a tree of directories. You navigate by going deeper into categories rather than jumping laterally between documents. It sounds limiting at first, but there’s something appealing about that constraint.

First impressions#

My first experience with Gopher was through a terminal-based client connecting to some of the servers still running today. What struck me immediately was how clean everything felt. No loading spinners, no cookie banners, no newsletter popups begging for my email address. Just menus of text leading to other menus or documents. It reminded me of navigating a well-organized file system, but one that spanned the entire Internet.

The speed was shocking. Even on my modern connection, pages (or rather, menus) loaded instantly. Part of that is because there’s so little data being transferred. A Gopher menu is literally just lines of text with some metadata. No CSS, no JavaScript, no web fonts loading from three different CDNs. The protocol itself is almost embarrassingly simple, which turns out to be one of its best features.

I started thinking about where something like this could have been useful. Remember the early Kindles with free 3G Internet? Amazon eventually locked them down to only access the Kindle Store and Wikipedia, probably because of bandwidth costs. But Gopher would have been perfect for that kind of constrained environment. A text-focused device with limited connectivity browsing a text-focused protocol. It feels like a missed opportunity.

There’s also something meditative about browsing Gopherspace. The hierarchical structure forces you to be more intentional about where you’re going. You can’t get lost in a maze of hyperlinks the way you do on the Web. Each step down the menu tree is a deliberate choice. It made me realize how much of modern web browsing is just following whatever shiny link catches your eye next.

The linking system is more versatile than I expected too. Gopher can link to external services like Telnet sessions, which opens up interesting possibilities. I found myself imagining an alternate timeline where Gopher became the dominant protocol. Would we have YouTube-like services delivered through Telnet ASCII art? There’s already that famous Star Wars ASCII animation on Telnet. Maybe that would have been the norm rather than a novelty.

How it actually works#

Once I got past the initial novelty, I wanted to understand how Gopher actually functions under the hood. The protocol is defined in RFC 1436, and reading through it was surprisingly straightforward. This isn’t a 200-page specification with edge cases and backward compatibility concerns. It’s simple by design.

Here’s the basic flow: a client connects to a Gopher server (typically on port 70) and sends a selector string. That’s it. Just a single line identifying what resource you want. The server responds with either a menu (a list of items) or the actual content you requested. No headers, no negotiation, no complex handshaking.

What’s clever is how menus are structured. Each line in a Gopher menu follows a tab-separated format:

typeIndicator <TAB> displayName <TAB> selector <TAB> hostname <TAB> port
plaintext

The type indicator is a single character that tells the client what kind of resource this is. A ‘0’ means it’s a text file, ‘1’ means it’s another menu (a directory), ‘7’ means it’s a search interface. There are others too, including some non-standard extensions for HTML and images that came later.

I also learned about Gopher+, an attempt to modernize the protocol with metadata like MIME types and file modification times. It was a bit like adding headers to HTTP, trying to make Gopher smarter. And then there was Veronica, which was basically the Google of Gopherspace, a search engine that indexed all these menus so you could actually find things without clicking through endless directories. It showed that even with a simple protocol, you could build powerful discovery tools.

The simplicity becomes really apparent when you compare it to HTTP. With HTTP, you’ve got request methods (GET, POST, PUT, DELETE), status codes (200, 404, 500, etc.), headers for content type and caching and cookies and a dozen other things. Gopher just says “here’s what I want” and the server says “here you go.” The client figures out what to do with it based on that single-character type indicator.

I actually tried debugging a Gopher connection using telnet, just to see the raw protocol in action:

telnet gopher.floodgap.com 70
plaintext

Then I sent an empty selector (just hit enter) and got back the root menu. Watching the response come through as plain text was oddly satisfying. You could build a basic Gopher client in an afternoon because there’s so little to implement.

Discovering Gopherpedia#

One of the most interesting things I found while exploring Gopherspace was Gopherpedia, which is exactly what it sounds like: Wikipedia accessible through the Gopher protocol. Someone actually went through the effort of creating a mirror that serves Wikipedia content as Gopher menus.

Trying to read a Wikipedia article through Gopherpedia really highlighted both what Gopher does well and where it struggles. The hierarchical category system maps naturally to Gopher’s menu structure. You can browse articles by topic, follow a logical tree of categories, and everything feels organized in a way that Wikipedia’s web interface sometimes doesn’t.

But then you hit the limitations. Wikipedia articles are full of inline links, right? You’re reading about, say, the Apollo program, and there are links to NASA, the Moon, rocket engines, all woven into the text. In Gopherpedia, those links can’t be inline. They either get listed at the end of the document or they break up the reading flow as separate menu items. It’s functional but awkward.

The formatting issues become more obvious with technical articles. Code blocks, mathematical notation, tables… these all rely on visual structure that plain text struggles to convey. Wikipedia on the web can use syntax highlighting and proper table layouts. Gopherpedia gives you ASCII and hopes for the best. For simple articles it works fine. For anything complex, you really feel the constraints.

It made me think about what would need to change if Gopher had continued evolving. Maybe some kind of lightweight markup language, something simpler than HTML but richer than plain text. The Gemini protocol (created in 2019 as a spiritual successor to Gopher) actually does something like this with its “gemtext” format. But at what point do these additions just turn Gopher into a worse version of the Web?

Where Gopher breaks down#

The more I explored, the more I started noticing patterns in what Gopher could and couldn’t do well. Static, hierarchical content? Perfect. Anything interactive or dynamic? That’s where things get complicated.

Think about something as basic as a web form. You fill in some fields, hit submit, and the server processes your input. Gopher wasn’t designed for this. The protocol is fundamentally request-response, not submission-based. There’s a search type (type 7) that lets you send a query string, but that’s about it. No POST requests, no file uploads, no real form handling.

I tried to imagine building a modern search engine on Gopher. You could crawl and index things easily enough, that’s just following links. But the interface? You’d connect to a search endpoint, type your query into a local buffer, and hit enter. That’s it. No autocomplete, no “did you mean…”, no instant results appearing as you type. All that interactivity we take for granted relies on the client and server talking back and forth constantly, which Gopher just doesn’t do.

This isn’t just a theoretical limitation. It means you can’t really do user accounts, comments, any kind of interactive service. A social network built on pure Gopher would be nearly impossible. You could maybe hack something together where users submit content through email or some external mechanism, and it gets compiled into static menus later. But that’s clearly not what people expect from modern services.

The other big constraint is real-time updates. Gopher clients poll servers; servers don’t push updates to clients. If you wanted something like a chat system or live notifications, you’d need to either poll constantly (inefficient and bandwidth-heavy) or extend the protocol significantly. Neither option is particularly appealing.

There’s also the stateless nature of the protocol. Every request is independent. No sessions, no cookies, no way to maintain context between interactions. From a privacy perspective, that’s actually kind of nice. From a functionality perspective, it rules out a lot of what we consider basic web features.

I started thinking about what technical extensions would be necessary to make Gopher viable for modern use cases. Client-side scripting for interactivity. Form submission capabilities. Some kind of push notification system. Better support for rich media with proper metadata. But each addition chips away at Gopher’s core appeal: simplicity. At some point you’re just rebuilding HTTP with extra steps.

Why it matters (even though it’s dead)#

Gopher lost to the Web, and honestly, it’s easy to see why. The Web’s flexibility won out over Gopher’s structure. Hyperlinks turned out to be more powerful than hierarchical menus. Images and multimedia made the Internet more accessible to non-technical users. And there was a crucial economic factor too: the University of Minnesota decided to license the Gopher server software commercially. Even though they later backed off, that moment of uncertainty was enough to scare developers away. Meanwhile, the Web was open and free from day one.

But exploring Gopher in 2021 has been a reminder that the Web’s complexity isn’t inevitable. We made choices, as a technical community and as users, that led us here. We chose rich media over bandwidth efficiency. We chose flexibility over structure. We chose engagement over intention. None of these are inherently wrong, but they all have costs.

There’s something appealing about Gopher’s constraints. The inability to track users across sessions. The focus on content over presentation. The forced organization that comes from hierarchical structure. These feel almost radical in the modern web context, where every site wants to be an application and every interaction generates data for some algorithm to chew on.

I’m not arguing we should all switch to Gopher (the three dozen people still maintaining Gopher servers probably wouldn’t appreciate the traffic anyway). But understanding what we gave up to get where we are feels valuable. The Web didn’t have to become this heavy, this complicated, this surveillance-oriented.

I’m planning to set up my own gopherhole as a side project, maybe mirror some of my blog content there. It seems like a fun technical exercise, and honestly, the idea of having a corner of the Internet that’s just structured text files served over a simple protocol appeals to me. If nothing else, it’ll be a space where I don’t have to worry about JavaScript frameworks going out of date every six months.

References & Further Reading#

If you’re interested in diving deeper into the history and technical details of Gopher, here are some of the resources I found helpful during my research:

Exploring the Gopher Protocol
https://theanig.dev/blog/gopher-protocol
Author Anirudh Ganesh
Published at June 29, 2021