Using Iceberg Catalogs in the Browser with DuckDB-Wasm
With recent updates of DuckDB itself, DuckDB-Wasm and the Iceberg extension it is now possible to query Iceberg catalog directly from the browser, with no backends. involved.
Example clients that work:
Disable the built-in http client in DuckDB-Wasm
To remotely querying Iceberg data, we first need to disable the internal http client of DuckDB-Wasm, and then use the official httpfs extension build:
-- Load the httpfs extension, this disables the built-in http client
LOAD http;
Load the Iceberg extension
You can then load the Iceberg extension:
-- Load Iceberg extension
LOAD iceberg;
Query Iceberg data in S3 Tables
I published another blog post βQuery S3 Tables with DuckDBβ in Q1/2025 which outlines the basic setup of a S3 Tables buckets, as well as a Namespace and an actual Table, please refer to it when trying to set this up in your environment.
So, if youβd like to attach an S3 Tables bucket as a database to DuckDB-Wasm, you can do this like the following:
ATTACH 'arn:aws:s3tables:us-east-1:12345678912:bucket/duckdb-test'
AS test_db (
TYPE iceberg,
ENDPOINT_TYPE s3_tables
);
The attach target is the ARN of the S3 Table bucket.
You then can check which tables are available:
SHOW ALL TABLES;
ββββββββββββββββ¬ββββββββββ¬ββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββ¬ββββββββββββ
β database β schema β name β column_names β column_types β temporary β
β varchar β varchar β varchar β varchar[] β varchar[] β boolean β
ββββββββββββββββΌββββββββββΌββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββΌββββββββββββ€
β test_db β test β daily_sales β [sale_date, product_category, sales_amount] β [DATE, VARCHAR, DOUBLE] β false β
ββββββββββββββββ΄ββββββββββ΄ββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββ΄ββββββββββββ
To query the table, just use normal SQL statements like you would with any other local table:
SELECT * FROM test_db.test.daily_sales;
ββββββββββββββ¬βββββββββββββββββββ¬βββββββββββββββ
β sale_date β product_category β sales_amount β
β date β varchar β double β
ββββββββββββββΌβββββββββββββββββββΌβββββββββββββββ€
β 2024-01-15 β Laptop β 900.0 β
β 2024-01-15 β Monitor β 250.0 β
β 2024-01-16 β Laptop β 1350.0 β
β 2024-02-01 β Monitor β 300.0 β
β 2024-02-01 β Keyboard β 60.0 β
β 2024-02-02 β Mouse β 25.0 β
β 2024-02-02 β Laptop β 1050.0 β
β 2024-02-03 β Laptop β 1200.0 β
β 2024-02-03 β Monitor β 375.0 β
ββββββββββββββ΄βββββββββββββββββββ΄βββββββββββββββ
Query Iceberg data in R2 Data Catalog / R2
There are a few steps to set up an R2 bucket for the usage as an Iceberg catalog.
Creating a R2 bucket
To create a R2 bucket, go to you accountβs Cloudflare Dashboard, and in the left sidebar click on βStorage & databasesβ β βR2 Object Storageβ and then on βOverviewβ:

After that, click on βCreate bucketβ in the top right corner. Youβll see the next screen below:

Setting a CORS policy
To set a CORS policy which is necessary to allow specific origin requests from the browser, you need to go to the βCORSβ Policyβ section and click on βAddβ. Then, you can copy & paste the CORS policy below and click on βSaveβ.
[
{
"AllowedOrigins": [
"https://sql-workbench.com",
"https://embedded.sql-workbench.com",
"https://terminal.sql-workbench.com",
"https://shell.duckdb.org"
],
"AllowedMethods": [
"GET",
"HEAD",
"PUT",
"POST"
],
"AllowedHeaders": [
"Authorization",
"Cache-Control",
"Content-Range",
"Content-Type",
"Content-Length",
"Range",
"X-Amz-Acl",
"X-Amz-Content-Sha256",
"X-Amz-Date",
"X-Amz-Security-Token",
"X-Iceberg-Access-Delegation",
"X-Host-Override"
],
"ExposeHeaders": [
"Content-Type",
"Access-Control-Allow-Origin",
"ETag"
]
}
]
Enabling R2 Data Catalog
Now, enable the R2 Data Catalog in your R2 bucketβs settings:

After clicking on βEnableβ, it takes a few seconds, and you should see your Catalog URI and your Warehouse Name. Those are both needed when querying the data later.

Creating a Account Token for R2 / R2 Data Catalog access
To access the data via queries, DuckDB needs an Account API Token. In the left sidebar menu, click on βManage accountβ β βAccount API Tokensβ

Then, on the next screen, click on βCreate Tokenβ and on the following screen on βGet startedβ in the Custom Token section.

Next, enter a name for your token, and create the two Permission entries as outlined below:

Click on βContinue to summaryβ and then create your access token
Querying data
You now have all the pieces you need for querying the data from your R2 Data Catalog.
As the R2 Data Catalog doesnβt send CORS headers, you need to use our cors.sqlqry.run CORS proxy, which provides a /iceberg route that needs to be postfixed with the R2 Data Catalog base URL concatenated with your Cloudflare Account ID and the name of the R2 bucket your created.
Create a DuckDB secret for the R2 Data Catalog as shown belog. All requests will subsequently use this secret to authorize themselves:
CREATE OR REPLACE SECRET r2secret (
TYPE iceberg,
ENDPOINT 'https://cors.sqlqry.run/iceberg/catalog.cloudflarestorage.com/YOUR_CLOUDFLARE_ACCOUNT_ID/YOUR_BUCKET_NAME',
TOKEN 'YOUR_ACCOUNT_API_TOKEN'
);
Then, attach the remote Iceberg catalog as database by supplying the Warehouse Name from the R2 Data Catalog settings:
ATTACH IF NOT EXISTS 'YOUR_WAREHOUSE_NAME' AS r2lake (TYPE iceberg);
If you havenβt created a schema (namespace) yet, you can do this like this with plain SQL:
CREATE SCHEMA IF NOT EXISTS. r2lake.test;
Create an example table:
CREATE TABLE IF NOT EXISTS r2lake.test.sales (
sale_id INT,
product_id INT,
quantity INT,
price DECIMAL(10, 2),
sale_date DATE
);
Insert data:
INSERT INTO r2lake.test.sales
(sale_id, product_id, quantity, price, sale_date)
VALUES
(1, 1, 10, 100.00, '2021-01-01'),
(2, 2, 20, 234.45, '2021-01-02'),
(3, 3, 30, 30.99, '2021-01-03');
Query the data:
SELECT * FROM r2lake.test.sales;
Summary
Thanks to the innovations of the DuckDB team, itβs now possible to directly query Iceberg catalogs from the browser. The use cases for this may be in-browser SQL clients for example, or demo applications that demonstrate how Iceberg itself works.