Concepts / Regions & geo-routing

Regions & geo-routing

Turnix runs TURN servers in several regions. Each credential points at exactly one region, through the host <region>.turnix.io. Relaying through a region close to your users keeps latency low.

How Turnix picks the region#

For every POST /credentials/ice request, Turnix decides in this order:

  1. fixed_region: use exactly this region. If the slug does not exist, the request fails with 422 {"error":"Specified Region Not Found"}. If the region is offline or in maintenance, it fails with 422 {"error":"Region Offline"}.
  2. preferred_region: use this region if it exists and is online. Otherwise, silently fall through to step 3.
  3. GeoIP: look up the location of the client IP (see below) and use the nearest region that is online.
  4. Fallback: if the IP cannot be located, use the platform's default region.

Use fixed_region when you must keep traffic in one place, for example for data residency. Use preferred_region when you have a good default but would rather get a working credential than an error.

Which IP is used for GeoIP#

Turnix determines the client IP from the request, in this order:

  1. the X-TURN-CLIENT-IP header
  2. the first valid IP in the X-Forwarded-For header
  3. the IP address of the connection
Forward the end user's IP

You call the API from your backend, so without a header Turnix sees your server's IP and picks the region closest to your data center, not to your user. Send the user's public IP in X-TURN-CLIENT-IP:

bash
curl -X POST https://turnix.io/api/v1/credentials/ice \
  -H "Authorization: Bearer $TURNIX_API_TOKEN" \
  -H "X-TURN-CLIENT-IP: 203.0.113.42"

If your backend runs behind a load balancer, read the user's IP from your framework's trusted-proxy setting (for example req.ip in Express with trust proxy, or request.remote_ip in Rails), not from a raw header the user could forge.

Listing regions#

GET /regions returns all public regions with their slug, location and status. The dashboard shows the same list, with each region's TURN hostname, under Server.

A region is usable when both is_online and is_operational are true.

Regions and plans#

On the free plan, credentials are issued only in regions marked is_trial: true. Requests for other regions behave as follows:

  • fixed_region set to a non-trial region: 422 {"error":"Specified Region Not Found"}
  • preferred_region set to a non-trial region: ignored, GeoIP picks the nearest trial region

Paid plans can use every online region. See Usage, limits & billing.

Region hostnames and ports#

Every region serves the same set of transports on its host:

URL Transport Use
turn:<region>.turnix.io:3478?transport=udp UDP Fastest; the default choice
turn:<region>.turnix.io:3478?transport=tcp TCP Networks that block UDP
turns:<region>.turnix.io:443?transport=tcp TLS over TCP on port 443 Strict firewalls and proxies that allow only HTTPS-like traffic
turns:<region>.turnix.io:443?transport=udp DTLS on port 443 Included for completeness; most browsers ignore it

STUN is served globally at stun:stun.turnix.io:3478.

Always pass all URLs from the response to RTCPeerConnection. The browser tries them in parallel and uses the best one that works.

Last updated October 30, 2026