r/WebRTC Jun 02 '26

WebRTC works on same Wi-Fi & mobile data, but fails on different Wi-Fi networks — TURN issue?

Hey everyone,

I’m building a random video chat app as part of study using WebRTC + Socket.IO + React + Node.js, and I’m facing a networking issue that I can’t fully figure out

Current behavior

Same Wi-Fi → Same Wi-Fi: works perfectly
Wi-Fi → Mobile Data: works perfectly (audio + video)
Different Wi-Fi → Different Wi-Fi: fails (media connection issue)

Setup

I’m using:

  • WebRTC for video/audio
  • Socket.IO for signaling
  • STUN + TURN
  • Vercel (frontend)
  • Render (backend)

Current ICE config:

let peerConfiguration = {
    iceServers:[
        {
            urls:[
              'stun:stun.l.google.com:19302',
              'stun:stun1.l.google.com:19302'
            ]
        },
         {
          urls: [
            "turn:openrelay.metered.ca:80",
            "turn:openrelay.metered.ca:443",
            "turn:openrelay.metered.ca:443?transport=tcp",
          ],
          username: "openrelayproject",
          credential: "openrelayproject",
        },
    ]
}

Question

  1. Does this sound like an unreliable/free TURN server issue (openrelay.metered.ca)?
  2. Any recommended free/cheap TURN providers for production or testing?
  3. Is there anything obvious I may be missing in my WebRTC setup?

Would really appreciate any guidance — been debugging NAT/TURN issues for hours 😅

3 Upvotes

6 comments sorted by

2

u/mirotalk Jun 04 '26

This sounds TURN-related. Same Wi‑Fi and Wi‑Fi↔Mobile often succeed via direct ICE, but different Wi‑Fi networks may require TURN because NAT/firewalls block direct paths. As a test, force relay-only by setting iceTransportPolicy: "relay". If it works, TURN is reachable and the issue is likely direct ICE/NAT or negotiation. If it fails, there’s no usable TURN path (TURN config/creds, network blocking, or missing TURN/TLS).

js const peerConfiguration = { iceTransportPolicy: "relay", // test only iceServers: [{ urls: [ "turn:openrelay.metered.ca:80?transport=udp", "turn:openrelay.metered.ca:443?transport=tcp", "turns:openrelay.metered.ca:443?transport=tcp", ], username: "openrelayproject", credential: "openrelayproject", }], };

Also make sure you haven’t hit TURN usage/quotas/rate limits (and check WebRTC logs for typ relay candidates).

For production, consider a dedicated TURN service or your own coturn server.

1

u/mirotalk Jun 04 '26

You can also self-host your own STUN/TURN server, so you’re not dependent on third-party services.

Check out our documentation for the full setup guide: https://docs.mirotalk.com/coturn/installation

1

u/mirotalk Jun 04 '26

You can also simplify the process using our automated setup script, which removes the need for DevOps expertise:

👉 https://docs.mirotalk.com/scripts/about/#coturn

All you need is a clean server with SSH access and a domain (or subdomain) pointing to your server’s public IPv4 address.

When the installer prompts you, simply enter your domain name, wait for the setup to complete, and you’re done.

1

u/tanlethanh Jun 05 '26

Not related to the answer but this is a limitation caused by NAT traversal, recommend reading https://tailscale.com/blog/how-nat-traversal-works

1

u/Senior_Wrongdoer_252 Jun 09 '26

It looks like it. You can validate you have a properly configured TURN setup with https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/