Obscura

DeFiLlama TVL

Total value locked on each blockchain, from DeFiLlama.

defillama_tvl — the dataset name to pass to the Obscura API.

Category Markets Columns 8 Refresh Daily Point-in-time available_date

What one row means

One blockchain's total value locked (TVL) in USD as reported by DeFiLlama's live `/v2/chains` snapshot endpoint at the moment of a single scrape, for one calendar day (one row per chain per day, upserted repeatedly through that day as the scrape re-runs).

One row per One row per (chain, captured_date) — composite unique key enforced by the upsert's OnConflict on (chain, captured_date); a chain's row for a given day is overwritten each time the task reruns that day..

Point-in-time availability

Every Obscura dataset carries available_date: the calendar day the publisher made the row available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the same thing on every dataset in the catalog.

For defillama_tvl: snapshot: available_date = captured_date, a STORED GENERATED column. WHY THAT IS THE DAY IT BECAME AVAILABLE: /v2/chains is a live keyless current-state endpoint with no historical or period parameter, so a TVL reading for a past day cannot be fetched at all — the record becomes obtainable at the instant of the HTTP GET and on no earlier day. EVIDENCE captured_date is the capture day: Utc::now().date_naive() on a live run, BronzeObject::captured_day() on a bronze replay. The column was called `observed_on` until migration 000205 renamed it: that name described the SUBJECT ('the day the value was observed') where the fact it holds is about US, and an availability audit duly misclassified it as a source column.

Refresh cadence

Obscura refreshes defillama_tvl daily — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.

Schema — 8 columns

The full public column list for defillama_tvl, with the meaning of every field. The same schema is served unauthenticated at https://api.obscura.trade/v1/catalog/defillama_tvl.

ColumnTypeDescription
chaintext · not nullBlockchain/chain display name as returned by DeFiLlama's `name` field (e.g. 'Ethereum', 'Mantle', 'Plasma', 'Robinhood Chain'); half of the composite unique key with captured_date. Free-text from the vendor, not a normalized ticker/slug.
captured_datedate · not nullThe UTC calendar day the collector CONTACTED DeFiLlama — Utc::now().date_naive() on a live run, the bronze object's capture day on a replay — and the natural per-day snapshot key alongside chain. Part of the primary key, and the column available_date is generated from: /v2/chains serves only the current moment, so the day we asked is the day this reading was obtainable. Named `observed_on` before migration 000205, which described the subject rather than the act.
tvl_usddouble precisionChain's total value locked in USD at scrape time, from the API's `tvl` field. Rows below args.min_tvl_usd (default 0) are filtered out before upsert.
token_symboltextNative gas/governance token ticker for the chain, from the API's `tokenSymbol` field (e.g. 'ETH', 'MNT', 'XPL'). Nullable — chains without a distinct native token store NULL.
chain_idbigintEVM chain ID (e.g. 1 for Ethereum, 5000 for Mantle) from the API's `chainId` field. Nullable — non-EVM chains or unassigned IDs come through as NULL.
gecko_idtextCoinGecko slug for the chain's native token, from the API's `gecko_id` field (e.g. 'mantle', 'plasma', 'corn-3'). Stable cross-dataset external identifier that joins to CoinGecko price/market data far more reliably than the collision-prone token ticker. Nullable — chains without a mapped CoinGecko asset come through as NULL.
cmc_idtextCoinMarketCap numeric id for the chain's native token, from the API's `cmcId` field (a numeric string, e.g. '27075'). Stable cross-dataset external identifier keying into CMC data, not collision-prone like the ticker. Nullable — chains without a mapped CMC asset come through as NULL.
available_datedatePUBLIC-availability date = captured_date, STORED generated directly from it. Since the source is a live current-state endpoint with no historical parameter, the day we polled is the day this reading was obtainable — the point-in-time column to filter and join on.

Access defillama_tvl

Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.

import obscura

client = obscura.Client("obs_live_…")

df = client.query(
    dataset="defillama_tvl",
    start="2024-01-01",
)

Create a free account Browse all 95 datasets

Frequently asked questions

What is in the defillama_tvl dataset?

Total value locked on each blockchain, from DeFiLlama. One blockchain's total value locked (TVL) in USD as reported by DeFiLlama's live `/v2/chains` snapshot endpoint at the moment of a single scrape, for one calendar day (one row per chain per day, upserted repeatedly through that day as the scrape re-runs).

How do I avoid look-ahead bias with defillama_tvl?

Filter on defillama_tvl.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — snapshot: available_date = captured_date, a STORED GENERATED column. WHY THAT IS THE DAY IT BECAME AVAILABLE: /v2/chains is a live keyless current-state endpoint with no historical or period parameter, so a TVL reading for a past day cannot be fetched at all — the record becomes obtainable at the instant of the HTTP GET and on no earlier day. EVIDENCE captured_date is the capture day: Utc::now().date_naive() on a live run, BronzeObject::captured_day() on a bronze replay. The column was called `observed_on` until migration 000205 renamed it: that name described the SUBJECT ('the day the value was observed') where the fact it holds is about US, and an availability audit duly misclassified it as a source column. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.

In what formats can I get defillama_tvl?

As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="defillama_tvl". The column schema is public at https://api.obscura.trade/v1/catalog/defillama_tvl.

How often is defillama_tvl updated?

Obscura refreshes defillama_tvl on a daily schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.

Related datasets

Cboe IndicesDaily history of Cboe's volatility indices, including VIX, sourced directly from Cboe. Crypto MarketsPer-coin market data from CoinGecko: price, market cap and volume across thousands of cryptocurrencies. DeFiLlama ProtocolsTotal value locked in each DeFi protocol, tracked by DeFiLlama. DeFiLlama StablecoinsCirculating supply of each stablecoin over time, from DeFiLlama. Flow MetricsTrade-flow metrics per symbol in fixed time windows: taker (aggressor) buy versus sell volume and trade counts, broken o… Forex OrderbookOANDA's order book and position book by currency pair: where retail traders' open orders and positions sit relative to p… Forex PositionsRetail forex positioning by pair (share of traders long versus short), collected from several broker sentiment feeds. Forex Positions AggregateA consensus long/short reading per currency pair, blending the individual broker sentiment feeds.