WebRTC

Setup WebRTC Phone in Asterisk / FreePBX and Resolve Call Not Coming

MYLINEHUB Team • 2026-03-14 • 18 min

Complete practical guide to set up a WebRTC browser phone on Asterisk and FreePBX, fix the case where presence NOTIFY arrives but the call does not ring, and correctly configure Max Contacts, Remove Existing, DTLS-SRTP, ICE, NAT, and multi-browser ringing.

Setup WebRTC Phone in Asterisk / FreePBX and Resolve Call Not Coming
📞 WebRTC 🧩 Asterisk ⚙️ FreePBX 🛠️ Troubleshooting

Setup WebRTC Phone in Asterisk / FreePBX and Fix “Call Not Coming” 🚀

This guide walks through the real production setup and debugging path for a browser-based WebRTC phone using Asterisk and FreePBX. It is written around a very specific issue that confuses many teams: the extension looks registered, presence updates arrive, but the browser phone does not ring on an incoming call.

The most important clue in this case was: NOTIFY was coming, but INVITE was not. That means Asterisk knew the extension state, but it was not actually choosing the browser contact as a real incoming call destination.

🔍 Core diagnosis in one line: if your browser receives NOTIFY but does not receive INVITE, the PBX knows the extension exists — but it is not truly delivering the call to that browser contact.

🚨 Main symptom

Presence says “Ringing” or “On the phone”, but the browser never receives a true incoming call.

🧭 Real meaning

NOTIFY means state update. INVITE means actual ringing. Only INVITE proves call delivery.

⚠️ Root cause

The extension may look registered, but Asterisk is not retaining or selecting the browser contacts correctly.

✅ Fastest fix

Use Max Contacts > 1, set Remove Existing = No, re-register all browsers, then verify live INVITEs.

📅 Date context: This article is based on the exact troubleshooting path reviewed on 2026-03-14, using extension 10000001, PJSIP, browser WebRTC registration, FreePBX extension screens, and Asterisk contact-selection analysis.

📚 What this guide covers

The article below is intentionally split into collapsible sections so it stays easy to read on both desktop and mobile. Tap the section header or the triangle arrow to expand each part.

🧠

The real meaning of “NOTIFY comes but call does not come”

This is the core concept behind the whole problem.

This is the single most important concept in the entire issue. A browser can receive SIP traffic and still not receive the actual call. In this case, the system was sending presence updates such as Event: presence with values like Ringing or on-the-phone.

❌ Presence NOTIFY is not the call. It only tells subscribers that the extension state changed. It does not prove that Asterisk sent a real incoming INVITE to the browser contact.

NOTIFY sip:browser-contact@... SIP/2.0
Event: presence
...
<note>Ringing</note>
<rpid:on-the-phone />

A real browser ring only happens when Asterisk sends an actual SIP invite to the registered contact:

INVITE sip:random-contact-id@client-ip:port;transport=ws SIP/2.0
📣
NOTIFY means the PBX is broadcasting extension state or presence information.
📞
INVITE means the PBX is actually trying to deliver the incoming call to a real contact.
200 OK means the endpoint accepted or answered, but it still does not guarantee every media scenario is correct.
💡 Simple summary: if you only see NOTIFY, the PBX knows the extension state. If you do not see INVITE going to the browser contact, then the PBX is not actually delivering the incoming call there.

What we confirmed in this exact debugging case

The setup was mostly right — but one contact-handling detail was critical.
✅ Confirmed

Dial target is correct

The extension was configured with Dial = PJSIP/10000001, which is the correct target for ringing contacts attached to the extension endpoint/AOR.

✅ Confirmed

Most WebRTC options were already enabled

ICE, AVPF, RTCP mux, DTLS-SRTP, Rewrite Contact, Force rport, RTP Symmetric, and WebRTC defaults were already present.

🚨 Critical gap

Contact retention was the real issue

For multiple browsers to ring, Asterisk must keep multiple valid contacts under the same AOR. If contacts are replaced or dropped, only one browser rings — or none.

🧭 Main conclusion: Find Me / Follow Me is not what makes multiple browser phones ring on one PJSIP extension. If extension 10000001 has several valid contacts under its AOR, then PJSIP/10000001 can already fork the call to those contacts. Follow Me is separate routing logic. It is not the main mechanism for multiple browser registrations.

1
The extension existed and could publish state.
So the problem was not “extension missing” or “WebRTC completely broken.”
2
The browser looked connected.
That created a false sense of success, even though Asterisk was not truly delivering the call there.
3
The real question became:
“When the incoming call arrives, which contacts does Asterisk actually invite?”
🛠️

Asterisk first: what to check before changing more FreePBX settings

Always prove the backend truth before guessing from the GUI.

Always debug this from the Asterisk side first. FreePBX generates configuration, but Asterisk decides: which contacts exist, which are valid, and who receives the INVITE.

📌 Asterisk checklist
Confirm the endpoint exists. Make sure you are dialing the endpoint you think you are dialing.
Confirm the AOR contacts. If multiple browser phones should ring, the AOR must show multiple contacts.
Confirm contact retention. New registrations must not keep evicting older ones.
Confirm live INVITEs. Use the PJSIP logger and verify real SIP delivery during a test call.
🎯 What you’re trying to prove
✅ The endpoint points to the correct AOR
✅ The AOR contains all expected browser contacts
✅ Contacts are stable and not expiring immediately
✅ The credentials and registration path are actually matching the client
✅ Asterisk sends INVITE to those contacts at call time

🖥️ Run these commands first

asterisk -rx "pjsip show endpoint 10000001"
asterisk -rx "pjsip show aor 10000001"
asterisk -rx "pjsip show contacts"
asterisk -rx "pjsip show auth 10000001"
asterisk -rx "pjsip show registrations"

You should also inspect the generated config on disk:

grep -Rin "10000001" /etc/asterisk/pjsip*.conf

⚠️ Do not keep guessing in the GUI first. If pjsip show aor 10000001 does not show multiple contacts, no wording in FreePBX will change that backend reality.

📞

How multi-browser ringing actually works

This is where many teams mix up registration, presence, and real call forking.

When several browser phones register using the same extension credentials, Asterisk can store them as multiple contacts under the extension’s AOR. If the AOR allows enough contacts and does not replace older ones, dialing the endpoint can fork the call to those registered browsers.

; Conceptual behavior
endpoint 10000001  -> linked to AOR 10000001
AOR 10000001       -> stores multiple dynamic contacts
Dial(PJSIP/10000001)

1️⃣ max_contacts

Must be greater than 1 if more than one browser should remain active.

2️⃣ remove_existing

Must not keep evicting older contacts when new registrations appear.

3️⃣ Stable registration

Contacts must remain reachable and valid when the incoming call arrives.

4️⃣ Real delivery

Asterisk must actually send INVITE to each contact.

🚨 Key trap in this case: the browser may still show registered, presence NOTIFY may still arrive, and the extension may look alive — but Asterisk may have only one surviving call-eligible contact, or may not be selecting the browser contact for the call at all.

⚠️

The exact failure case: Max Contacts and Remove Existing behavior

One of the most common reasons browser phones stop ringing correctly.

This is one of the most common reasons WebRTC browser calls do not reach all open browser phones — and it matches the issue pattern discussed here exactly.

max_contacts = 1
Only one active contact is allowed, so only one browser can remain as a valid incoming-call target. If you expect several tabs, browsers, or devices to ring together, this is too restrictive.
remove_existing = yes
New registrations can replace older contacts. That means users may think older browsers are still “connected,” while Asterisk has already pushed them out of call eligibility.
Reconnect churn
If browser sessions reconnect often, contacts can keep changing, expiring, or reordering. When the call actually arrives, the contact you expect may no longer be active.

✅ Operational rule: if you want all browser phones on the same extension to ring, the PBX must keep multiple valid contacts alive at the same time. A strong baseline is: Max Contacts = 10 and Remove Existing = No.

🧩 Why teams get confused: presence can still work even when Asterisk has replaced older contacts, dropped older registrations, or is no longer inviting the browser you expect.
🌐

Raw Asterisk WebRTC baseline

Even if FreePBX generates the config, it helps to understand the Asterisk-side logic.

A browser SIP client is not the same as a normal UDP SIP phone. It needs WSS signaling, DTLS-SRTP media, and endpoint behavior that is friendly to WebRTC.

📡 Required signaling / transport

  • WSS transport for browser signaling
  • Working TLS certificate
  • WebSocket connectivity without browser certificate errors

🎙️ Required media / NAT behavior

  • media_encryption=dtls
  • ice_support=yes
  • use_avpf=yes
  • rtcp_mux=yes
  • rewrite_contact=yes
  • rtp_symmetric=yes
  • force_rport=yes
  • direct_media=no

🧱 Conceptual Asterisk PJSIP example

; Example structure only.
; FreePBX will normally generate these values for you.

[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0
allow_reload=yes

[10000001]
type=endpoint
aors=10000001
auth=10000001
transport=transport-wss
webrtc=yes
use_avpf=yes
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
ice_support=yes
rtcp_mux=yes
rewrite_contact=yes
rtp_symmetric=yes
force_rport=yes
direct_media=no
context=from-internal
disallow=all
allow=opus,ulaw,alaw

[10000001]
type=auth
auth_type=userpass
username=10000001
password=super-secret

[10000001]
type=aor
max_contacts=10
remove_existing=no

ℹ️ Important: the exact generated FreePBX files may differ, but the underlying logic stays the same: one endpoint, one AOR, multiple contacts, one dial target.

🔎

Live debugging: the fastest way to prove the problem

Do not stop at “registered.” Prove real call delivery.

Once multiple browsers are registered, do not stop at “it says connected.” Run a live PJSIP trace while placing a real call to the extension.

asterisk -rvvvvv
pjsip set logger on
core set verbose 5
core set debug 5

Now place a test call to extension 10000001.

✅ What you want to see

INVITE sip:contact-a@client1;transport=ws SIP/2.0
INVITE sip:contact-b@client2;transport=ws SIP/2.0
INVITE sip:contact-c@client3;transport=ws SIP/2.0

🚨 If you see NOTIFY but no INVITE to the browser contact, that is the real failure. At that point, the issue is no longer “browser UI.” It is: Asterisk did not choose that contact as a destination for the call.

🧪 Good test state

All browsers are freshly registered, the AOR shows multiple active contacts, and no reconnect churn is happening during the test.

🧨 Misleading test state

The browser UI says connected, but the AOR shows only one contact or a different contact than the one you expect.

🖼️

FreePBX screen walkthrough for this exact case

Image-first explanation of the real UI path, without repeating the same details in tables again.

The screenshots below are the best way to understand this case visually. Instead of duplicating the same fields in tables and captions, each image here is explained only for what it adds to the diagnosis.

🧠 Reading tip: treat this as a guided UI walkthrough. The screenshots show where the settings live, while the surrounding text explains why they mattered in this failure pattern.

FreePBX extension general tab for extension 10000001
1.PNG · General tab

This screen confirms the extension exists as a real PJSIP extension with the expected identity. In this case, that matters because the issue was not “extension missing” or “wrong extension object.”

FreePBX Find Me Follow Me upper section for extension 10000001
2.PNG · Follow Me upper section

This shows Follow Me was enabled. That is useful context, but it is also why base endpoint testing needed to be simplified later.

FreePBX Find Me Follow Me lower section for extension 10000001
3.PNG · Follow Me lower section

This reinforces that extra routing logic was present. It does not explain the root cause by itself, but it can make troubleshooting noisier if left enabled during testing.

FreePBX Advanced tab upper section showing ICE AVPF and RTCP mux
4.PNG · Advanced WebRTC behavior

This screen shows that the extension was already largely WebRTC-ready at the media and browser-compatibility level. That is an important clue because it shifts attention away from “basic WebRTC support missing” and toward contact selection and retention.

FreePBX Advanced tab with Max Contacts Remove Existing and NAT settings
5.PNG · The most important screenshot

This is the key image in the entire case. It shows the extension was dialing through PJSIP/10000001, had room for multiple contacts, but also had Remove Existing = Yes. That combination can still break multi-browser ringing because Asterisk may keep replacing older browser contacts with newer registrations.

FreePBX Advanced extension options section
6.PNG · Additional extension behavior

This part is not the main cause here, but it helps confirm the extension had broader options configured and was not just a bare-minimum object.

FreePBX Advanced section with recording and start of DTLS configuration
7.PNG · Recording and DTLS area

This screen continues the picture that browser-related media security was present. Again, the case was not blocked at the “WebRTC encryption missing” level.

FreePBX DTLS and optional destinations section for extension 10000001
8.PNG · DTLS completion and optional destination

This completes the visual review of the extension. By this point, the larger pattern is clear: the extension was already substantially configured for browser WebRTC, but the incoming-call problem still depended on whether Asterisk retained the right contacts and sent actual INVITEs.

⚠️ Key lesson from the screenshots: a FreePBX extension can look highly WebRTC-ready in the GUI, while the real failure still happens at the Asterisk decision layer: which contacts survive, and which contacts receive the INVITE.

⚙️

The FreePBX settings that matter most in this case

Not a repeated field dump — just the settings that actually changed the outcome.

Since the screenshots already show the interface, this section focuses only on the settings that really mattered to the diagnosis. The goal here is not to repeat every visible field again, but to isolate the few settings that changed the call outcome.

📞
Dial target: PJSIP/10000001
This was correct and important because it means Asterisk should ring all valid contacts under the endpoint/AOR if they are actually retained.
👥
Max Contacts: keep it high enough, such as 10
This allows multiple browser sessions to exist under the same extension instead of forcing a single surviving contact.
🚫
Remove Existing: set it to No
This was the most important functional correction in the case because older browser contacts should not be evicted by newer registrations.
🌐
NAT and contact helpers: keep Rewrite Contact, RTP Symmetric, and Force rport enabled
These help Asterisk keep usable signaling and RTP behavior for remote browser endpoints.
🔐
WebRTC media baseline: keep ICE, AVPF, RTCP Mux, DTLS-SRTP, and DTLS support enabled
These were already aligned with browser expectations and should remain part of the baseline.
🚦
Transport clarity: a dedicated WSS transport can make debugging easier
Auto may still work, but a browser-only extension often becomes easier to reason about when the transport path is explicit.

✅ Clean baseline: keep the good WebRTC media settings, change Remove Existing to No, keep Max Contacts high enough, and then verify with Asterisk CLI that multiple contacts truly exist and are actually invited.

🌍

FreePBX global settings you should also verify

Extension settings alone are not enough for browser WebRTC.

Browser WebRTC depends not only on extension settings, but also on PBX-wide transport, TLS, NAT, certificate, and network behavior.

🧰 FreePBX → Asterisk SIP Settings → PJSIP

  • WSS transport is enabled and reachable
  • TLS certificate is valid for the exact browser domain
  • External Address is correct
  • Local Networks are correct
  • RTP port range is open and routed correctly

🖥️ Browser/WebRTC operational checks

  • No browser TLS warning or certificate mismatch
  • WebSocket connects successfully over WSS
  • Microphone permission is granted
  • ICE candidates are being generated correctly
  • TURN can be added if direct ICE paths are weak in production networks

📌 Very important: an extension can look perfectly configured while the PBX still advertises the wrong public address or exposes the wrong certificate path. In that case the browser may register, but call delivery, media, or contact usability can still break.

🔁

About Find Me / Follow Me: useful for routing, not the core fix here

Helpful in some call flows, but not the main solution for this problem.

In this case, Find Me / Follow Me was enabled and the extension itself was placed in its own follow-me list. That is not the cleanest way to solve multi-browser ringing.

🧪 Recommended testing approach: disable Find Me / Follow Me while debugging the base endpoint, or at minimum remove the self-reference from the Follow-Me list. First prove that PJSIP/10000001 can ring all retained contacts directly.

🎯 Why disable it during testing?

It removes extra dialplan complexity and lets you focus on the real contact-selection issue.

🧩 What confusion does it cause?

Teams may mix up routing logic with contact retention and think Follow Me is the real fix.

✅ What should be proven first?

That the base PJSIP endpoint already forks correctly to multiple active browser contacts.

⚠️ Important: Follow Me can still be useful in other routing scenarios. But for this problem — multiple browser phones on one PJSIP extension should ring — the first priority is to keep multiple valid contacts under the AOR and verify multiple INVITEs.

🚀

The fastest fix path for this exact case

A clean action plan from broken state to verified ringing.
Set Remove Existing = No.
Keep Max Contacts = 10 or another value above your actual browser count.
Disable Find Me / Follow Me during base testing.
Apply config and fully re-register all browser phones.
Run pjsip show aor 10000001 and confirm multiple contacts appear.
Run pjsip set logger on and place a real incoming call.
Confirm that Asterisk sends INVITE to each active browser contact.

📋 Copy-paste debug commands

# Inspect endpoint and AOR state
asterisk -rx "pjsip show endpoint 10000001"
asterisk -rx "pjsip show aor 10000001"
asterisk -rx "pjsip show contacts"
asterisk -rx "pjsip show auth 10000001"
asterisk -rx "pjsip show registrations"

# Inspect generated PJSIP config
grep -Rin "10000001" /etc/asterisk/pjsip*.conf

# Start live Asterisk logger
asterisk -rvvvvv
pjsip set logger on
core set verbose 5
core set debug 5

🎉 Expected fixed state: the AOR shows multiple active contacts, and the incoming call produces multiple INVITEs. At that point, all open browser phones for extension 10000001 can ring together.

Try it

Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.

💬 Try WhatsApp Bot ▶️ Watch CRM YouTube Demos
Tip: Comment “Try the bot” on our YouTube videos to see automation in action.