# Blockchain Data API - Dune SQL Query Results, Onchain Analytics (`nabeelbaghoor/blockchain-sql-onchain-data-api`) Actor

Export Dune query results to a dataset: latest results of any public or owned Dune query, run saved queries with parameters or raw DuneSQL and poll to completion, with filters, sorting and sampling. DEX trades, NFTs, tokens, wallets on Ethereum, Solana, Base and more. Bring your own API key.

- **URL**: https://apify.com/nabeelbaghoor/blockchain-sql-onchain-data-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 query result row returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Blockchain Data API - Dune SQL Query Results, Onchain Analytics

Export the results of any public or owned Dune query, or run your own DuneSQL over Dune's indexed blockchain data, straight into an Apify dataset with your own Dune API key.

This actor works with the Dune API (the SQL query execution and results endpoints). It reads the latest stored result of saved Dune queries without re-running them, or executes saved queries with your parameter values and raw DuneSQL statements, polls each execution until it finishes (with a timeout cap), and turns every result row into a clean dataset row you can download as JSON, CSV or Excel, schedule, or feed into dashboards, spreadsheets, trading research, notebooks and AI agents. Bring your own API key.

### What it does

- **Latest query results (default, cheapest)**: reads the newest stored result of each saved Dune query ID, whether it last ran in the Dune app, on a schedule or through the API. Nothing is executed, so no execution credits are used; Dune bills only the data exported.
- **Execute a saved query with parameters**: runs each query ID again with the parameter values you give (blockchain, token address, wallet, date range, days and so on), polls the free status endpoint, and reads the result when it completes.
- **Execute raw DuneSQL**: runs one SQL statement over Dune tables such as `dex.trades`, `nft.trades`, `tokens.transfers`, `prices.usd`, decoded contract events and the raw blocks, transactions and logs of Ethereum, Solana, Bitcoin, Base, Arbitrum, Optimism, Polygon, BNB Chain and many more chains.
- **Timeout cap and cancel**: an execution still running at your timeout (default 300 seconds, at most 1800) is cancelled so it stops using compute, or left running so you can read it later by execution ID.
- **Stored execution results**: re-reads the result of an earlier execution ID (kept by Dune for 90 days) without running anything.
- **Custom endpoints**: reads a Dune custom API endpoint by handle and slug.
- **Server-side shaping**: filters (a SQL-like WHERE clause), sort (ORDER BY), column selection and uniform random sampling, all applied by Dune before export so you pay for fewer bytes.
- **Credit aware**: each read asks only for the rows still left under your maximum, pages by offset, and executions only happen in the execute modes.
- **Pay only for results**: empty results, failed or timed out executions and refusals are a free row that says why, never charged.

### Input

| Field | Used by | What it does |
| --- | --- | --- |
| `mode` | all | `latestResult` (default), `executeQuery`, `executeSql`, `executionResult` or `customEndpoint` |
| `queryIds` | latest result, execute query | Saved Dune query IDs or dune.com/queries URLs, one per line (up to 50, or 10 for executions) |
| `queryParameters` | latest result, execute query | JSON object of the query's parameter values, such as `{"blockchain": "ethereum"}`; a list is a multi-select |
| `sql` | execute SQL | One DuneSQL statement |
| `performance` | execute modes | Engine tier: `small`, `medium` or `large`; empty for Dune's default |
| `timeoutSeconds` | execute modes | How long to wait for an execution (default 300, max 1800) |
| `pollIntervalSeconds` | execute modes | How often to check the status (default 5); status checks are free |
| `cancelOnTimeout` | execute modes | Cancel an execution still running at the timeout (default on) |
| `executionIds` | execution result | Earlier execution IDs, one per line |
| `customEndpoints` | custom endpoint | Custom endpoints as `handle/endpoint-slug` |
| `filters` | all | Server-side filter, such as `amount_usd > 1000 AND project = 'uniswap'` |
| `sortBy` | all | Server-side sort, such as `amount_usd desc, block_time` |
| `columns` | all | Only these result columns |
| `sampleCount` | all | A uniform random sample of this many rows (not with filters) |
| `allowPartialResults` | all | Read a result Dune truncated for size instead of refusing it |
| `maxResults` | all | Row ceiling for the run (default 100) |
| `requestsPerMinute` | all | Pacing to your plan's rate limit (default 30) |
| `apiKey` | all | Your Dune API key, stored as a secret |

Example input, the latest stored result of a saved query, largest rows first:

```json
{
    "mode": "latestResult",
    "queryIds": ["3568055"],
    "sortBy": "one_day_volume desc",
    "maxResults": 100
}
```

Example input, run raw DuneSQL and wait up to five minutes:

```json
{
    "mode": "executeSql",
    "sql": "SELECT block_time, blockchain, project, amount_usd, tx_hash FROM dex.trades WHERE block_time > now() - interval '1' hour ORDER BY amount_usd DESC LIMIT 100",
    "performance": "medium",
    "timeoutSeconds": 300
}
```

### How to get an API key

Sign in at dune.com and create a key under the API keys section of your settings (dune.com/settings/api). API access needs an active trial or a paid Dune plan (Analyst, Plus or Enterprise); free access after a trial is view only and does not include API exports. Bring your own API key: paste it into the API key field or set the `DATA_API_KEY` environment secret.

### Example output

```json
{
    "mode": "latestResult",
    "modeLabel": "Latest query result",
    "recordType": "resultRow",
    "identifier": "query 3568055",
    "found": true,
    "id": "01HW6N7VF1H7VYQ91GC0NP673E|0",
    "queryId": "3568055",
    "executionId": "01HW6N7VF1H7VYQ91GC0NP673E",
    "state": "QUERY_STATE_COMPLETED",
    "rowNumber": 0,
    "executionEndedAt": "2026-10-10T23:39:29.389539Z",
    "expiresAt": "2027-01-08T23:39:29.38954Z",
    "executionCostCredits": null,
    "totalRowCount": 1000,
    "columnNames": ["chain", "all_time_volume", "one_day_volume"],
    "chain": "ethereum",
    "all_time_volume": 332594074340.38,
    "one_day_volume": 92699347.48,
    "retrievedAt": "2026-10-11T09:00:00.000Z",
    "note": null
}
```

Every column the query returns becomes its own field, named as in the query; a column that shares a name with one of the actor's own fields is kept as `column_<name>`. Rows from the execute modes also carry `executionCostCredits`, the credits Dune reports for that execution.

### FAQ

#### What is the Dune API?

Dune is an onchain data platform that indexes and decodes blockchain data from Ethereum, Solana, Bitcoin, Base, Arbitrum, Optimism, Polygon, BNB Chain and many other chains into SQL tables. The Dune API runs DuneSQL queries and returns their results as JSON, which this actor turns into dataset rows.

#### Do I need my own API key?

Yes. This actor reads the Dune API with your own key and never ships a shared one. A run without a key ends straight away with a message that says where to get one, and nothing is charged.

#### Does reading a query's latest result run the query again?

No. The latest query result mode reads the result Dune already stored from the query's last run, in the app, on a schedule or through the API. It uses no execution credits; Dune bills only the data exported. To refresh the data, schedule the query on dune.com or use the execute query mode.

#### How do I run a Dune query with parameters?

Use the execute query mode, give the query ID and a `queryParameters` object such as `{"token_address": "0x...", "days": 30}`. Parameters you leave out keep the defaults set on the query. The actor polls the execution and reads the result when it completes.

#### Can I run my own SQL?

Yes. The execute SQL mode runs one DuneSQL statement over any Dune table, such as `dex.trades`, `nft.trades`, `tokens.transfers` or decoded contract events. Add a `LIMIT` to keep compute and export credits down.

#### What happens if a query takes too long?

The actor waits up to your execution timeout (default 300 seconds, at most 30 minutes, which is Dune's own limit). If the execution is still running, it is cancelled to stop further compute, or, with cancel on timeout off, left running so you can read it later with the execution result mode and the execution ID from the note.

#### How do I filter or sort results without editing the query?

Set `filters` (a SQL-like WHERE clause such as `amount_usd > 1000`), `sortBy` (an ORDER BY clause such as `block_time desc`) and `columns`. Dune applies them server side before export, so smaller results also cost fewer credits.

#### What do I pay?

Pay per result: 0.005 USD per result row pushed to the dataset. Empty results, failed or timed out executions and refusals are never charged. Your Dune plan's own credits are used separately: executions by compute, and every results read by the megabytes exported, which is why each read asks only for the rows still left under your maximum.

#### What happens if my key is wrong or my credits run out?

A rejected key (HTTP 401) or a request over your billing cycle's credit limit (HTTP 402) ends the run cleanly with a status message that explains what to change. Rate limits (HTTP 429) are waited out and retried. A private or missing query becomes a free row saying so, and the run moves on.

### Keyword map

Dune API, Dune Analytics API, DuneSQL API, blockchain data API, onchain data API, onchain analytics, crypto SQL API, Ethereum data export, Solana onchain data, DEX trades API, NFT trades data, token transfers, wallet analytics, Dune query results export, Dune dashboard data, execute Dune query, crypto data pipeline, Web3 analytics.

### Terms and data use

Use of the Dune API is governed by Dune's General Terms and Conditions and its SQL API Service Addendum. Your API key is personal to your account: it may not be sold, sublicensed or shared, and it should never be placed in public repositories, client-side code or public dashboards, so keep it as a secret here. The addendum bars uses that act as a substitute for Dune's service or compete with Dune's business, and the general terms ask that reused public queries credit their creators. Results land in your own Apify dataset; check your Dune plan's terms before redistributing them outside your organisation. This actor is not affiliated with or endorsed by Dune.

# Actor input Schema

## `mode` (type: `string`):

Latest query result reads the stored result of each saved Dune query without running it (cheapest: billed only by data exported). Execute query runs each saved query again, with your parameter values, waits for it and reads the result (uses execution credits). Execute SQL runs one raw DuneSQL statement the same way. Execution result reads the stored result of an earlier execution ID. Custom endpoint reads a Dune custom API endpoint by handle and slug.

## `queryIds` (type: `array`):

Latest query result and execute query modes. Saved Dune query IDs, the number after /queries/ in a dune.com query URL (a full URL such as https://dune.com/queries/3568055 also works), one per line. The query must be public or owned by you or your team. Up to 50 for latest results, 10 for executions.

## `queryParameters` (type: `object`):

Latest query result and execute query modes. Values for the query's own parameters as a JSON object, such as {"blockchain": "ethereum", "days": 30}; a list is a multi-select parameter. Execute query runs with them (parameters left out keep their defaults). Latest query result returns the newest stored result that ran with these values.

## `sql` (type: `string`):

Execute SQL mode. One DuneSQL statement to run, such as SELECT block_time, project, amount_usd FROM dex.trades WHERE block_time > now() - interval '1' day LIMIT 100. Add a LIMIT to keep compute and export credits down.

## `performance` (type: `string`):

Execute modes only. The engine tier to run on; leave empty for Dune's default. Credits follow the compute actually used.

## `timeoutSeconds` (type: `integer`):

Execute modes only. How long to wait for an execution to finish before giving up. Dune's own limit is 30 minutes.

## `pollIntervalSeconds` (type: `integer`):

Execute modes only. How often to check the execution status. Status checks are free.

## `cancelOnTimeout` (type: `boolean`):

Execute modes only. Cancel an execution that is still running at the timeout so it stops using compute credits. Turn off to let it finish and read it later with the execution result mode.

## `executionIds` (type: `array`):

Execution result mode. The 26 character execution_id of earlier executions, one per line. Results are kept for 90 days.

## `customEndpoints` (type: `array`):

Custom endpoint mode. Dune custom endpoints as handle/endpoint-slug, one per line.

## `filters` (type: `string`):

Server-side row filter over the result columns, like a SQL WHERE clause without the WHERE, such as amount_usd > 1000 AND project = 'uniswap'. Cannot be combined with a sample count.

## `sortBy` (type: `string`):

Server-side sort over the result columns, like a SQL ORDER BY clause, such as amount_usd desc, block_time.

## `columns` (type: `array`):

Return only these result columns, one per line. Fewer columns means less data exported and fewer credits.

## `sampleCount` (type: `integer`):

Return a uniform random sample of this many rows instead of the first rows. Cannot be combined with filters.

## `allowPartialResults` (type: `boolean`):

Read a result that was truncated because it was too large (over Dune's 32GB result limit) instead of refusing it.

## `maxResults` (type: `integer`):

The most rows this run returns and charges for, across all queries. Each read asks Dune only for the rows still left, which also limits the export credits used.

## `requestsPerMinute` (type: `integer`):

Pacing. Dune allows 70 executions and 200 result reads a minute on the Plus plan and more on Enterprise, and answers 429 above it, which the actor waits out and retries.

## `apiKey` (type: `string`):

Your own Dune API key, from the API keys section of your Dune settings (dune.com/settings/api). Stored as a secret and sent only in the X-Dune-Api-Key header; it is never logged. You can instead set the DATA_API_KEY environment secret.

## Actor input object example

```json
{
  "mode": "latestResult",
  "queryIds": [
    "3568055"
  ],
  "timeoutSeconds": 300,
  "pollIntervalSeconds": 5,
  "cancelOnTimeout": true,
  "allowPartialResults": false,
  "maxResults": 100,
  "requestsPerMinute": 30
}
```

# Actor output Schema

## `records` (type: `string`):

One row per result row, plus uncharged rows for empty or refused requests.

# 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 = {
    "queryIds": [
        "3568055"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/blockchain-sql-onchain-data-api").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 = { "queryIds": ["3568055"] }

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/blockchain-sql-onchain-data-api").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 '{
  "queryIds": [
    "3568055"
  ]
}' |
apify call nabeelbaghoor/blockchain-sql-onchain-data-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/blockchain-sql-onchain-data-api"
        }
    }
}
```

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/Fz0yXRyZN8F2fCacw/builds/YOPE4ahFoiL4sbRh3/openapi.json
