WebDuck – DuckDB as a Service

jonbaer1 pts0 comments

WebDuck - DuckDB as a Service with REST API and Web UI<br>WebDuck<br>DuckDB as a Service<br>Fast, simple DuckDB-as-a-Service with REST API and Web UI. Install via pip, deploy with Docker, query your data in seconds.<br>Get StartedView on GitHub

Web UI<br>Dashboard

Projects

Browse View

Quickstart<br>pip<br>pip install webduck# Unix<br>pipx install webduck# macOS

Docker<br>docker run --name webduck<br>-p 8998:8998<br>-v webduck_data:/app/data<br>-e WEBDUCK_ADMIN_USER=admin<br>-e WEBDUCK_ADMIN_PASS=secret<br>autumoswitzerland/webduck

Terminal

Features

REST API<br>Full REST API with JWT auth, optional DB passwords, and project management.

Dashboard<br>Live traffic monitor with queries per second and active sessions, plus a storage overview including trash usage.

DuckDB Engine<br>Built on DuckDB with file-locking for safe concurrent access and fast analytics.

Projects & Data Browser<br>Organize databases into projects, browse tables with infinite scroll, and edit cells in place.

Import/Export<br>CSV, Parquet and JSON import via drag & drop, one-click export with browser download.

SQL Editor<br>Multi-statement SQL editor with query history and SQL file upload, sequential execution.

Compress & Optimize<br>Database size and fragmentation indicators, with compact support to reclaim disk space.

Trash<br>Delete to trash instead of permanently — restore projects and databases with one click.

i18n<br>English + German out of the box, extensible via PO/Gettext.

API Examples<br>Query your data from any language<br>cURLPythonPHPJava<br># Login - get JWT token<br>TOKEN=$(curl -s -X POST http://localhost:8998/admin/login \<br>-H "Content-Type: application/json" \<br>-d '{"username": "admin", "password": "secret"}' | jq -r '.token')

# Create a project<br>curl -X POST http://localhost:8998/admin/projects \<br>-H "Authorization: Bearer $TOKEN" \<br>-H "Content-Type: application/json" \<br>-d '{"name": "myproject"}'

# Create a database<br>curl -X POST http://localhost:8998/admin/projects/myproject/databases \<br>-H "Authorization: Bearer $TOKEN" \<br>-H "Content-Type: application/json" \<br>-d '{"name": "mydb"}'

# Query data — no password = open<br>curl -X POST http://localhost:8998/db/projects/myproject/databases/mydb/query \<br>-H "Content-Type: application/json" \<br>-d '{"sql": "SELECT * FROM users LIMIT 10"}'

# Set DB password (optional — without it, API is open)<br>curl -X PUT http://localhost:8998/admin/projects/myproject/databases/mydb/password \<br>-H "Authorization: Bearer $TOKEN" \<br>-H "Content-Type: application/json" \<br>-d '{"password":"dbpass","access_level":"write"}'

# Query with DB password set<br>curl -X POST http://localhost:8998/db/projects/myproject/databases/mydb/query \<br>-H "Content-Type: application/json" \<br>-H "X-Project-Key: myproject:dbpass" \<br>-d '{"sql": "SELECT * FROM users LIMIT 10"}'<br>import requests

BASE = "http://localhost:8998"

# Login<br>token = requests.post(<br>f"{BASE}/admin/login",<br>json={"username": "admin", "password": "secret"}<br>).json()["token"]<br>headers = {"Authorization": f"Bearer {token}"}

# Create project<br>requests.post(f"{BASE}/admin/projects",<br>json={"name": "myproject"}, headers=headers)

# Create database<br>requests.post(f"{BASE}/admin/projects/myproject/databases",<br>json={"name": "mydb"}, headers=headers)

# Query data — no password = open<br>result = requests.post(f"{BASE}/db/projects/myproject/databases/mydb/query",<br>json={"sql": "SELECT * FROM users LIMIT 10"})<br>print(result.json())

# Set DB password (optional)<br>requests.put(f"{BASE}/admin/projects/myproject/databases/mydb/password",<br>json={"password": "dbpass", "access_level": "write"}, headers=headers)

# Query with DB password set<br>result = requests.post(f"{BASE}/db/projects/myproject/databases/mydb/query",<br>json={"sql": "SELECT * FROM users LIMIT 10"},<br>headers={"X-Project-Key": "myproject:dbpass"})<br>print(result.json())<br>php<br>// Login<br>$login = http_post_json(<br>"http://localhost:8998/admin/login",<br>["username" => "admin", "password" => "secret"]<br>);<br>$token = json_decode($login, true)['token'];<br>$headers = ["Authorization: Bearer $token"];

// Create project<br>http_post_json(<br>"http://localhost:8998/admin/projects",<br>["name" => "myproject"], $headers<br>);

// Create database<br>http_post_json(<br>"http://localhost:8998/admin/projects/myproject/databases",<br>["name" => "mydb"], $headers<br>);

// Query data — no password = open<br>$response = http_post_json(<br>"http://localhost:8998/db/projects/myproject/databases/mydb/query",<br>["sql" => "SELECT * FROM users LIMIT 10"]<br>);<br>print_r(json_decode($response, true));

// Set DB password (optional)<br>http_put_json(<br>"http://localhost:8998/admin/projects/myproject/databases/mydb/password",<br>["password" => "dbpass", "access_level" => "write"], $headers<br>);

// Query with DB password set<br>$response = http_post_json(<br>"http://localhost:8998/db/projects/myproject/databases/mydb/query",<br>["sql" => "SELECT * FROM users LIMIT 10"],<br>["X-Project-Key: myproject:dbpass"]<br>);<br>print_r(json_decode($response, true));<br>var client = HttpClient.newHttpClient();<br>var base = "http://localhost:8998";

// Login<br>var loginReq = HttpRequest.newBuilder()<br>.uri(URI.create(base +...

projects password myproject admin json query

Related Articles