# What Is a Tailcat Connection Token (ConnBlob)? A Complete Technical Guide

> Discover what a Tailcat connection token ConnBlob is. Learn how this string enables secure client connections without DNS lookups in our complete technical guide.

- Repository: [Tailscale/tailcat](https://github.com/tailscale/tailcat)
- Tags: deep-dive
- Published: 2026-08-30

---

**A Tailcat connection token (ConnBlob) is a compact, URL-safe string that encodes a server's public key and DERP relay information, allowing clients to establish connections without additional network lookups or DNS resolution.**

The `tailscale/tailcat` repository implements this token format to enable portable, self-contained server addresses that can be embedded in URLs, command-line arguments, or DNS TXT records. Understanding the ConnBlob structure is essential for developers integrating Tailcat servers and clients into custom networking solutions.

## What Is a ConnBlob?

A **ConnBlob** (defined as `type ConnBlob string` in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go)) serves as an opaque connection token handed out by Tailcat servers to clients. According to the source code comments at lines 133–136, it represents "a compact, URL-safe string... the `tc`-prefixed base64url encoding of CBOR-encoded [ConnInfo]."

The token embeds everything a client requires to reach the server:

- **ServerPublic** – The server's public key (`NodePublic`) for cryptographic identity verification
- **Region/RegionID** – The DERP relay region or regions the server uses for NAT traversal
- **Optional DERP details** – Self-contained host and port information when the minimal region ID is expanded

Because the blob is URL-safe and compact, it eliminates the need for clients to fetch additional configuration data before initiating a connection.

## ConnBlob Structure and Encoding

The internal format follows a strict binary-to-text encoding pipeline implemented in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go).

### Wire Format and Serialization

The actual serialization logic resides in `ConnInfo.ConnBlob()` (lines 58–89). This method performs four distinct steps to minimize token size:

1. **Field Pruning** – Converts the internal `ConnInfo` structure to wire-compatible structs (`wireConnInfo`, `wireRegion`, `wireNode`), dropping unused fields to keep the payload minimal
2. **CBOR Encoding** – Serializes the pruned wire struct using Concise Binary Object Representation (CBOR)
3. **Base64url Encoding** – Converts the CBOR bytes to URL-safe Base64 (without padding)
4. **Prefixing** – Prepends the literal string `"tc"` to identify the token type

The resulting format is: `tc` + `<base64url-encoded CBOR data>`.

### CBOR Wire Definitions

The underlying data structures that define the CBOR schema live in [`wire.go`](https://github.com/tailscale/tailcat/blob/main/wire.go). These include `wireConnInfo`, `wireRegion`, and `wireNode`, which provide stable, versioned serialization targets for the connection information.

## Generating a ConnBlob on the Server

Servers generate connection tokens through the `Server.ConnBlob()` method, which delegates to `locoBackend.connBlob()` (lines 607–613) to construct a `ConnInfo` instance before calling `ConnInfo.ConnBlob()`.

Here is how to generate a token from a running server:

```go
// Create and start a new Tailcat server
srv, err := tailcat.NewServer(nil)
if err != nil {
    log.Fatal(err)
}
srv.Start(context.Background())

// Obtain the connection token for distribution to clients
blob := srv.ConnBlob()
fmt.Println("Server connection token:", blob)
// Output: tcM7W1iYXNlNjR1cmxzdHJpbmc...

```

The server automatically embeds its public key and current DERP region configuration into the returned `ConnBlob` value.

## Parsing and Using ConnBlob on Clients

Clients reverse the encoding process using `ParseConnBlob` (lines 744–747 in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go)), which CBOR-decodes the token back into a `ConnInfo` structure containing the server's public key and network coordinates.

### Basic Token Parsing

```go
// Receive a token from CLI argument, DNS TXT record, or URL parameter
blob := tailcat.ConnBlob("tcBASE64URLENCODEDSTRING")

// Decode into structured connection information
ci, err := tailcat.ParseConnBlob(blob)
if err != nil {
    log.Fatalf("Invalid connection token: %v", err)
}

fmt.Printf("Server public key: %s\n", ci.ServerPublic)
fmt.Printf("DERP Region ID: %d\n", ci.RegionID)

```

### Establishing Client Connections

The `NewClient` function (lines 1455–1471) accepts a `ConnBlob` directly to configure a client instance that knows how to reach the specified server:

```go
// Initialize client with the server token
client := tailcat.NewClient(blob)
defer client.Close()

// Dial a specific port on the server through the DERP relay
conn, err := client.DialTCPPort(context.Background(), 80)
if err != nil {
    log.Fatalf("Dial failed: %v", err)
}
defer conn.Close()

```

### Resolving Short Tokens

Some tokens contain only a `RegionID` without full DERP details. The `ConnBlob.Resolve` method (lines 91–99) fetches the complete DERP map and returns a fully embedded, self-contained blob:

```go
// Expand a minimal token into a complete connection descriptor
resolved, err := blob.Resolve(context.Background())
if err != nil {
    log.Fatalf("Failed to resolve DERP regions: %v", err)
}
fmt.Println("Resolved token:", resolved)

```

## Key Source Files and Implementation Details

The ConnBlob implementation spans several files in the `tailscale/tailcat` repository:

- **[`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go)** – Core type definitions (`ConnBlob`, `ConnInfo`), serialization logic (`ConnInfo.ConnBlob`), parsing functions (`ParseConnBlob`), and high-level API methods (`Server.ConnBlob`, `NewClient`)
- **[`wire.go`](https://github.com/tailscale/tailcat/blob/main/wire.go)** – CBOR wire format definitions (`wireConnInfo`, `wireRegion`, `wireNode`) that ensure stable binary encoding across versions
- **[`tailcat_test.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_test.go)** – Comprehensive tests validating ConnBlob generation, round-trip parsing, and edge cases
- **[`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go)** – Command-line interface handling for `<addrblob>` arguments, including parsing and DNS resolution workflows

## Summary

- **ConnBlob is a typed string** (`type ConnBlob string`) that functions as a self-contained server address in the Tailcat ecosystem.
- **Encoding follows a strict pipeline**: CBOR serialization of wire structs → Base64url encoding → `"tc"` prefix.
- **Servers generate tokens** via `Server.ConnBlob()`, which internally calls `ConnInfo.ConnBlob()` to create the final string representation.
- **Clients parse tokens** using `ParseConnBlob()` to extract the server's public key and DERP region information required for NAT traversal.
- **Short tokens can be resolved** using `ConnBlob.Resolve()` to fetch full DERP map details and create self-contained connection descriptors.
- The implementation prioritizes **URL safety and compactness**, making tokens suitable for command-line arguments, DNS records, and URL query parameters.

## Frequently Asked Questions

### What does the "tc" prefix in a ConnBlob signify?

The literal `"tc"` prefix identifies the string as a Tailcat connection token and distinguishes it from other base64url-encoded data. When `ParseConnBlob` processes a token, it validates this prefix before stripping it and decoding the remaining CBOR payload.

### How does a ConnBlob enable server connections without DNS?

By embedding the server's public key (`NodePublic`) and DERP relay region information directly in the token, the ConnBlob eliminates the need for traditional DNS resolution or service discovery. Clients extract the DERP region ID and optional host details from the decoded `ConnInfo`, then establish connections through the specified relay infrastructure using only the data contained in the token.

### What is the difference between a short and resolved ConnBlob?

A **short ConnBlob** contains only a `RegionID` referencing a DERP region defined in a global map, requiring a network fetch to obtain full relay addresses. A **resolved ConnBlob** embeds the complete DERP hostnames, ports, and coordinates directly in the CBOR payload, making it fully self-contained. The `ConnBlob.Resolve()` method in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go) (lines 91–99) converts short tokens into resolved ones by fetching the DERP map and inlining the region details.

### Where is the ConnBlob type defined in the Tailcat source code?

The `ConnBlob` type definition and its associated methods are located in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go) at lines 133–136, where it is declared as `type ConnBlob string` with documentation explaining its purpose as a URL-safe, CBOR-encoded connection descriptor. Serialization logic appears at lines 58–89 (`ConnInfo.ConnBlob`), while parsing logic resides at lines 744–747 (`ParseConnBlob`).