# Connecting

> Attach a DuckHouse database from the DuckDB CLI, Python, Node.js, the DuckPlus IDE or anything else that embeds DuckDB.

Source: https://duckhouse.co/docs/connect

Every DuckHouse database speaks [Quack](https://duckdb.org/quack/), DuckDB's own protocol for talking to another DuckDB over the network. Anything that embeds DuckDB can connect: the CLI, Python, Node.js, R, Java, Go, Rust, or a notebook.

## What you need

|  |  |
| --- | --- |
| DuckDB | 1.5.3 or newer. Your database runs 1.5.5; matching it is safest. |
| Address | Shown on the database's page, in the form `quack:duckdb-a1b2c3d4e5.fly.dev:443`. Connections are always encrypted with TLS. |
| Token | Starts with `dh_`. See [Tokens and API keys](https://duckhouse.co/docs/tokens.md). |

## Attach

Attaching makes the remote database available under a name you choose, here `wh`.

```sql
ATTACH 'quack:duckdb-a1b2c3d4e5.fly.dev:443' AS wh (TOKEN 'dh_your_token');
```

### Keep the token out of your SQL

Store the token as a DuckDB secret once, and attach without it afterwards. The `SCOPE` ties the secret to one database, so you can hold a different token for each.

```sql
CREATE PERSISTENT SECRET duckhouse (
  TYPE quack,
  TOKEN 'dh_your_token',
  SCOPE 'quack:duckdb-a1b2c3d4e5.fly.dev'
);

ATTACH 'quack:duckdb-a1b2c3d4e5.fly.dev:443' AS wh;
```

> DuckDB stores persistent secrets **unencrypted** in `~/.duckdb/stored_secrets`. That is fine on your own laptop. On shared machines and in CI, read the token from an environment variable instead, as the examples below do.

## Python

```python
import os
import duckdb

con = duckdb.connect()
con.execute(f"ATTACH 'quack:duckdb-a1b2c3d4e5.fly.dev:443' AS wh (TOKEN '{os.environ['DUCKHOUSE_TOKEN']}')")

con.sql("SELECT count(*) FROM wh.events").show()

# Straight into pandas or Polars
df = con.sql("FROM wh.query('SELECT * FROM events ORDER BY id LIMIT 1000')").df()
```

## Node.js and Bun

```typescript
import { DuckDBInstance } from '@duckdb/node-api'

const db = await DuckDBInstance.create(':memory:')
const con = await db.connect()

await con.run(
  `ATTACH 'quack:duckdb-a1b2c3d4e5.fly.dev:443' AS wh (TOKEN '${process.env.DUCKHOUSE_TOKEN}')`,
)

const result = await con.runAndReadAll('SELECT count(*) AS n FROM wh.events')
console.log(result.getRowObjectsJson())
```

## A desktop IDE: DuckPlus

[DuckPlus](https://duckhouse.co/duckplus) is a free, open-source Mac IDE from DuckHouse, built only for DuckDB. Paste your database's address and token and it opens a workspace with a schema browser, a SQL editor with autocomplete, and a results grid. Tokens are kept in your operating system's keychain, not in a file.

DuckPlus sends every statement to the server with `quack_query`, so your SQL runs inside your DuckHouse database. None of the [attachment gaps](https://duckhouse.co/docs/querying.md) apply, and you refer to tables by their names on the server: `events`, not `wh.events`.

## One query, no attach

`quack_query` sends a single statement and returns its result. It suits scripts that run one query and exit.

```sql
FROM quack_query(
  'quack:duckdb-a1b2c3d4e5.fly.dev:443',
  'SELECT count(*) FROM events',
  token = 'dh_your_token'
);
```

## No DuckDB available?

Serverless functions, BI tools and other places that cannot embed DuckDB can run SQL over plain HTTPS with the [REST API](https://duckhouse.co/docs/api.md#run-a-query).

## Troubleshooting

| You see | What it means |
| --- | --- |
| `Authentication failed` | The token is wrong or was revoked. Tokens are per database; check you are using this database's. |
| The first query takes about five seconds | The database was [stopped while idle](https://duckhouse.co/docs/databases.md#stop-when-idle) and is waking up. Later queries are fast. |
| The ATTACH never returns | Look for a missing `);` at the end of the statement. If the statement is complete, check on the database's page that it is running. |
| SSL or connection errors right after a token change | Changing tokens restarts the database. Wait a few seconds and attach again. |
| Errors mentioning the `quack` extension | Your DuckDB is older than 1.5.3, or cannot download extensions. Run `INSTALL quack; LOAD quack;` to see the underlying error. |

-   Still stuck? The database's page in the dashboard has a query console that reaches it the same way you do, which tells you whether the problem is the database or your client.
