Use Anywhere
One ATTACH line exposes the whole catalogue to DuckDB, Python and R, reading the same file the browser reads. Or read a Parquet file directly, or download it.
The browser explorer is a convenience, not a walled garden. Every dataset is a plain Parquet file at a stable URL, and the whole catalog is a frozen DuckLake — so you can query it from a notebook, a script, or a scheduled job with one line.
One line to the whole catalog
ATTACH 'ducklake:https://openlake.meridian.online/catalog/open.ducklake' AS meridian (READ_ONLY);That attaches the open catalog read-only and exposes every dataset as a schema-qualified table. There is one schema per namespace: an issuer's namespace, which Meridian holds for datasets it maintains from that issuer's public files (gleif, sec, census), or library for datasets Meridian made itself:
| Table | What it is |
|---|---|
meridian.gleif.lei | GLEIF legal entities (LEI register) |
meridian.sec.company_tickers_exchange | SEC EDGAR company tickers |
meridian.census.naics_2022 | NAICS industry classification, 2022 edition |
meridian.library.edgar_lei | EDGAR ↔ GLEIF crosswalk (CIK ↔ LEI) |
The name no longer says whether a dataset is raw or derived from others; the dataset's page says so.
The catalog is a single ~5 MB file that points at the underlying Parquet by reference — attaching it copies no data. Your engine reads only the columns and row groups each query needs, straight from R2.
The snippets
These do what the explorer's Use elsewhere drawer does, with the full table name written out. The query shown is the GLEIF country breakdown from the quick start.
-- One ATTACH exposes every Meridian open dataset as a table.
INSTALL ducklake;
ATTACH 'ducklake:https://openlake.meridian.online/catalog/open.ducklake' AS meridian (READ_ONLY);
SELECT country, count(*) AS entities
FROM meridian.gleif.lei
GROUP BY country
ORDER BY entities DESC
LIMIT 20;
-- Or read just this one Parquet directly:
INSTALL httpfs;
SELECT country, count(*) AS entities
FROM read_parquet('https://openlake.meridian.online/gleif/lei.parquet')
GROUP BY country
ORDER BY entities DESC
LIMIT 20;import duckdb
con = duckdb.connect()
con.execute("INSTALL ducklake; INSTALL httpfs;")
con.execute("ATTACH 'ducklake:https://openlake.meridian.online/catalog/open.ducklake' AS meridian (READ_ONLY)")
df = con.sql("""
SELECT country, count(*) AS entities
FROM meridian.gleif.lei
GROUP BY country
ORDER BY entities DESC
LIMIT 20
""").df()
# Or read just this one Parquet directly:
# duckdb.sql("""
# SELECT country, count(*) AS entities
# FROM read_parquet('https://openlake.meridian.online/gleif/lei.parquet')
# GROUP BY country
# ORDER BY entities DESC
# LIMIT 20
# """).df()Requires the duckdb package: pip install duckdb.
library(duckdb)
con <- dbConnect(duckdb())
dbExecute(con, "INSTALL ducklake; INSTALL httpfs;")
dbExecute(con, "ATTACH 'ducklake:https://openlake.meridian.online/catalog/open.ducklake' AS meridian (READ_ONLY)")
dbGetQuery(con, "
SELECT country, count(*) AS entities
FROM meridian.gleif.lei
GROUP BY country
ORDER BY entities DESC
LIMIT 20
")
# Or read just this one Parquet directly:
# dbGetQuery(con, "
# SELECT country, count(*) AS entities
# FROM read_parquet('https://openlake.meridian.online/gleif/lei.parquet')
# GROUP BY country
# ORDER BY entities DESC
# LIMIT 20
# ")Requires the duckdb package: install.packages("duckdb").
# DuckDB CLI — the whole commons via one ATTACH
duckdb -c "
INSTALL ducklake;
ATTACH 'ducklake:https://openlake.meridian.online/catalog/open.ducklake' AS meridian (READ_ONLY);
SELECT country, count(*) AS entities FROM meridian.gleif.lei GROUP BY country ORDER BY entities DESC LIMIT 20;"
# Or read just this one Parquet directly:
# duckdb -c "INSTALL httpfs; SELECT country, count(*) AS entities FROM read_parquet('https://openlake.meridian.online/gleif/lei.parquet') GROUP BY country ORDER BY entities DESC LIMIT 20;"Extension requirements
The engine needs two DuckDB extensions, both fetched on first use:
ducklake— resolves theducklake:catalog. Install withINSTALL ducklake;. It pulls in HTTP support automatically, so theATTACHline above works on its own.httpfs— reads a Parquet file directly over HTTPS. Install withINSTALL httpfs;. You only need it for theread_parquet('https://…')fallback path.
Both live in the default extension repositories; a recent DuckDB (these snippets were checked on DuckDB 2.0.0) installs them without any extra configuration. INSTALL runs once and caches the extension locally.
ATTACH vs. read_parquet directly
Two ways in, and they answer different questions:
ATTACHthe catalog when you want the whole commons behind one connection — stable table names (meridian.gleif.lei,meridian.library.edgar_lei, …), joins across datasets, and no per-file URLs to track.read_parquet('https://openlake.meridian.online/<namespace>/<name>.parquet')when you want exactly one dataset and nothing else. The<namespace>/<name>.parquetURL is stable and always resolves to the current release.
Reproducible reads
The stable <namespace>/<name>.parquet URL follows the latest release. If you need a fixed snapshot that never changes under you, use the content-addressed URL from the manifest instead — see Data & provenance.
Just download the file
No SQL engine handy? The Parquet is an ordinary object — curl it:
# Resolve the current immutable URL from the manifest, then download it:
curl -s https://openlake.meridian.online/manifest.json | jq -r '.datasets["gleif/lei"].url'
# Or grab the stable pointer directly (follows the latest release):
curl -O https://openlake.meridian.online/gleif/lei.parquetA note on the corpus column
Each table carries a hidden corpus column — a normalized blend of the text columns that powers the explorer's search box. SELECT * will include it (and it's large). When you want the clean, human columns, list them explicitly or exclude it:
SELECT * EXCLUDE (corpus) FROM meridian.gleif.lei LIMIT 50;Old addresses
Until 31 October 2026 the datasets had flat names. Those names still work, so a query or script written against them keeps running for now:
| Old SQL name | Old file | New SQL name | New file |
|---|---|---|---|
meridian.source.gleif, meridian.gleif | https://openlake.meridian.online/gleif.parquet | meridian.gleif.lei | https://openlake.meridian.online/gleif/lei.parquet |
meridian.source.edgar, meridian.edgar | https://openlake.meridian.online/edgar.parquet | meridian.sec.company_tickers_exchange | https://openlake.meridian.online/sec/company_tickers_exchange.parquet |
meridian.source.naics, meridian.naics | https://openlake.meridian.online/naics.parquet | meridian.census.naics_2022 | https://openlake.meridian.online/census/naics_2022.parquet |
meridian.crosswalk.edgar_gleif, meridian.edgar_gleif | https://openlake.meridian.online/edgar_gleif.parquet | meridian.library.edgar_lei | https://openlake.meridian.online/library/edgar_lei.parquet |
They do not behave the same way:
- The old SQL names are views over the new tables, so they return the same, current rows.
- The old files, and the old keys in the manifest (
gleif,edgar,naics,edgar_gleif), are frozen: they hold the release they had on 31 October 2026 and get no new ones.
Both stay readable until an end date that is not set yet. It will be set once the Brightfield release that reads the new addresses is out, and it will be at least 90 days after that release. Move to the new names before then; the new ones are the ones that follow each release.
Quick Start
Open a dataset, search it, filter it, run SQL over it, profile its columns and export a CSV, all in your browser, in about two minutes.
Data & Provenance
Where each Meridian dataset comes from, its open licence, how releases are published, its typed columns, what we promise about URLs, and the known limits.