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

Python Issues

Report Python SDK issues

TypeScript Issues

Report TypeScript SDK issues

Go Issues

Report Go SDK issues

Community Discord

Get help from the community

API Reference

View complete API documentation