# What Is the Tailcat Address Format? Structure, Encoding, and Parsing Guide

> Understand the Tailcat address format, a URL-safe string encoding server connection metadata like public keys and DERP regions using CBOR. Learn its structure and parsing.

- Repository: [Tailscale/tailcat](https://github.com/tailscale/tailcat)
- Tags: api-reference
- Published: 2026-09-06

---

**The Tailcat address format is a URL-safe string starting with "tc" followed by a base64url-encoded CBOR payload containing server connection metadata such as public keys and DERP region information.**

The Tailcat address format enables compact, portable server discovery within the `tailscale/tailcat` codebase. These addresses encode cryptographic identity and network path details into a single string that clients can parse to establish WireGuard connections. Understanding this format is essential for developers building on the Tailcat protocol.

## Structure and Encoding of Tailcat Addresses

Every Tailcat address follows a strict binary-to-text encoding scheme defined in the core library.

### The "tc" Prefix and Base64url Encoding

The format begins with the literal prefix **tc**, immediately followed by the base64url encoding (RFC 4648 §5) of a CBOR-serialized **ConnInfo** structure. This design produces strings like `tcomFwWC...` that remain unambiguous in URLs and JSON payloads.

The type definition and documentation reside in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go):

```go
// Addr is a compact, URL‑safe tailcat address that a server gives to clients
// so they can connect. It is the "tc"-prefixed base64url encoding of a
// CBOR-encoded [ConnInfo]. A typical Addr looks like "tcomFwWC…". 
type Addr string

```

[source](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go#L146-L149)

### The CBOR Payload Fields

When decoded, the CBOR payload reveals a **ConnInfo** struct containing the following fields:

- **ServerPublic** – The server’s WireGuard node public key (wrapped as `NodePublic`).
- **ServerDiscoPublic** – A distinct public key used for path-discovery (disco) packets.
- **PresharedKey** – An optional WireGuard pre-shared key included by default for enhanced security.
- **Region** or **RegionID** – Either a full DERP region description (generating a longer address) or a compact numeric region ID (shorter address).

## How to Generate a Tailcat Address

Servers expose their connection details through the `TailcatAddr` method, which serializes the server's current state into the address format.

```go
// s is a *tailcat.Server that has already been started.
addr := s.TailcatAddr()          // Addr type, e.g., "tcJ5Bv…"
fmt.Println("Tailcat address:", addr)

```

[source](https://github.com/tailscale/tailcat/blob/main/main/tailcat_test.go#L298-L302)

This method handles the CBOR serialization and base64url encoding internally, ensuring the output always conforms to the specification.

## How to Parse a Tailcat Address

Clients decode these strings using the `ParseAddr` function, which reverses the encoding process and restores implicit fields such as full region data when a `RegionID` is provided.

```go
var client tailcat.Client
client.Server = addr                       // the address string from the server
ci, err := tailcat.ParseAddr(addr)         // ci is a ConnInfo struct
if err != nil {
    log.Fatalf("invalid address: %v", err)
}
fmt.Printf("Server public key: %s\n", ci.ServerPublic)

```

[source](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go#L1052-L1055)

The function signature confirms the operation:

```go
// ParseAddr decodes an [Addr] back into a [ConnInfo], restoring
// the implicit fields that [ParseAddr] synthesizes (region and …)
func ParseAddr(addr Addr) (ConnInfo, error)

```

[source](https://github.com/tailscale/tailcat/blob/main/main/tailcat_test.go#L298-L304)

## CLI Usage and Real-World Examples

The Tailcat command-line interface leverages this format for server discovery. When starting a server with the `--full-address` flag, the CLI prints the generated address to stdout.

```bash

# Start a server that prints its address

$ tailcat serve --full-address
tailcat address: tcFh9K…

# Connect a client to that address

$ tailcat client tcFh9K…

```

This implementation resides in the CLI handler at [`main/cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go):

```go
// serve command handling with --full-address flag

```

[source](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go#L94-L102)

Web clients also consume these addresses, as demonstrated in [`main/web/main_js.go`](https://github.com/tailscale/tailcat/blob/main/main/web/main_js.go), where the address is passed to browser-based WebAssembly clients through the `addr` field.

## Summary

- **Tailcat addresses** use a "tc" prefix followed by base64url-encoded CBOR data, ensuring URL safety and compactness.
- The **ConnInfo** payload contains cryptographic keys (`ServerPublic`, `ServerDiscoPublic`), optional `PresharedKey`, and DERP region routing information.
- **Server.TailcatAddr()** generates valid addresses from running server instances.
- **ParseAddr()** decodes addresses into structured `ConnInfo` objects, handling both full region objects and compact region IDs.
- The format is integrated throughout the codebase, from the core library in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go) to CLI tools and WebAssembly clients.

## Frequently Asked Questions

### What does the "tc" prefix signify in Tailcat addresses?

The "tc" prefix serves as a format identifier that distinguishes Tailcat addresses from other URI types. According to the source code comments in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go), this literal prefix ensures parsers can immediately identify the string as a Tailcat address before attempting base64url decoding.

### How does the encoding differ from standard base64?

Tailcat addresses use **base64url** encoding (RFC 4648 §5) rather than standard base64. This variant replaces the `+` and `/` characters with `-` and `_` respectively, and omits padding characters (`=`), making the result safe for use in URL paths and JSON strings without additional escaping.

### What security information is exposed in a Tailcat address?

The address exposes the server's **public keys** (WireGuard and disco) and **DERP region** data. However, it does not contain private keys or the optional pre-shared key itself in plaintext—the `PresharedKey` field in the CBOR payload indicates presence or configuration, but the actual key material is established out-of-band during the WireGuard handshake.

### Can a Tailcat address be parsed manually without the library?

While possible, manual parsing requires implementing CBOR decoding and handling the implicit field resolution that `ParseAddr` performs (such as mapping numeric `RegionID` values to full region structs). The `tailscale/tailcat` source code provides the authoritative reference implementation for this logic.