WEBRTC • TURN SERVER • GUIDE

Free TURN server for WebRTC: options, setup and limits

A TURN server relays the audio and video of a WebRTC call when two devices cannot connect directly, which happens on some mobile networks, office Wi-Fi and strict firewalls. You can get TURN for free in three ways: run the open-source coturn yourself, use a public free server for testing, or use a service that includes it. RTCExpress includes TURN relay on its Free plan, with 1:1 voice calls and 2,000 voice minutes a month.

When you need TURN

A WebRTC call first tries to connect the two devices directly. A STUN server helps by telling each device its public address. Most calls connect this way and never touch a relay.

Some networks block direct connections: carrier-grade NAT on mobile data, symmetric NAT on routers, and company firewalls that only allow certain ports. On those networks the call either fails to connect or connects with no audio. A TURN server fixes this by relaying the media, so both devices only need to reach the relay.

Rule of thumbSTUN alone works in development, because your test devices are usually on the same friendly network. Real users on mobile data are where calls without TURN start failing.

Option 1: run your own TURN server with coturn

coturn is the standard open-source TURN server. The software is free; you pay for a server with a public IP address and for the bandwidth of relayed calls. A small cloud VM is enough to start.

A minimal configuration with time-limited passwords:

# /etc/turnserver.conf
listening-port=3478
fingerprint
use-auth-secret
static-auth-secret=CHANGE_ME_TO_A_LONG_RANDOM_STRING
realm=turn.example.com
external-ip=203.0.113.10
min-port=49160
max-port=49200
no-cli
# Never relay into private or cloud-metadata addresses
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
  • Open UDP and TCP port 3478, and the UDP relay range (49160–49200 above), in your firewall.
  • Set external-ip to the server's public IP address when it runs behind cloud NAT.
  • Keep the denied-peer-ip lines, so nobody can use your relay to reach private networks.

With use-auth-secret, your backend creates a separate login for each user that expires on its own, instead of one shared password:

// Server side: one short-lived TURN login per signed-in user
import { createHmac } from "node:crypto";

export function turnCredentials(userId, secret, ttlSec = 3600) {
  const username = `${Math.floor(Date.now() / 1000) + ttlSec}:${userId}`;
  const credential = createHmac("sha1", secret).update(username).digest("base64");
  return { urls: "turn:turn.example.com:3478", username, credential };
}

Only give these credentials to signed-in users. A TURN server with a fixed password in your app's code is an open relay that anyone can use on your bandwidth.

Option 2: public free TURN servers

Lists of free public TURN servers are easy to find. They are useful for a quick experiment, but they are a poor fit for an app with real users:

  • Credentials are shared or public, so anyone can use the same relay and its capacity.
  • There is no promise about uptime, speed or how long the server will stay online.
  • Your users' call media passes through a server you know nothing about. It is encrypted by WebRTC, but you still depend on a stranger's infrastructure.

Option 3: use a service that includes TURN

Calling platforms run STUN, TURN and signaling for you, so you don't operate a relay at all. With RTCExpress, TURN is part of every plan, including Free:

  • Each signed-in user gets their own TURN login that expires after one hour. The SDKs fetch it automatically from /v1/ice using the user token from your backend.
  • Without a valid user token, only STUN is returned, so the relay can't be used by strangers.
  • The Free plan includes 1:1 voice calls with 2,000 voice minutes a month and in-app chat; Starter ($9/month) adds group voice and 30,000 minutes. See pricing.

Current limits, stated honestly: the relay runs in one region (US West), over UDP on port 3478. TURN over TLS on port 443, which helps on the strictest company networks, is not offered yet.

How to check that TURN works

Force the browser to use only relayed connections. If you see a relay candidate, the TURN server and credentials are correct:

// Browser: allow only relayed candidates, so the call must go through TURN
const pc = new RTCPeerConnection({
  iceServers: [turn], // from your backend
  iceTransportPolicy: "relay",
});
pc.onicecandidate = (e) => e.candidate && console.log(e.candidate.candidate);
pc.createDataChannel("test");
await pc.setLocalDescription(await pc.createOffer());
// A line containing "typ relay" means TURN works.

You can also paste your TURN details into the WebRTC Trickle ICE sample page. For a real test, call between a phone on mobile data (Wi-Fi off) and a laptop on Wi-Fi.

Frequently asked questions

Is there a free TURN server?

Yes, in three ways: run the free, open-source coturn on your own server (you pay for the server and bandwidth), use a public free TURN server (fine for experiments, not for production), or use a service that includes TURN. RTCExpress includes TURN relay on its Free plan, together with 1:1 voice calls and 2,000 voice minutes a month.

What is the difference between STUN and TURN?

STUN only tells a device its public address so two devices can try to connect directly. It is cheap and free STUN servers are common. TURN relays the actual audio and video when a direct connection fails, so it uses real bandwidth.

Do I need a TURN server for one-to-one calls?

Yes, if your app must work for everyone. Most calls connect directly, but users on some mobile networks, office Wi-Fi or strict firewalls can only connect through a relay. Without TURN those calls fail to connect or have no audio.

Is Google's STUN server a TURN server?

No. stun.l.google.com is a free STUN server. It cannot relay media, so it does not help when a direct connection is blocked.

How much bandwidth does a TURN server use?

Only relayed calls use it. A voice call uses roughly 0.3 to 0.5 MB per minute in each direction, and a video call several MB per minute, depending on resolution. The server receives and sends each stream, so count both.

Skip running a relay

Create a free project and follow a tutorial: TURN, STUN and signaling are already set up.

Create free accountVoice calling tutorial