2026-07-15 on Kevin Guillaumond's blog
In the course of my employment at Dialpad, I find myself responsible for the Telephony infrastructure that underpins its eFax solution 1.
For whatever reason, fax isn’t exactly a trendy technology. Which could explain why it’s difficult to find a centralised place that explains the basics.
Here’s the blog post that I wish I’d found when I started working on fax 2.
The main concepts are:
In order to send a piece of paper over a wire, you need to turn it into a bitstream. Our current way to do it was standardised back in 1980, when (an ancestor of) the ITU-T came up with the T4 Recommendation.
T6 later added a further compression type, which reduces the time it takes to transmit a single page.
I haven’t had to dig this deep yet, so T4/T6 is essentially a black box to me. Let’s just remember that T4 is the standard “fax codec”. It has been around for more than 40 years, and I expect every fax system to support it. T6 is essentially a more efficient variant of T4 that will get picked if both sides support it.
There are other such “fax codecs”, but none as universal as T4/T6.
There are a few ways to send an image over the wire. When sending a document, the two fax terminals need to pick one.
T30 describes a procedural protocol that governs how a fax is sent. The whole spec is hundreds of pages long, but at a high level, the fax session happens in five phases:
T30 is used by “Group 3” fax machines, which essentially means “every fax machine you’ll encounter”. Groups 1 and 2 are old enough that they can be ignored 4. Group 4 didn’t really pan out, so group 4 machines (outside of maybe a few countries) also support group 3.
So for all intents and purposes, all faxes use T30 for session management 5.
The phases are described in clause 2.3 of the T30 document, while the messages themselves are explained in clause 5.

Phase A is very simple: the caller sends CNG (Calling tone), while the callee sends CED (Called terminal identification). Both terminals have confirmation that the other side is a fax machine, and move on to phase B 6.
In phase B, the callee starts by sending DIS (Digital Identification Signal), which lists its fax capabilities (i.e. the high-speed protocols it supports). The caller responds with DCS (Digital Command Signal), which picks a protocol from that list.
Then comes training. The caller switches to the negotiated high-speed protocol, and sends a training sequence (specific to said protocol) followed by TCF (Training Check Field). If the callee has received the training sequence as expected, it responds with CFR (Confirmation to Receive), and both terminals move on to phase C. Otherwise, it sends back FTT (Failure To Train), and training has to restart (possibly with more robust parameters).
Phase C is data transmission. Image data is sent as a raw stream of bits, unless error correction mode is enabled, as we’ll see later.
Then comes phase D, where the caller goes back to the control channel and sends one of:
The callee will respond to that message with one of:
Phase E is normally just the caller sending DCN (Disconnect) to end the call.
Note that T30 defines a lot more control messages. We’ve only looked at the main ones here.
We’ve seen that by default, the image data is sent as raw bits and the only acknowledgement/retransmission mechanism happens at the page level. That makes fax very susceptible to line noise and minor transport-level problems.
The solution to this is ECM (Error Correction Mode).
Instead of sending the image data bits directly, the caller cuts them up into blocks, which are sent as HDLC (High Level Data Link Control) frames. There are 64 or 256 octets in a frame (value negotiated in phase B), and 256 frames in a block. Check out Appendix A.3 for details.
The callee can then check each frame individually. When asked, it reports back exactly which frames were bad, and those get retransmitted. The page is only assembled after every block has been verified 7.
The T30 messages look slightly different. The sender sends control messages after every block instead of after every page. They are PPS-* (Partial Page Signal) messages:
The recipient will signal success with MCF as before, and failure with PPR (Partial Page Request), which contains a list of frames that failed their error detection.
You should use ECM. It solves a lot of transport problems (especially over the Internet), for a small performance cost.
Fax over the telephony network is just a normal phone call. On such calls, there is only one communication channel: audio in the voice channel (~300 - ~3400 Hz). All the fax data and all the T30 messages are sent as tones over that audio channel.
Converting bits to and from analog data is the job of a modem. In practice, fax uses two different ones: a slow and robust one for control messages and a fast one for the data.
Phase A is simple enough that it doesn’t actually use a modem: the CNG and CED messages are pre-arranged. They are defined in T30 (clauses 4.2 and 4.1.1 respectively).
At this point, both terminals recognize each other as fax machines. They enter phase B and switch to the V.21 channel 2 modem at 300 bits per second. This is defined in T30 clause 5.
Like the fax itself in the ECM case, T30 messages are encapsulated in HDLC frames, which also contain control fields and error detection fields.
The goal of phase B is to negotiate the modem for phase C. The most common one is V.17 at 14,400 bps. V.29 (up to 9,600 bps) and V.27ter (up to 4,800 bps) are common fallback options in bad network conditions. V.34 (Super G3 Mode) can go up to 33,600 bps but isn’t as widely supported.
Working on an eFax solution means that at least part of the call goes over the Internet. But T30 fax predates the Internet, and really doesn’t deal well with packet loss and jitter. It also doesn’t work with modern voice codecs like Opus, or modern VoIP features like echo cancellation. Anything that tries to optimize speech will mess with fax calls.
The solution to that problem is T38: a standard to carry fax calls across IP networks.
The name makes it sound like an improvement over T30, but they are actually completely different things that are used together. T38 provides a transport for fax data that’s more adapted to the realities of the Internet.
That transport change can be completely invisible to the fax machine. You can just put a T38 gateway (that acts like a modem of sorts) between the machine and the Internet:

Clause 7 of T38 defines IFP (Internet Facsimile Protocol), a protocol for exchanging fax data that can be used in conjunction with either TCP or UDP. An IFP packet is a wrapper for T30 data (either actual fax data or a T30 control message).
Note that while T38 can also be used over TCP, it’s not as common. The main problem of TCP is that it uses retransmission to deal with packet loss. That doesn’t work well with fax, because fax is sensitive to timing.
When using UDP, the IFP packet is itself wrapped into a UDPTL packet. UDPTL provides:
UDPTL packets can then be wrapped in UDP frames.
T38 is usually negotiated through a mid-call re-INVITE. It’s sent as soon as the sender has received the CED, which indicates that the other side is indeed a fax machine.
The re-INVITE contains an SDP that looks like:
m=image 40002 udptl t38
c=IN IP4 192.0.2.5
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxRateManagement:transferredTCF
a=T38FaxMaxBuffer:2000
a=T38FaxMaxDatagram:528
a=T38FaxUdpEC:t38UDPRedundancy
The recipient responds with either:
This is all defined in Annex D of the T38 document.
…
That’s about all I know about fax! Thanks for reading and do let me know if you found any mistakes!
But please don’t reach out to me directly for support :) ↩︎
Of course, my understanding still isn’t perfect. Please do reach out to me if you spot mistakes in this post! ↩︎
I know it should really be written as “T.4” (and T.6, T.30, T.38 etc.), but it gets very tedious when you type these things many times a day. ↩︎
Group 1 relies on a recommendation (T2) that was marked obsolete in 1996. Group 2 machines are no longer manufactured and even if you do run into one, it will understand T30. ↩︎
That’s for sure true for Dialpad’s eFax solution. ↩︎
CNG is actually optional. Most of the time, the recipient is a fax machine that can safely assume that it only ever receives calls from other fax machines. CNG is only useful for shared lines, when the recipient wants to route the call based on whether it’s fax or voice. ↩︎
Since ECM removes transport errors, it can be used to fax a binary file. Check out T434. ↩︎