Skip to main content
Dune provides official SDKs that make it easy to interact with our API. All SDKs include a powerful execute() function that handles polling, pagination, and error handling automatically.
New: All SDKs now include an execute() function that automatically handles:
  • Query execution submission
  • Polling for completion
  • Automatic pagination for large result sets
  • Error handling and retries
  • Result formatting
No more manual polling or pagination logic!

Python

The Python SDK is our most mature and feature-complete client.

Installation

pip install dune-client
Always use the latest release. Check releases page for the current version. Features in the main branch may not be released yet.

Quick Start

from dune_client import DuneClient

# DuneClient will read the DUNE_API_KEY environment variable
dune = DuneClient()

# Execute a query by ID
results = dune.execute(query_id=3493826)

# Or execute raw SQL
results = dune.execute(sql="SELECT * FROM dex.trades LIMIT 10")

# Access results
for row in results.rows:
    print(row)

The execute() Function

The execute() function is the simplest way to run queries and get results:
from dune_client import DuneClient

dune = DuneClient(api_key="YOUR_API_KEY")

# Execute a saved query
results = dune.execute(
    query_id=3493826,
    performance="medium",  # or "large"
    params={
        "blockchain": "ethereum",
        "min_volume": 1000
    }
)

print(f"Got {len(results.rows)} rows")

Advanced Features

Filtering and Pagination

from dune_client import DuneClient

dune = DuneClient(api_key="YOUR_API_KEY")

# Use Dune's server-side filtering
results = dune.get_latest_result_dataframe(
    query=3493826,
    filters="amount_usd > 10000 AND blockchain = 'ethereum'",
    columns="tx_hash,amount_usd,block_time",
    sort_by="amount_usd desc",
    limit=100,
    offset=0
)

Query Management

from dune_client import DuneClient
from dune_client.query import QueryBase
from dune_client.types import QueryParameter

dune = DuneClient(api_key="YOUR_API_KEY")

# Create a new query
query = QueryBase(
    name="My DEX Analysis",
    query_sql="SELECT * FROM dex.trades WHERE blockchain = {{blockchain}}",
    params=[
        QueryParameter.text_type(name="blockchain", value="ethereum")
    ]
)

# Create the query on Dune
created_query = dune.create_query(query)
print(f"Created query: https://dune.com/queries/{created_query.query_id}")

# Update an existing query
query.query_id = created_query.query_id
query.query_sql = "SELECT * FROM dex.trades WHERE blockchain = {{blockchain}} LIMIT 1000"
dune.update_query(query)

# Execute it
results = dune.execute(query_id=created_query.query_id)

Data Uploads

from dune_client import DuneClient
import pandas as pd

dune = DuneClient(api_key="YOUR_API_KEY")

# Upload a CSV file
with open('data.csv', 'rb') as file:
    dune.upload_csv(
        data=file,
        table_name="my_dataset",
        description="Custom dataset for analysis"
    )

# Or upload a DataFrame
df = pd.DataFrame({
    'address': ['0x123...', '0x456...'],
    'label': ['DEX', 'Lending'],
    'category': ['DeFi', 'DeFi']
})

dune.upload_csv(
    data=df.to_csv(index=False),
    table_name="my_labels",
    is_private=False
)

API Reference

Execute a query and wait for results.Parameters:
  • query_id (int, optional): ID of saved query to execute
  • sql (str, optional): Raw SQL to execute
  • params (dict, optional): Query parameters
  • performance (str, optional): “medium” or “large” (default: “medium”)
Returns: ExecutionResult with .rows property
Execute a query and return results as a pandas DataFrame.Parameters: Same as execute()Returns: pandas.DataFrame
Get the most recent execution results for a query without re-executing.Parameters:
  • query (int): Query ID
  • filters (str, optional): Server-side filters
  • columns (list, optional): Columns to include
  • sort_by (list, optional): Sort order
  • limit (int, optional): Max rows to return
  • offset (int, optional): Pagination offset
Returns: ExecutionResult
Check execution status without fetching results.Parameters:
  • execution_id (str): Execution ID
Returns: ExecutionStatus
Cancel a running execution.Parameters:
  • execution_id (str): Execution ID
Returns: bool
Full Python SDK documentation →

TypeScript

The TypeScript SDK provides type-safe access to Dune’s API.

Installation

npm install @duneanalytics/client-sdk
# or
yarn add @duneanalytics/client-sdk

Quick Start

import { DuneClient, QueryParameter } from '@duneanalytics/client-sdk';

// Initialize client
const dune = new DuneClient(process.env.DUNE_API_KEY!);

// Execute a query
const results = await dune.execute({ queryId: 3493826 });

// Access results
console.log(`Got ${results.rows.length} rows`);
results.rows.forEach(row => console.log(row));

The execute() Function

import { DuneClient, QueryParameter } from '@duneanalytics/client-sdk';

const dune = new DuneClient(process.env.DUNE_API_KEY!);

// Execute a saved query with parameters
const results = await dune.execute({
  queryId: 3493826,
  parameters: [
    QueryParameter.text("blockchain", "ethereum"),
    QueryParameter.number("min_volume", 1000)
  ],
  performance: 'medium'
});

console.log(`Total rows: ${results.rows.length}`);

Advanced Features

Type-Safe Query Parameters

import { DuneClient, QueryParameter } from '@duneanalytics/client-sdk';

const dune = new DuneClient(process.env.DUNE_API_KEY!);

const results = await dune.execute({
  queryId: 1215383,
  parameters: [
    QueryParameter.text("TextField", "Plain Text"),
    QueryParameter.number("NumberField", 3.1415926535),
    QueryParameter.date("DateField", "2022-05-04 00:00:00"),
    QueryParameter.enum("ListField", "Option 1"),
  ]
});

Async/Await Pattern

import { DuneClient } from '@duneanalytics/client-sdk';

const dune = new DuneClient(process.env.DUNE_API_KEY!);

async function fetchDEXMetrics() {
  try {
    // Execute multiple queries in parallel
    const [volume, users, protocols] = await Promise.all([
      dune.execute({ sql: "SELECT SUM(amount_usd) as total FROM dex.trades WHERE block_time > now() - interval '24' hour" }),
      dune.execute({ sql: "SELECT COUNT(DISTINCT trader) as total FROM dex.trades WHERE block_time > now() - interval '24' hour" }),
      dune.execute({ sql: "SELECT project, SUM(amount_usd) as volume FROM dex.trades WHERE block_time > now() - interval '24' hour GROUP BY 1" })
    ]);
    
    return {
      totalVolume: volume.rows[0].total,
      uniqueUsers: users.rows[0].total,
      topProtocols: protocols.rows
    };
  } catch (error) {
    console.error('Failed to fetch metrics:', error);
    throw error;
  }
}

// Use it
const metrics = await fetchDEXMetrics();
console.log(metrics);

API Reference

Execute a query and wait for results.Parameters:
  • queryId (number, optional): ID of saved query
  • sql (string, optional): Raw SQL to execute
  • parameters (QueryParameter[], optional): Query parameters
  • performance (“medium” | “large”, optional): Performance tier
Returns: Promise<ExecutionResult>
Get most recent results without re-executing.Parameters:
  • queryId (number): Query ID
  • filters (string, optional): Server-side filters
  • columns (string[], optional): Columns to include
  • sortBy (string[], optional): Sort order
  • limit (number, optional): Max rows
Returns: Promise<ResultsResponse>
Check execution status.Parameters:
  • executionId (string): Execution ID
Returns: Promise<ExecutionStatus>
Cancel a running execution.Parameters:
  • executionId (string): Execution ID
Returns: Promise<boolean>
Full TypeScript SDK documentation →

Go

The Go SDK provides idiomatic Go access to Dune’s API.

Installation

go get github.com/duneanalytics/duneapi-client-go

Quick Start

package main

import (
    "fmt"
    "os"
    
    "github.com/duneanalytics/duneapi-client-go"
)

func main() {
    // Initialize client
    client := duneapi.New(os.Getenv("DUNE_API_KEY"))
    
    // Execute a query
    results, err := client.Execute(3493826)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Got %d rows\n", len(results.Rows))
}

The Execute() Function

package main

import (
    "fmt"
    "github.com/duneanalytics/duneapi-client-go"
)

func main() {
    client := duneapi.New("YOUR_API_KEY")
    
    // Execute a saved query
    results, err := client.ExecuteQuery(duneapi.ExecuteQueryParams{
        QueryID:     3493826,
        Performance: "medium",
        Parameters: map[string]interface{}{
            "blockchain": "ethereum",
            "min_volume": 1000,
        },
    })
    
    if err != nil {
        panic(err)
    }
    
    for _, row := range results.Rows {
        fmt.Printf("%+v\n", row)
    }
}

Advanced Features

Concurrent Queries

package main

import (
    "fmt"
    "sync"
    
    "github.com/duneanalytics/duneapi-client-go"
)

func main() {
    client := duneapi.New("YOUR_API_KEY")
    
    queries := []int{3493826, 3493827, 3493828}
    
    var wg sync.WaitGroup
    results := make([]duneapi.ExecutionResult, len(queries))
    
    for i, queryID := range queries {
        wg.Add(1)
        go func(index int, id int) {
            defer wg.Done()
            
            result, err := client.Execute(id)
            if err != nil {
                fmt.Printf("Error executing query %d: %v\n", id, err)
                return
            }
            
            results[index] = result
        }(i, queryID)
    }
    
    wg.Wait()
    
    for _, result := range results {
        fmt.Printf("Query completed with %d rows\n", len(result.Rows))
    }
}

Error Handling

package main

import (
    "errors"
    "fmt"
    
    "github.com/duneanalytics/duneapi-client-go"
)

func main() {
    client := duneapi.New("YOUR_API_KEY")
    
    results, err := client.Execute(3493826)
    if err != nil {
        // Handle different error types
        var apiErr *duneapi.APIError
        if errors.As(err, &apiErr) {
            fmt.Printf("API Error %d: %s\n", apiErr.StatusCode, apiErr.Message)
            return
        }
        
        var execErr *duneapi.ExecutionError
        if errors.As(err, &execErr) {
            fmt.Printf("Execution Error: %s\n", execErr.Message)
            return
        }
        
        // Unknown error
        panic(err)
    }
    
    fmt.Printf("Success! Got %d rows\n", len(results.Rows))
}

API Reference

Execute a query and wait for results.Parameters:
  • queryID (int): Query ID to execute
Returns: (*ExecutionResult, error)
Execute a query with full options.Parameters:
  • params (ExecuteQueryParams): Struct with QueryID, Performance, Parameters
Returns: (*ExecutionResult, error)
Execute raw SQL.Parameters:
  • params (ExecuteSQLParams): Struct with SQL, Performance
Returns: (*ExecutionResult, error)
Get most recent results without re-executing.Parameters:
  • queryID (int): Query ID
  • opts (*GetResultOptions): Optional filters, columns, sort
Returns: (*ResultsResponse, error)
Check execution status.Parameters:
  • executionID (string): Execution ID
Returns: (*ExecutionStatus, error)
Full Go SDK documentation →

Comparison

FeaturePythonTypeScriptGo
execute() function✅ Yes✅ Yes✅ Yes
Automatic polling✅ Yes✅ Yes✅ Yes
Automatic pagination✅ Yes✅ Yes✅ Yes
Server-side filtering✅ Yes✅ Yes✅ Yes
Query management✅ Full⚠️ Partial⚠️ Partial
Data uploads✅ Full❌ No❌ No
DataFrame support✅ Pandas❌ No❌ No
Type safety⚠️ Optional✅ Full✅ Full
Async/await⚠️ Limited✅ Full✅ Goroutines

Getting Help