# Connecting to SurrealDB

Learn how to connect the Mojo SDK to SurrealDB over HTTP, HTTPS, and WebSocket, and how to choose a wire format.

The Mojo SDK connects to a SurrealDB instance with `connect()`, which takes an endpoint URL and an optional `ConnectOptions`. The URL scheme selects the transport.

```python
from surrealdb import AsyncSurrealClient, ConnectOptions
from std.collections import Optional


def main():
    var client = AsyncSurrealClient()
    _ = client.connect(
        "http://localhost:8000/rpc",
        ConnectOptions(
            namespace=Optional(String("test")),
            database=Optional(String("test")),
            access_token=Optional(String("Basic cm9vdDpyb290")),
        ),
    )
```

`connect()` returns a `Bool`. The endpoint path is `/rpc`.

## Transports

The SDK ships transports for four schemes:

| Scheme | Transport | Notes |
|--------|-----------|-------|
| `http://`  | HTTP/1.1 | Request and response querying. The most thoroughly tested path. |
| `https://` | HTTP/1.1 over TLS | Build with `-D HTTPS=1`. See [TLS](#tls). |
| `ws://`    | WebSocket | Stateful sessions, server-side transactions, and live queries. |
| `wss://`   | WebSocket over TLS | Build with `-D HTTPS=1`. |

> [!NOTE]
> WebSocket support is rolling out. For request and response querying, including atomic multi-statement transactions, use the HTTP or HTTPS transport.

## Connection options

`ConnectOptions` carries the namespace, database, credentials, and wire format for the connection.

<table>
    <thead>
        <tr>
            <th colspan="2" scope="col">Field</th>
            <th colspan="2" scope="col">Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td colspan="2" scope="row" data-label="Field"><code>namespace</code></td>
            <td colspan="2" scope="row" data-label="Description">The namespace to use. Sent as the <code>Surreal-NS</code> header.</td>
        </tr>
        <tr>
            <td colspan="2" scope="row" data-label="Field"><code>database</code></td>
            <td colspan="2" scope="row" data-label="Description">The database to use. Sent as the <code>Surreal-DB</code> header.</td>
        </tr>
        <tr>
            <td colspan="2" scope="row" data-label="Field"><code>access_token</code></td>
            <td colspan="2" scope="row" data-label="Description">The credential placed in the <code>Authorization</code> header. See <a href="/docs/reference/mojo/concepts/authentication.md">Authentication</a>.</td>
        </tr>
        <tr>
            <td colspan="2" scope="row" data-label="Field"><code>tls_insecure</code></td>
            <td colspan="2" scope="row" data-label="Description">Disables TLS certificate verification. Dev fixtures only. Defaults to <code>False</code>.</td>
        </tr>
        <tr>
            <td colspan="2" scope="row" data-label="Field"><code>format</code></td>
            <td colspan="2" scope="row" data-label="Description"><code>RpcFormat.CBOR</code> (default) or <code>RpcFormat.JSON</code>.</td>
        </tr>
    </tbody>
</table>

The `Surreal-NS` and `Surreal-DB` headers are sent automatically when `namespace` and `database` are set.

## Selecting a namespace and database

You can also switch the namespace and database on an open connection with `use()`:

```python
client.use("test", "test")
```

## Wire format: CBOR or JSON

Both protocols use the same `/rpc` endpoint and the same RPC methods. Pick the wire format with `ConnectOptions.format`:

```python
from surrealdb import AsyncSurrealClient, ConnectOptions, RpcFormat
from std.collections import Optional


def main():
    var client = AsyncSurrealClient()
    _ = client.connect(
        "http://localhost:8000/rpc",
        ConnectOptions(
            namespace=Optional(String("test")),
            database=Optional(String("test")),
            access_token=Optional(String("Basic cm9vdDpyb290")),
            format=RpcFormat.JSON,  # or RpcFormat.CBOR (default)
        ),
    )
    var resp = client.query("RETURN 1 + 1;")
```

Switching `format` swaps the `Content-Type` and `Accept` headers (`application/json` versus `application/cbor`) and the codec used to encode and decode the RPC envelope. Everything else stays the same.

CBOR is the default because it is what the SurrealDB server uses internally and the most compact on the wire. JSON is useful when you want to inspect traffic in DevTools, match the SurrealDB JavaScript SDK behaviour, or proxy through a JSON-only gateway.

## TLS

Certificates are validated against the system root store by default. For self-signed dev fixtures, set `tls_insecure=True`:

```python
ConnectOptions(
    namespace=Optional(String("test")),
    access_token=Optional(String("Basic cm9vdDpyb290")),
    tls_insecure=True,  # never use in production
)
```

For the build flags required to connect over `https://` or `wss://`, see [Build with HTTPS](/docs/reference/mojo/installation.md#build-with-https).

## Connection state

Two helpers report the state of the connection and the features the active transport supports:

```python
if client.is_connected():
    var caps = client.capabilities()
```

`capabilities()` returns an `EngineCapabilities` describing which RPC features the active transport supports (live queries, sessions, server-side transactions, and the API endpoint). The client checks these flags before issuing a request, and raises an `UnsupportedFeatureError` rather than sending a request the server would reject.

Close the connection when you are done:

```python
client.close()
```
