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:
fixed_region: use exactly this region. If the slug does not exist, the request fails with422 {"error":"Specified Region Not Found"}. If the region is offline or in maintenance, it fails with422 {"error":"Region Offline"}.preferred_region: use this region if it exists and is online. Otherwise, silently fall through to step 3.- GeoIP: look up the location of the client IP (see below) and use the nearest region that is online.
- 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:
- the
X-TURN-CLIENT-IPheader - the first valid IP in the
X-Forwarded-Forheader - the IP address of the connection
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:
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_regionset to a non-trial region:422 {"error":"Specified Region Not Found"}preferred_regionset 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.