# DefiLlama Scraper - DeFi TVL & Protocol Revenue (`dataio/defillama-protocol-revenue-tvl`) Actor

Scrape DefiLlama DeFi protocol data, one row per protocol and chain: TVL, fees and revenue joined from a separate endpoint, period-over-period changes, and valuation multiples the source never calculates. Filter by category and minimum TVL. No API key.

- **URL**: https://apify.com/dataio/defillama-protocol-revenue-tvl.md
- **Developed by:** [Tom Awake](https://apify.com/dataio) (community)
- **Categories:** Developer tools, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 protocol rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does DefiLlama Scraper do?

DeFi protocols as **one row per chain**, with revenue sitting next to the
value locked, and the valuation multiples worked out.

DefiLlama publishes two things that do not talk to each other.
`/protocols` gives value locked, but hides the per-chain split inside a
nested object. `/overview/fees` gives fees and revenue, in a separate call,
with no value locked. Putting them side by side takes a join nobody makes.

No API key. No account.

***

### The four things this does that the source does not

**1. It explodes the per-chain breakdown.**

Gate is deployed on **128 chains**. LayerZero V2 on 53. Uniswap V3 on 43.
The source stacks all of it into one `chainTvls` object.

Unfolded, 8,271 protocols become **17,749 protocol-chain rows** — and on
the larger protocols the expansion runs **6.3×**. Each row carries how
much that chain holds and what share of the protocol it represents, down
to four decimals where the share is marginal.

**2. It throws out the chains that are not chains.**

`chainTvls` mixes real chains with accounting aggregates. Across 644
distinct keys, **273 carry a hyphen** — `Ethereum-borrowed`,
`Ethereum-staking`, `Ethereum-pool2` — and others are bare aggregates
named `staking` or `borrowed`.

Treating those as chains double-counts value that is already in the
per-chain figures. They are filtered out.

**3. It joins revenue to value locked.**

2,697 protocols report fees. Matched to the TVL dataset by slug:
**93% join cleanly**. From that join come the multiples analysts
otherwise compute by hand:

| Protocol | TVL | Annualised fees | TVL / fees |
|---|---|---|---|
| **PumpSwap** | $0.33B | $650M | **×0.5** |
| Meteora DLMM | $0.19B | $231M | ×0.8 |
| Uniswap V4 | $1.14B | $385M | ×3.0 |
| … | | | |
| **Fraxtal** | $0.17B | ~$0M | **×101,252** |

Half a dollar of locked value per dollar of annual fees at one end; a
hundred thousand at the other. That spread is the whole question, and no
endpoint answers it.

**4. It computes the changes.**

The source returns `total24h` and `total48hto24h` side by side, `total7d`
next to `total14dto7d`, and never subtracts them. `feesChange24hPct`,
`feesChange7dPct` and `feesChange30dPct` do.

***

### Field coverage

Measured on a 1,500-row run filtered to protocols reporting revenue.

| Field | Coverage |
|---|---|
| `protocol`, `category`, `chain`, `tvlTotal` | 100% |
| `tvlOnChain` | 99.4% |
| `tvlToAnnualFees` | 99.3% |
| `twitter` | 99.9% |
| `chainSharePct` | 94.0% |
| `feesChange7dPct` | 93.3% |
| `fees24h` | 86.6% |
| `ageYears` | 83.4% |
| `marketCap`, `mcapToTvl` | **~24%** |

That last row matters: **market cap is only present on 14.8% of all
protocols**, so `mcapToAnnualFees` is available on a minority. It is left
empty rather than estimated. `tvlToAnnualFees` is the multiple that is
actually available at scale.

***

### What it is for

- **Protocol valuation.** Sort by `tvlToAnnualFees` within a category.
  Comparable protocols with very different multiples is where the work
  starts.
- **Chain ecosystem analysis.** Filter by chain and you get every protocol
  present, how much it holds there, and what share of itself that
  represents. `Base` and `Solana` look very different once you see who is
  actually deployed on them.
- **Concentration risk.** A protocol at 93% on one chain (LayerZero V2 on
  Ethereum) and one spread across 33 (Beefy) are not the same asset.
- **Revenue momentum.** `feesChange7dPct` across a category shows which
  business is actually growing, not which token is.
- **Due diligence.** Age, audit count, parent protocol and token symbol,
  alongside the numbers.

Three dataset views ship with the Actor: **Protocols by chain**,
**Revenue & multiples** and **Protocol profile**.

***

### Limits

Stated plainly, because they affect what you can conclude.

- **TVL is not revenue, and neither is a valuation.** These are the
  figures protocols report to DefiLlama through community-maintained
  adapters. Methodologies differ between protocols and change over time.
- **Market cap is mostly missing.** 14.8% of protocols. Any ratio built on
  it covers a minority, and a selected one — protocols with a listed token.
- **Revenue is per protocol, not per chain.** The fee figures repeat on
  every chain row of the same protocol. Summing `fees24h` across rows
  double-counts; only `tvlOnChain` is additive.
- **Categories are DefiLlama's own.** 102 of them, some overlapping, and a
  CEX sitting in the same dataset as a DEX is a deliberate choice of
  theirs, not a classification we impose.
- **"Annualised" is arithmetic, not a forecast.** Where the source does
  not provide `annualized1y`, it is 30-day fees × 365/30. For a protocol
  that launched last week, that number is meaningless — check
  `ageYears`.
- **Zero-TVL rows are off by default.** A protocol deployed on a chain but
  holding nothing is a real signal, but it triples the row count.
- **This is not investment advice**, and nothing here is a recommendation.
  It is public data, reshaped.

***

### How much does it cost?

You pay per protocol row returned: **$0.003 each**, that is $3.00 per 1,000. There is no start fee, and subscription plans pay less per protocol row.

The example input below asks for up to 2,000 protocol rows, so it costs **$6.00 at most**.

If a run reaches the spending limit you set, the output stops at that limit and never goes past it. You are never charged for rows that were not delivered.

### Use DefiLlama Scraper as an API

Call it from your own code with the Apify client, here in Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/defillama-protocol-revenue-tvl").call(run_input={
    'minTvlUsd': 100000000,
    'withRevenueOnly': True,
    'maxItems': 2000,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

### Other actors you might like

- [GLEIF LEI Lookup](https://apify.com/DataIO/gleif-lei-lookup): Legal Entity Identifier API
- [BODACC Scraper](https://apify.com/DataIO/bodacc-french-insolvencies-sales): French Insolvencies & Sales
- [SEC XBRL Screener](https://apify.com/DataIO/sec-edgar-xbrl-financial-screener): Company Financials Data

### FAQ

#### Is it legal to use this data?

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

#### Can I run it on a schedule?

Yes. Create a schedule in Apify Console, daily or weekly for example, and each run delivers a fresh dataset, which you can send by email, webhook or integration.

#### Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

### Source

[DefiLlama](https://defillama.com)'s public API (`/protocols`,
`/overview/fees`). No authentication. This Actor is not affiliated with
DefiLlama; please credit them if you republish the data.

# Actor input Schema

## `protocols` (type: `array`):

Protocol names or slugs, for example uniswap-v3, aave-v3, lido. Leave empty for the whole set of 8,271 protocols.

## `categories` (type: `array`):

DefiLlama categories in lowercase: dexs, lending, liquid staking, derivatives, yield, cex, bridge. 102 categories exist; Dexs alone holds 2,100 protocols.

## `chains` (type: `array`):

Chain names, for example Ethereum, Base, Solana, Arbitrum. Filters the exploded rows, so you get exactly the protocols present on those chains and how much each holds there.

## `minTvlUsd` (type: `integer`):

Applied to the protocol's total, not the per-chain amount. 100000000 (100M) keeps roughly 250 protocols out of 8,271.

## `withRevenueOnly` (type: `boolean`):

2,697 protocols report fees, and they are the ones you can value. Turning this on also makes the valuation multiples meaningful on almost every row.

## `multiChainOnly` (type: `boolean`):

Keeps protocols deployed on more than one chain — the ones whose per-chain breakdown is worth having.

## `includeZeroTvl` (type: `boolean`):

A protocol deployed on a chain but holding nothing there. It is a real signal — an abandoned deployment — but it triples the row count.

## `maxItems` (type: `integer`):

One row per protocol per chain. The full set explodes to about 17,700 rows.

## Actor input object example

```json
{
  "withRevenueOnly": false,
  "multiChainOnly": false,
  "includeZeroTvl": false,
  "maxItems": 2000
}
```

# Actor output Schema

## `results` (type: `string`):

Every row produced by the run, in JSON.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxItems": 2000
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataio/defillama-protocol-revenue-tvl").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "maxItems": 2000 }

# Run the Actor and wait for it to finish
run = client.actor("dataio/defillama-protocol-revenue-tvl").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxItems": 2000
}' |
apify call dataio/defillama-protocol-revenue-tvl --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataio/defillama-protocol-revenue-tvl"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/uQ3wVeJlgkfaNBYXu/builds/BmhltCpSaQfdSL9gQ/openapi.json
