Specification of the protocol used by Phoenix channels

Is there a document available that describes how Phoenix channels are multiplexed into that single web socket? How a datagram/message looks like, what a client/server has to implement at least to be considered conforming to the standard?

I’m aware that I could reverse engineer the protocol from reading Phoenix source code, but I really prefer to have some technical document over code.


Not quite what you’re asking for, but this might provide some insight: https://github.com/brandonhamilton/purescript-phoenix/blob/master/src/Phoenix.purs


Well if do really have to read code I prefer phoenix’ since it is normative for its channels.


The Transport moduledoc is what you’re looking for:


This is a good documentation, but I don’t think it’s optimal from the standpoint of a client developer. At least, that was my personal impression back when I was writing an Elixir client. Ultimately, I inspected websocket messages in the browser, and read the Phoenix code (both server and client) to understand the protocol. On the plus side, the protocol is pretty simple, so it didn’t require a lot of work.

I think that a guide for client implementers would be beneficial, probably as a separate page in Phoenix docs. It could be written in a tutorial form, something like: to join a topic send a following message, then the server can reply with x or y, … I don’t think such guide would be long, but it could improve the job of client implementers.

If the team agrees, I’ll be happy to give this a shot, with a caveat that I can’t commit on any deadline.


Please do, and no rush!


I know this is a bit old but I was just working on making a C++ client and I basically went through a similar process as sasajuric although I found it was also helpful to read the code in the JS client as a reference implementation. I wound up writing this so I wouldn’t forget what I learned:


It’s certainly not a complete specification but it might help some people that arrive at this thread from a Google search like I did.


I think reading the phoenix js client is a start point

I didn’t want to create a new topic for this so I’m just going to revive this one.

Has anyone actually produced what could be considered documentation of the Phoenix protocol? Telling people to read the JS source isn’t really good enough, in my opinion. The JS source is, well, JS source code. Translating it to f.e. Haskell you gain almost nothing from the way it’s written in this object spaghetti JS style and can you really claim JS to be a good, descriptive way to express something like a protocol?


I’m certainly with you, that some more detailed specification would be nice.

What you can find in the js file are the handful of channel-specific events you could receive besides the custom user-land events:

  close: "phx_close",
  error: "phx_error",
  join: "phx_join",
  reply: "phx_reply",
  leave: "phx_leave"

The other part a client needs to be aware of is in which format messages are sent by the used transport.


E.g. the built in transports use basically a simple json blob for messages:

So the channel -> transport interface is documented and the websocket/longpolling transport -> client is using json in a particular format.

So what I miss the most is some descriptions for the above listed channel events and when they’re sent/shall be sent, some description about how to handle the different refs in messages and how to handle presence lists/diffs.

1 Like

I would find this useful as well and would be willing to help contribute to this document. We’ve had some bugs in an internal Dart/Flutter implementation and some of these bugs were due to a misunderstanding int he spec.

A good start would be sample send/receive payloads with informal explanations of what is going on.

Anyone interested in collaborating on this?

1 Like

Hello @venkatd, is it one of these libraries?:

@Enuzo no it’s private to our application. We had tried phoenix_wings I believe, but we had bugs with dropped connections so ended up rolling our own at a lower level. The process was difficult because of undocumented things–we had to look more closely at the javascript implementation.