IRCv3 Message IDs

This specification is a work-in-progress and may have major incompatible changes without warning.

This specification may change at any time and we do not recommend implementing it in a production environment.

Copyright © 2016 James Wheare <>

Unlimited redistribution and modification of this document is allowed provided that the above copyright notice and this permission notice remains intact.

Notes for implementing work-in-progress version

This is a work-in-progress specification.

Software implementing this work-in-progress specification MUST NOT use the unprefixed msgid tag name. Instead, implementations SHOULD use the draft/msgid tag name to be interoperable with other software implementing a compatible work-in-progress version.

The final version of the specification will use an unprefixed tag name.


This specification describes a message tag indicating a server supplied unique ID for events.


Communication on IRC has historically been limited to a flat structure of sequential messages without unique identifiers shared across clients. As a result, the protocol lacks an ability to establish relationships between messages and other entities. This places limits on client-side enhancements such as reply tracking, message editing, rating or sending other forms of message annotation.

The message ID tag is a way for servers to enable these enhancements.



This specification doesn’t define any capabilities of its own, but the draft/message-tags capability MUST be negotiated for servers wishing to use this tag.


This specification adds the draft/msgid tag, which has a required value.

Servers MAY attach this tag on any event. If this tag is being used, it SHOULD be attached to all PRIVMSG and NOTICE events.

Tag value

The tag value is chosen by the originating server and MUST be unique, meaning any other message transmitted on the entire network at any time MUST NOT share the same value.

However, if a message is re-transmitted as-is, for example with the chathistory batch type, the ID SHOULD be reused. As a result, clients MUST accept shared IDs.

The tag value MUST be treated as a case sensitive opaque identifier. Clients MUST NOT use case folding or normalization when comparing IDs.

Relationships with other specifications

In order to treat messages that refer to IDs consistently, clients need to know the IDs for their own messages as well. Servers that provide message IDs SHOULD also provide the echo-message capability.

Server implementation considerations

This section is non-normative.

Choosing an ID format

In order to guarantee sufficient uniqueness, message IDs can’t be implemented as simple numeric counters that risk clashing with other servers on the network, or being reset if the server restarts.

Some examples of appropriate IDs are:

When using timestamps, make sure they’re correctly synchronised using NTP or similar.

Networks might also consider the risk of collisions when there’s a chance of merging with another network in future, and choose an appropriately resistant ID format.

Although clients are required to treat IDs as case sensitive opaque values, servers might still choose a case insensitive ID format internally.

Client implementation considerations

This section is non-normative.

Message IDs have no guarantee of being universally unique across different IRC networks, nor will they necessarily share the same format. There is also no requirement that numeric IDs increase monotonically. Don’t attempt to correlate them beyond their scope and don’t use them for message ordering.

In the case of re-transmitted messages that share an ID, clients might choose to mark a message as repeated, or just use the most recent occurence as the target for followup actions. Using server IDs alone as internal primary keys isn’t recommended, otherwise re-transmitted messages may not be individually addressable in client-side message stores.

Handling duplicates gracefully is also useful in the case of servers accidentally reusing an ID.


This section is non-normative, message IDs are not required to be UUIDs or have any specific format. Additional tags used in these examples may or may not have a specified meaning elsewhere.

A channel PRIVMSG sent by the server:

S: @draft/msgid=63E1033A051D4B41B1AB1FA3CF4B243E :nick!user@host PRIVMSG #channel :Hello!

A private PRIVMSG sent by the server:

S: @draft/msgid=server1-1480339715754191-21 :nick!user@host PRIVMSG me :Hello!

A channel NOTICE sent by the server:

S: @draft/msgid=G6PuDDBWQYmu3HmXXOAPzA :nick!user@host NOTICE #channel :Hello!

A private NOTICE sent by the server:

S: @draft/msgid=ticketid-5 :nick!user@host NOTICE me :Hello!

A channel JOIN sent by the server:

S: @draft/msgid=msgid123 :nick!user@host JOIN #channel account :Real Name

A channel PRIVMSG sent by the server, and a possible client response. The +example/reply tag is a non-standard example:

S: @draft/msgid=msgid1 :nick!user@host PRIVMSG #channel :Hello!
C: @+example/reply=msgid1 :nick2!user2@host2 PRIVMSG #channel :Hello to you!

Two channel PRIVMSG messages sent by the server, with possible non-standard example annotations to indicate split message concatenation:

S: @draft/msgid=msgid1;example/split :nick!user@host PRIVMSG #channel :Hello
S: @draft/msgid=msgid2;example/concat=msgid1 :nick!user@host PRIVMSG #channel : World

A client negotiating the draft/message-tags capability to enable and disable messages tagged with IDs.

S: :nick!user@host PRIVMSG #channel :Hello
C: CAP REQ draft/message-tags
S: CAP me ACK :draft/message-tags
S: @draft/msgid=msgid-a :nick!user@host PRIVMSG #channel :Hello again
C: CAP REQ -draft/message-tags
S: CAP me ACK :-draft/message-tags
S: :nick!user@host PRIVMSG #channel :Another hello