Skip to content

Instantly share code, notes, and snippets.



Last active Apr 2, 2017
What would you like to do?

Note: This is an old edition of the CTCP document before it was moved to

Client-to-Client Protocol (CTCP)

© 2015–2016 Mantas Mikulėnas

This documentation is released under CC BY 4.0.

This attempts to document the CTCP sub-protocol as currently used on IRC. It obsoletes all earlier CTCP specifications, which were unnecessarily complex and remained mostly unimplemented.

Changes since 1994 specification

In the current specification, the raw message body must consist entirely of either a CTCP message or plain text (non-CTCP), superseding any previous specifications which used to allow intermixing plain-text chunks and "tagged data" CTCP chunks.

This specification does not include any mechanism for quoting plain text (non-CTCP) messages, obsoleting any previous "low-level quoting" specifications. Likewise, it does not define any mechanism for quoting CTCP parameters, although individual CTCP message specifications may define their own quoting.

CTCP message syntax

delim   = %x01

command = 1*( %x02-09 / %x0B-0C / %x0E-1F / %x21-FF )
              ; any octet except NUL, delim, CR, LF, and " "

params  = 1*( %x02-09 / %x0B-0C / %x0E-FF )
              ; any octet except NUL, delim, CR, and LF

message = delim command [ SPACE params ] delim

"Extended data" CTCPs are sent as a PRIVMSG body and generate no reply:

:dan- PRIVMSG #ircv3 :\x01ACTION is now away (BX-MsgLog:ON)\x01

"Metadata query" and "Extended query" CTCPs are sent as PRIVMSG body, while replies are sent as NOTICE body:

:dx PRIVMSG SaberUK :\x01VERSION\x01
:SaberUK NOTICE dx :\x01VERSION Your Mother 6.9\x01

:bcode PRIVMSG Kyth :\x01AVATAR\x01
:Kyth NOTICE bcode :\x01AVATAR\x01

Queries sent to a channel always generate private replies:

:mt PRIVMSG #ircv3 :\x01PING 1473523796 918320\x01
:Jobe NOTICE mt :\x01PING 1473523796 918320\x01

CTCP message types

The existing CTCP sub-protocol doesn't define any way to distinguish between different CTCP message types, so while it would be desirable to generate "unknown command" error responses to queries but not extended-data, that's not always possible. Generally, channel-directed CTCPs should never cause an error reply.

Extended data

Purpose: Request special formatting. That is, send a user-visible message that should be displayed differently from regular messages – e.g. an action/emote, a whisper, an announcement.

Does not require any automatic response.

Examples: Well-known ACTION, possibly OTR or SOUND.

Usage note: In practice many servers implement optional filtering to block query/reply CTCPs in channels (i.e. broadcast ping). Since they cannot distinguish query CTCPs from data CTCPs, they only whitelist the widely-used ACTION and block everything else. Therefore any future extended-data CTCPs, if any, will end up being limited to private messages.

Replacement: Will be replaced by IRCv3.∞ intents client-to-client tags.

Metadata query/reply

Purpose: Provide static information about the target client, user, or connection.

The target usually responds with a single reply (although some choose to ignore all such queries; bouncers might forward the query to all clients, causing multiple replies.) It is strongly recommended to always send at least one reply, which may be empty to indicate unavailable information.

Metadata queries must not require the recipient to implement any side effects (beyond sending the reply); if a CTCP message causes side effects by design, it should be categorized as "extended query" instead.


Replacement: Will be replaced by server-side IRCv3.2 metadata. Someday.

Extended query/reply

Purpose: Provide dynamic information or invoke actions.

Examples: PING (returns same data), PAGE (causes out-of-band notification).

Replacement: Yeah, right.

CTCP message registry

Extended data messages can have parameters, but usually do not generate an automatic reply.

Metadata query messages do not have any parameters, but expect a reply with parameters as the response data.

Extended query messages and replies may have parameters.


Type: Extended data

Parameters: Text (not parsed).

Support: Universal. Must implement.

Shows the message in the form of a third-person action or emote; in other words, it's the /me command:

<user> Here goes:
 * user is testing /me


Type: Metadata query

Support: KVIrc-specific. Optional.

Returns an URL to an "avatar" image chosen by the user (

The image MUST be in JPEG, PNG, or GIF format; SHOULD be no larger than 500 kB[1]; and SHOULD be served over HTTPS.

Clients which choose to implement avatar display MUST support retrieving images over HTTP or HTTPS; MUST support the aforementioned image formats (and MUST NOT require the URL to contain a file extension); and wait no what do you mean "no images on IRC" what wait let me go what do you mean "the elders of IRC have declared" no let me go what are you doing AUGH NO NO LET ME GO AAAAAAEEE—

[1] chosen by a dice roll


Type: Metadata query

Support: Widespread. Recommended.

Returns a list of all CTCP names understood by the client.



Type: Extended query

Support: Varies.

DCC is a mechanism for direct client-to-client connections, with several different subcommands implementing file transfer; direct chat; voice; and other kinds of data transfer. The DCC subcommands are a spec unto itself.


Type: Metadata query

Support: Widespread. Optional (redundant with WHOIS).

Not formally specified anywhere, but usually returns the user's full name (same as the WHOIS real-name field). This would fit the "FINGER" name.

However, some implementations are known to return the client's name and version instead.


Type: Extended query

Parameters: Text (not parsed).

Support: Rare. Known to be implemented by erc. Optional.

Does something to notify the recipient off-band (e.g. playing a sound; playing the given message via text-to-speech; etc.).

Should generate an empty reply as acknowledgement, though most implementations don't bother.


Type: Extended query

Parameters: PING <seconds> <usecs>

  • seconds: current Unix timestamp as decimal integer
  • usecs: current number of microseconds as decimal integer

Support: Near-universal. Must implement.

Reply must contain the exact same parameters as the original query (regardless of whether they're valid or not).

Used by the sender to check reachability and check latency ("lag").

--> PING 1473523721 662865
<-- PING 1473523721 662865

--> PING foo bar baz
<-- PING foo bar baz


Type: Metadata query

Support: Rare. Optional (silly).

Returns an URL to an image of a My Little Pony character.


Type: Metadata query

Support: Rare. Optional.

In some implementations, known to return an URL to the client's source code.


Type: Extended query

Parameters: None.

Support: Near-universal. Recommended. New implementations SHOULD default to UTC time for privacy reasons.

Returns the client's local time in unspecified human-readable format. (ISO 8601 is recommended, but raw ctime() output appears to be most common in practice.)

--> TIME
<-- TIME 2016-09-10 19:17:39 +0300


Type: Metadata query

Support: Universal. Recommended.

Returns the client's product name and version.

<-- VERSION WeeChat 1.5-rc2 (git: v1.5-rc2-1-gc1441b1) (Apr 25 2016)


Type: Metadata query

Support: Widespread. Optional (redundant with WHOIS).

Not formally specified anywhere, but usually returns the user's full name, as in FINGER. Some implementations are known to return nickname (realname).

<-- USERINFO fred (Fred Foobar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.