Exploring the roots and future of Internet Relay Chat

RFC 2812 vs RFC 1459: What Actually Changed in the IRC Protocol

RFC 1459 was published in May 1993. RFC 2812 arrived in April 2000. Between those dates, IRC went from a few thousand users to millions, spawned dozens of networks, weathered multiple civil wars, and proved that a text-based chat protocol could scale far beyond what its creator imagined. The updated RFC tried to capture seven years of battle-tested reality. It partially succeeded.

Context: Why Two RFCs?

By the late 1990s, RFC 1459 was showing its age. Not because the protocol was broken — it worked fine — but because the specification was incomplete. RFC 1459 described a protocol that had already evolved past the document by the time it was published. Server implementations like ircd 2.9, ircu, and the various EFnet patches all supported features not mentioned in the RFC, while ignoring parts of the spec that turned out to be impractical.

Christophe Kalt, a French IRC developer who worked on IRCnet's server software, took on the task of updating the specification. The result was not one RFC but four, published simultaneously in April 2000:

  • RFC 2810: IRC Architecture
  • RFC 2811: IRC Channel Management
  • RFC 2812: IRC Client Protocol
  • RFC 2813: IRC Server Protocol

Of these, RFC 2812 is the one that matters most to client developers and bot writers. It's the direct successor to the client-facing parts of RFC 1459.

The Four-Document Split

RFC 1459 crammed everything into one document: architecture, client protocol, server protocol, and channel management. This made it easy to read cover-to-cover but hard to reference for specific implementation questions. The 2000 update split things into four focused documents.

The split was logical but had an unintended consequence. Server protocol (RFC 2813) was heavily influenced by IRCnet's specific implementation. Networks running other server software — EFnet with its TS-based ircd, Undernet with ircu, DALnet with Bahamut — found that RFC 2813 didn't match their server-to-server protocols at all. It was essentially an IRCnet specification masquerading as a general standard.

RFC 1459 (1993) — Monolithic specification
    |
    +-- RFC 2810 (2000) — Architecture overview
    +-- RFC 2811 (2000) — Channel management
    +-- RFC 2812 (2000) — Client protocol (replacement for 1459 client parts)
    +-- RFC 2813 (2000) — Server protocol (IRCnet-specific in practice)
Warning: RFC 2812 has status "Informational," not "Standards Track." This means it documents existing practice rather than mandating new behavior. No network is obligated to implement it fully, and most don't.

Message Format Changes

The basic IRC message format remained the same between the two RFCs:

[:prefix] COMMAND [params] [:trailing]
Example: :nick!user@host PRIVMSG #channel :Hello everyone

RFC 2812 tightened several definitions. The most notable change was in how the prefix (the part before the command that identifies the sender) was specified. RFC 1459 was vague about when a prefix was required and what format it should take. RFC 2812 mandated that servers MUST include a full nick!user@host prefix for messages from users, while RFC 1459 merely suggested it.

Line length remained capped at 512 bytes including the trailing CRLF. This limitation, inherited from RFC 1459, would become one of IRC's most persistent pain points — especially as UTF-8 adoption meant that a single character could consume up to four bytes. The IRCv3 working group eventually addressed this with the message-tags specification, but that came much later.

Character set handling was slightly clarified but not resolved. RFC 1459 assumed the protocol was 8-bit clean (any byte value except NUL, CR, and LF was valid in messages). RFC 2812 maintained this assumption. Neither document mentioned UTF-8, which by 2000 was already becoming the dominant encoding on the web. This oversight would cause encoding headaches for another two decades.

New and Modified Commands

RFC 2812 introduced several new commands and modified existing ones:

New commands:

  • SERVICE — Register a network service. In practice, almost never used; services connect using server-to-server protocol instead.
  • SERVLIST — List available services. Also rarely implemented.
  • SQUERY — Send a query to a service. Same story.

Modified commands:

  • USER — The realname parameter was clarified. The mode bitmask parameter (the second parameter) was defined: bit 2 = wallops, bit 3 = invisible. RFC 1459 left the second and third parameters vaguely defined.
  • JOIN — RFC 2812 added support for joining multiple channels in one command with JOIN #chan1,#chan2 key1,key2. RFC 1459 mentioned this possibility but didn't specify the behavior clearly.
  • USERHOST — Clarified to support up to 5 nicknames per query.
  • WHOIS — Multiple parameters better defined.

The SERVICE/SERVLIST/SQUERY commands are particularly interesting as a case study in specification-driven design vs. practice-driven design. Kalt envisioned a formal service registration mechanism. The IRC community collectively ignored it and continued using pseudo-servers and direct server links for services. The commands exist in the RFC. They exist in almost no implementations.

Channel Types and Modes

RFC 1459 defined two channel types: #channels (network-wide) and &channels (local to one server). RFC 2812 added two more:

  • +channels — Channels without modes. Anyone could join, no one could be banned, no one could be opped. A truly anarchic space.
  • !channels — Safe channels with a unique ID prefix to prevent collision during netsplits. The channel name included a creation timestamp, making it impossible for two channels with the same name to exist.

Of these additions, !channels were implemented on IRCnet and almost nowhere else. +channels saw limited adoption on a few networks. Neither caught on broadly. The # and & prefixes from RFC 1459 remain the only universally supported channel types.

Channel modes received some updates. RFC 2812 added the e (ban exception) and I (invite exception) modes, which had already been implemented by several server packages. These were genuinely useful additions — they let channel operators create nuanced access control (ban a hostmask pattern, then except specific users within that pattern).

# Ban all of example.com, except trusted-user
MODE #channel +b *!*@*.example.com
MODE #channel +e trusted!user@specific.example.com

Numeric Reply Overhaul

RFC 1459 defined numeric reply codes somewhat haphazardly. Some ranges were assigned but not all codes within those ranges were used. Some codes had ambiguous meanings. RFC 2812 organized the numerics more systematically:

  • 001-004: Connection registration (RPL_WELCOME through RPL_MYINFO)
  • 005: RPL_ISUPPORT — Not in either RFC, but the most important numeric in modern IRC. Added by practice, standardized by IRCv3.
  • 200-399: Command replies
  • 400-599: Error replies

New error codes were added for new commands and edge cases. ERR_UNAVAILRESOURCE (437) was added for the channel/nick delay system used by IRCnet. ERR_NOCHANMODES (477) was added for +channels that don't support modes. Several existing codes had their descriptions tightened.

The numeric reply system remains one of IRC's design strengths. Three digits are easy to parse, easy to remember, and provide enough range for extensibility. HTTP borrowed the same approach. It works.

Adoption Reality: Nobody Implements All of 2812

Here is the uncomfortable truth about RFC 2812: no major IRC server or client implements it fully. Every implementation cherry-picks the parts that are useful and ignores the rest.

UnrealIRCd targets RFC 1459 as its baseline, with selected RFC 2812 additions (ban exceptions, invite exceptions, the clarified USER command). InspIRCd does the same. ircu (Undernet's server) has its own interpretation. IRCnet's ircd is closest to RFC 2812, which makes sense given the author's affiliation, but even it deviates.

On the client side, the situation is similar. Irssi, WeeChat, and HexChat all understand RFC 1459 commands and common extensions. They don't implement SERVICE, SQUERY, or SERVLIST. They handle !channels inconsistently or not at all.

The real standardization of modern IRC is happening through the IRCv3 working group, which takes a pragmatic approach: document what servers and clients actually do, reach consensus on extensions, and publish specifications that reflect reality rather than aspirations. IRCv3 has achieved what RFC 2812 could not — broad adoption of incremental protocol improvements.

Tip: If you're writing an IRC client or bot today, target RFC 1459 for baseline compatibility, support IRCv3 capability negotiation (CAP), and handle RPL_ISUPPORT (005) to discover server-specific features. This covers 99% of real-world IRC networks.

FAQ

Should I read RFC 1459 or RFC 2812 first?

Read RFC 1459 first. It's the foundational document and covers the core protocol concisely. Then skim RFC 2812 for clarifications and additions, particularly around channel modes and USER command parameters.

Why didn't RFC 2812 replace RFC 1459?

RFC 2812 was published as Informational, not Standards Track. It couldn't formally obsolete RFC 1459. More practically, the IRC community had already diverged significantly from any single specification by 2000, and adoption of 2812's new features was selective at best.

What is IRCv3 and how does it relate to the RFCs?

IRCv3 is a working group that develops modern extensions to the IRC protocol through consensus. It builds on top of RFC 1459 baseline with incremental capabilities like SASL authentication, message tags, account tracking, and server-time. It has achieved broader adoption than RFC 2812's additions.