> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/bluenviron/gortsplib/llms.txt
> Use this file to discover all available pages before exploring further.

# Transport options

> Choose between UDP, TCP, and UDP-multicast transports.

The `Protocol` field on `Client` controls how RTP and RTCP packets are carried between the client and the server. Set it before calling `Start()` or `StartRecording()`.

```go theme={null}
type Protocol int

const (
    ProtocolUDP          Protocol = iota // 0
    ProtocolUDPMulticast                 // 1
    ProtocolTCP                          // 2
)
```

The field is a pointer to `Protocol`. Setting it to `nil` (the default) enables automatic selection.

## Transport comparison

| Value                  | Wire protocol       | When to use                                                           |
| ---------------------- | ------------------- | --------------------------------------------------------------------- |
| `nil` (auto)           | UDP first, then TCP | General purpose. Recommended for most scenarios.                      |
| `ProtocolUDP`          | UDP unicast         | Low-latency LAN environments where packet loss is acceptable.         |
| `ProtocolTCP`          | TCP (interleaved)   | NAT traversal, firewalls, or any network where UDP is blocked.        |
| `ProtocolUDPMulticast` | UDP multicast       | One server sending to many clients simultaneously on a local network. |

## Automatic selection (default)

When `Protocol` is `nil`, the client first attempts UDP. If no packet arrives within `InitialUDPReadTimeout` (default `3s`), it switches to TCP and calls `OnTransportSwitch` to notify you of the change.

```go theme={null}
c := gortsplib.Client{
    Scheme: u.Scheme,
    Host:   u.Host,
    // Protocol is nil — the library tries UDP then falls back to TCP
}
```

## Forcing a specific transport

To lock in a transport without any fallback, point `Protocol` at a value:

<Tabs>
  <Tab title="UDP">
    ```go theme={null}
    proto := gortsplib.ProtocolUDP
    c := gortsplib.Client{
        Scheme:   u.Scheme,
        Host:     u.Host,
        Protocol: &proto,
    }
    ```

    UDP has the lowest overhead and is preferred on reliable local networks.
  </Tab>

  <Tab title="TCP">
    ```go theme={null}
    proto := gortsplib.ProtocolTCP
    c := gortsplib.Client{
        Scheme:   u.Scheme,
        Host:     u.Host,
        Protocol: &proto,
    }
    ```

    TCP carries RTP/RTCP frames interleaved inside the RTSP connection. This avoids the need to open additional ports and works through most firewalls and NATs.
  </Tab>

  <Tab title="UDP-multicast">
    ```go theme={null}
    proto := gortsplib.ProtocolUDPMulticast
    c := gortsplib.Client{
        Scheme:   u.Scheme,
        Host:     u.Host,
        Protocol: &proto,
    }
    ```

    UDP-multicast lets a single stream reach many clients with a single set of packets. The server must advertise multicast addresses in its SDP.
  </Tab>
</Tabs>

## Full options example

The example below sets the transport to automatic along with explicit timeout values:

```go client-play-options/main.go theme={null}
// Package main contains an example.
package main

import (
	"log"
	"time"

	"github.com/bluenviron/gortsplib/v5"
	"github.com/bluenviron/gortsplib/v5/pkg/base"
	"github.com/bluenviron/gortsplib/v5/pkg/description"
	"github.com/bluenviron/gortsplib/v5/pkg/format"
	"github.com/pion/rtcp"
	"github.com/pion/rtp"
)

// This example shows how to:
// 1. set additional client options.
// 2. connect to a RTSP server and read all medias on a path.

func main() {
	// parse URL
	u, err := base.ParseURL("rtsp://myuser:mypass@localhost:8554/mystream")
	if err != nil {
		panic(err)
	}

	// Client allows to set additional client options
	c := gortsplib.Client{
		Scheme: u.Scheme,
		Host:   u.Host,
		// tunneling method.
		Tunnel: gortsplib.TunnelNone,
		// transport protocol (UDP, Multicast or TCP). If nil, it is chosen automatically
		Protocol: nil,
		// timeout of read operations
		ReadTimeout: 10 * time.Second,
		// timeout of write operations
		WriteTimeout: 10 * time.Second,
	}

	// connect to the server
	err = c.Start()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	// find available medias
	desc, _, err := c.Describe(u)
	if err != nil {
		panic(err)
	}

	// setup all medias
	err = c.SetupAll(desc.BaseURL, desc.Medias)
	if err != nil {
		panic(err)
	}

	// called when a RTP packet arrives
	c.OnPacketRTPAny(func(medi *description.Media, _ format.Format, _ *rtp.Packet) {
		log.Printf("RTP packet from media %v\n", medi)
	})

	// called when a RTCP packet arrives
	c.OnPacketRTCPAny(func(medi *description.Media, pkt rtcp.Packet) {
		log.Printf("RTCP packet from media %v, type %T\n", medi, pkt)
	})

	// start playing
	_, err = c.Play(nil)
	if err != nil {
		panic(err)
	}

	// wait until a fatal error
	panic(c.Wait())
}
```

## Tunneling

In addition to the transport protocol, the `Tunnel` field controls whether RTSP is wrapped inside another protocol:

| Value             | Description                                                            |
| ----------------- | ---------------------------------------------------------------------- |
| `TunnelNone`      | Plain RTSP (default).                                                  |
| `TunnelHTTP`      | RTSP-over-HTTP. Useful when only HTTP port 80 or 443 is open.          |
| `TunnelWebSocket` | RTSP-over-WebSocket. Useful for browser-based environments or proxies. |

<Warning>
  Tunneling via HTTP or WebSocket adds latency and reduces throughput compared to plain RTSP. Use it only when the network requires it.
</Warning>

## Firewall considerations

<Warning>
  UDP unicast requires the server to reach the client's UDP ports for RTP and RTCP. If your client is behind a NAT or firewall that blocks inbound UDP, packets will never arrive and the library will fall back to TCP after `InitialUDPReadTimeout`. Use TCP directly if you know UDP is blocked.
</Warning>

UDP-multicast requires network infrastructure that supports IGMP snooping and multicast routing. It is generally only available on managed local-area networks.
