The complaint arrives in a specific shape. Calls connect. Audio is clean in both directions. People can talk for an hour without issue. But when someone dials into the conference bridge and types the access code, nothing happens. Or the bank's IVR keeps saying "I didn't catch that." Or the voicemail system ignores the PIN.
Nothing is wrong with the audio path, which is why the usual diagnostics come back clean. The problem is that a keypress is not audio. Or rather, it stopped being audio somewhere around 2001, and there are now three different ways to carry one, and both ends of the call have to have chosen the same one.
The problem underneath
DTMF stands for Dual-Tone Multi-Frequency, and the name describes the original mechanism exactly. Press 5 on an analog phone and it generates two sine waves simultaneously: 770 Hz and 1336 Hz. Every digit is a unique pair drawn from four row frequencies and four column frequencies. A detector on the far end listens for that pair and knows which key you pressed.
This design was excellent for the network it was built for. An analog circuit carries whatever audio you put on it, faithfully, end to end. The tones arrive as the tones you sent.
VoIP breaks that assumption in a way that is easy to miss, because it breaks it selectively.
The moment audio is compressed, it stops being a faithful reproduction and becomes a reconstruction. G.711 is waveform coding: it samples the signal and sends the samples, so a DTMF tone comes out roughly the way it went in. But low-bitrate codecs work completely differently. They carry a model of human speech: parameters describing a vocal tract, an excitation signal, a pitch. The decoder rebuilds something that sounds like the original to a human ear.
DTMF tones are not speech. They are two pure sine waves, which is close to the worst possible input for a codec built around a model of the human voice. What comes out the far end may still sound like a beep to you while being distorted well past what a detector will accept. The digit is, functionally, gone.
This is why inband DTMF has the most confusing failure signature in VoIP. It works fine, until a call negotiates a different codec, and then it doesn't, and nothing else about the call changed.
Method one: inband
Inband DTMF is the original approach carried forward unchanged. The tones are generated as audio and travel inside the voice stream along with everything else. No signalling, no negotiation, no separate mechanism. If the audio arrives, the tones arrive.
When it works: on G.711 end to end, with no transcoding anywhere in the path. Toll-quality uncompressed audio reproduces the tones well enough for reliable detection.
When it fails: whenever a compressed codec is involved, and whenever packet loss clips the tone. There is a subtler failure too: packet loss concealment. When a packet goes missing mid-tone, the decoder invents plausible audio to fill the gap. That is exactly right for speech and exactly wrong for a tone, because the invented audio may extend the tone, break it into two shorter tones, or shift its frequency content. A single press can be detected as two, or as nothing.
Inband is not something you should choose today. It is something you should recognise when you inherit it.
Method two: RFC 2833 / RFC 4733 telephone-events
This is the method that solved the problem, and it is what almost everything uses now.
Instead of sending the sound of a keypress, the sender describes the keypress as data: the user pressed 5, it has lasted this long, at this volume. That description travels in the RTP stream alongside the audio, but in its own payload type, so it is never handed to the codec at all. Nothing gets compressed, so nothing gets mangled.
You will hear this called RFC 2833 almost universally. RFC 2833 was obsoleted by RFC 4733 in 2006, with RFC 4734 covering tones more broadly, but the old number stuck in vendor documentation and in conversation. When someone says "2833," assume they mean telephone-events in general.
The events themselves are simple. Digits 0 through 9 are events 0 through 9. * is 10, # is 11, and the rarely-used A through D keys are 12 through 15. Each event packet carries the event code, a volume, a duration, and an end bit. Because a keypress has a duration, the sender emits a series of packets as the key is held, then marks the final packet with the end bit, usually sending that final packet three times, since losing the end marker is worse than sending it redundantly.
How it gets negotiated is where the failures start. Telephone-event uses a dynamic payload type, meaning the number identifying it is not fixed by the standard; it is chosen per call, from the 96–127 range, and announced in the SDP:
m=audio 49170 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
That says: this call carries G.711 µ-law as payload type 0, and telephone-events as payload type 101, supporting events 0 through 15. Payload type 101 is a near-universal convention, which is a blessing right up until you meet a device that picks 96, or 100, or 127.
Each side advertises the number it wants to receive. A correct implementation reads the far end's SDP and sends events using the far end's number. An implementation that assumes 101 because 101 is what everyone uses will send events the far end does not recognise. And because the packets are still valid RTP, nothing errors. They are simply ignored.
Method three: SIP INFO
The third method abandons the media path entirely and sends keypresses as SIP requests in the signalling channel:
INFO sip:[email protected]:5060 SIP/2.0
CSeq: 5 INFO
Content-Type: application/dtmf-relay
Content-Length: 22
Signal=5
Duration=250
It works, and it has one real advantage: it is completely immune to anything that happens to the audio. Codecs, packet loss, and transcoding cannot touch it.
It also has two problems that keep it a fallback rather than a default.
The first is that there is no single standard for the body. application/dtmf-relay in the format above is a Cisco convention that became a de facto standard; application/dtmf exists too, with a different body; some implementations use neither. Two devices can both "support SIP INFO" and still fail to understand each other.
The second is timing. Media and signalling take different paths through the network, and often through different intermediaries. A digit sent as an INFO can arrive noticeably out of step with the audio around it: usually harmless for an IVR menu, occasionally a real problem for anything time-sensitive, like DTMF-controlled recording or a system that expects digits to align with prompts.
Use SIP INFO when a path genuinely will not carry telephone-events. Do not use it as a first choice.
How it actually fails
The failures are recognisable once you know the shapes.
| Symptom | Usual cause | |---|---| | IVR ignores every keypress | Method mismatch. One end sends telephone-events, the other listens inband, or vice versa | | Digits register twice (pressing 1 gives 11) | Two methods active simultaneously. The device sends inband and telephone-events; the far end detects both | | Works internally, fails to outside numbers | Your PBX and phones agree with each other. The carrier expects something else. Classic trunk-side mismatch | | Worked yesterday, broken today, nothing changed | A codec changed. Inband DTMF that was riding on G.711 met a call that negotiated something compressed | | Digits occasionally dropped under load | Packet loss on RTP events, or an end bit lost so a press never terminates cleanly | | One long press becomes several digits | Duration and end-bit handling. Either the sender is not marking the end, or a middlebox is regenerating events | | Works one direction only | Each side advertises what it can receive. The two directions are negotiated separately and can disagree independently |
That last one deserves emphasis, because it is the most confusing in practice. Outbound digits working while inbound digits fail is not a contradiction: it is two independent negotiations, one of which succeeded.
Diagnosing it
The good news is that DTMF problems are unusually easy to confirm from a packet capture, because the evidence is unambiguous.
Read the SDP on both sides first. Look at the m=audio line and the a=rtpmap entries in the INVITE and in the answer. Is telephone-event offered by both? Do both sides list the same payload type number for it? A mismatch here explains everything and takes ten seconds to spot.
Then look at what is actually in the RTP. If both sides negotiated telephone-event as 101, filter for RTP packets with payload type 101 while someone presses keys. Three outcomes: events are present and correctly numbered, meaning the problem is at the far end's detector; events are present with the wrong payload type, meaning the sender ignored the negotiated number; or there are no events at all, meaning the sender is not using the method it agreed to.
Check for INFO messages in the signalling. If digits are arriving as SIP INFO while the far end is watching RTP, you have your answer.
Then the field test that needs no capture at all: force the call to G.711 and try again. If digits start working, you were sending inband and a codec was destroying them. That single test separates the codec-related failures from the negotiation-related ones, and it takes a minute.
Our PCAP analyzer will pull the SIP dialogs and RTP streams out of a capture and map them to each other, which makes the SDP-versus-actual-RTP comparison quick. For narrowing a large capture to the call in question first, see how to find the failing call in a huge SIP trace.
What to standardise on
Use RFC 4733 telephone-events everywhere. It is codec-independent, it is what carriers expect, and it is the only method with a real standard behind its wire format. Every modern endpoint supports it.
Send exactly one method. The double-digit problem is entirely self-inflicted. Many devices ship configured to send inband and telephone-events on the assumption that redundancy helps. It does not; it produces duplicates on any far end that listens for both.
Honour the payload type the far end advertised rather than assuming 101. If you are choosing equipment, this is worth testing explicitly, because it is a common enough bug that it is worth knowing about before deployment rather than after.
Let an SBC do the translation when you cannot control both ends. DTMF interworking is one of the standard jobs a session border controller does: accept telephone-events from your PBX, emit SIP INFO to a carrier that requires it, and keep both sides unaware of the other's preference. If you are already running one for trunk termination, this is a configuration line rather than a project.
Test the path you actually use. DTMF working between two desk phones on the same PBX proves very little about DTMF working into your carrier's IVR. The interesting failures live at boundaries: trunk handoffs, transcoding points, anything that rebuilds the media stream. If you are mapping call flows through menus and queues, the IVR planner is a useful way to see where those boundaries sit before you start testing.
DTMF is one of several things that work perfectly until a call crosses a boundary and something re-encodes it. For the wider category, see Common SIP Problems and What They Look Like, or the SIP Signaling From the Wire Up series for how the negotiation underneath all of this works.
Frequently Asked Questions
Why does my IVR not recognise keypresses over VoIP?+
Almost always a DTMF transport mismatch. There are three ways to carry a keypress over VoIP -- as audio in the media stream, as a named event inside RTP (RFC 2833/4733), or as a SIP INFO message in the signalling -- and both ends have to agree. If your PBX sends one method and the far end listens for another, the audio path works perfectly, the call sounds fine, and the digits simply never arrive.
What is the difference between RFC 2833 and inband DTMF?+
Inband sends the actual dual-tone audio through the voice stream, so it depends on the codec reproducing those tones faithfully. RFC 2833 (updated by RFC 4733) sends the keypress as a named event in its own RTP payload type -- the digit, its duration, and its volume as data rather than sound. Inband works on G.711 and degrades badly on compressed codecs; RFC 2833 is codec-independent, which is why it became the default.
Why do my DTMF digits register twice?+
Usually because two methods are active at once. If a device sends the tone inband and also sends RFC 2833 events for the same keypress, a far end that listens for both detects each press twice. Pressing 1 produces 11. The fix is to disable one method rather than to adjust detection thresholds.
Does DTMF work differently on G.729 than on G.711?+
Yes, if you are sending inband. G.711 is waveform coding -- it reproduces whatever audio you give it, including pure tones, well enough for a detector. G.729 and other low-bitrate codecs model human speech, and DTMF tones are not speech, so the compressed output can be distorted past the point a detector recognises it. This is why inband DTMF appears to work and then breaks the moment a call negotiates a compressed codec.
Share
Want to know when we publish new articles? Sign up for updates