> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dune.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Client SDKs

> Official and community SDKs for Python, TypeScript, and Go

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.

<Note>
  **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!
</Note>

## Python

The [Python SDK](https://github.com/duneanalytics/dune-client) is our most mature and feature-complete client.

### Installation

```bash theme={null}
pip install dune-client
```

<Warning>
  Always use the latest release. Check [releases page](https://github.com/duneanalytics/dune-client/releases) for the current version. Features in the main branch may not be released yet.
</Warning>

### Quick Start

```python theme={null}
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:

<CodeGroup>
  ```python Execute by Query ID theme={null}
  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")
  ```

  ```python Execute Raw SQL theme={null}
  from dune_client import DuneClient

  dune = DuneClient(api_key="YOUR_API_KEY")

  # Execute arbitrary SQL
  sql = """
  SELECT 
      blockchain,
      SUM(amount_usd) as volume
  FROM dex.trades
  WHERE block_time > now() - interval '24' hour
  GROUP BY 1
  ORDER BY 2 DESC
  """

  results = dune.execute(sql=sql, performance="medium")

  for row in results.rows:
      print(f"{row['blockchain']}: ${row['volume']:,.2f}")
  ```

  ```python With DataFrames theme={null}
  from dune_client import DuneClient
  import pandas as pd

  dune = DuneClient(api_key="YOUR_API_KEY")

  # Get results as a pandas DataFrame
  df = dune.execute_dataframe(query_id=3493826)

  # Or convert manually
  results = dune.execute(query_id=3493826)
  df = pd.DataFrame(results.rows)

  # Now use pandas for analysis
  print(df.describe())
  print(df.groupby('blockchain')['amount_usd'].sum())
  ```
</CodeGroup>

### Advanced Features

#### Filtering and Pagination

```python theme={null}
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

```python theme={null}
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

```python theme={null}
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

<AccordionGroup>
  <Accordion title="execute()">
    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
  </Accordion>

  <Accordion title="execute_dataframe()">
    Execute a query and return results as a pandas DataFrame.

    **Parameters:** Same as `execute()`

    **Returns:** `pandas.DataFrame`
  </Accordion>

  <Accordion title="get_latest_result()">
    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`
  </Accordion>

  <Accordion title="get_status()">
    Check execution status without fetching results.

    **Parameters:**

    * `execution_id` (str): Execution ID

    **Returns:** `ExecutionStatus`
  </Accordion>

  <Accordion title="cancel_execution()">
    Cancel a running execution.

    **Parameters:**

    * `execution_id` (str): Execution ID

    **Returns:** `bool`
  </Accordion>
</AccordionGroup>

[Full Python SDK documentation →](https://github.com/duneanalytics/dune-client)

## TypeScript

The [TypeScript SDK](https://www.npmjs.com/package/@duneanalytics/client-sdk) provides type-safe access to Dune's API.

### Installation

```bash theme={null}
npm install @duneanalytics/client-sdk
# or
yarn add @duneanalytics/client-sdk
```

### Quick Start

```typescript theme={null}
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

<CodeGroup>
  ```typescript Execute by Query ID theme={null}
  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}`);
  ```

  ```typescript Execute Raw SQL theme={null}
  import { DuneClient } from '@duneanalytics/client-sdk';

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

  // Execute arbitrary SQL
  const sql = `
    SELECT 
      blockchain,
      SUM(amount_usd) as volume
    FROM dex.trades
    WHERE block_time > now() - interval '24' hour
    GROUP BY 1
    ORDER BY 2 DESC
  `;

  const results = await dune.execute({ sql, performance: 'medium' });

  results.rows.forEach(row => {
    console.log(`${row.blockchain}: $${row.volume.toLocaleString()}`);
  });
  ```

  ```typescript With Filters theme={null}
  import { DuneClient } from '@duneanalytics/client-sdk';

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

  // Get latest results with server-side filtering
  const results = await dune.getLatestResults({
    queryId: 3493826,
    filters: "amount_usd > 10000 AND blockchain = 'ethereum'",
    columns: ["tx_hash", "amount_usd", "block_time"],
    sortBy: ["amount_usd desc"],
    limit: 100
  });

  console.log(results.rows);
  ```
</CodeGroup>

### Advanced Features

#### Type-Safe Query Parameters

```typescript theme={null}
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

```typescript theme={null}
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

<AccordionGroup>
  <Accordion title="execute()">
    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>`
  </Accordion>

  <Accordion title="getLatestResults()">
    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>`
  </Accordion>

  <Accordion title="getStatus()">
    Check execution status.

    **Parameters:**

    * `executionId` (string): Execution ID

    **Returns:** `Promise<ExecutionStatus>`
  </Accordion>

  <Accordion title="cancelExecution()">
    Cancel a running execution.

    **Parameters:**

    * `executionId` (string): Execution ID

    **Returns:** `Promise<boolean>`
  </Accordion>
</AccordionGroup>

[Full TypeScript SDK documentation →](https://www.npmjs.com/package/@duneanalytics/client-sdk)

## Go

The [Go SDK](https://github.com/duneanalytics/duneapi-client-go) provides idiomatic Go access to Dune's API.

### Installation

```bash theme={null}
go get github.com/duneanalytics/duneapi-client-go
```

### Quick Start

```go theme={null}
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

<CodeGroup>
  ```go Execute by Query ID theme={null}
  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)
      }
  }
  ```

  ```go Execute Raw SQL theme={null}
  package main

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

  func main() {
      client := duneapi.New("YOUR_API_KEY")
      
      sql := `
          SELECT 
              blockchain,
              SUM(amount_usd) as volume
          FROM dex.trades
          WHERE block_time > now() - interval '24' hour
          GROUP BY 1
          ORDER BY 2 DESC
      `
      
      results, err := client.ExecuteSQL(duneapi.ExecuteSQLParams{
          SQL:         sql,
          Performance: "medium",
      })
      
      if err != nil {
          panic(err)
      }
      
      for _, row := range results.Rows {
          fmt.Printf("%s: $%.2f\n", row["blockchain"], row["volume"])
      }
  }
  ```

  ```go With Context and Timeouts theme={null}
  package main

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

  func main() {
      client := duneapi.New("YOUR_API_KEY")
      
      // Create context with timeout
      ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
      defer cancel()
      
      // Execute with context
      results, err := client.ExecuteWithContext(ctx, 3493826)
      if err != nil {
          if err == context.DeadlineExceeded {
              fmt.Println("Query timed out")
          } else {
              panic(err)
          }
          return
      }
      
      fmt.Printf("Got %d rows\n", len(results.Rows))
  }
  ```
</CodeGroup>

### Advanced Features

#### Concurrent Queries

```go theme={null}
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

```go theme={null}
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

<AccordionGroup>
  <Accordion title="Execute()">
    Execute a query and wait for results.

    **Parameters:**

    * `queryID` (int): Query ID to execute

    **Returns:** `(*ExecutionResult, error)`
  </Accordion>

  <Accordion title="ExecuteQuery()">
    Execute a query with full options.

    **Parameters:**

    * `params` (ExecuteQueryParams): Struct with QueryID, Performance, Parameters

    **Returns:** `(*ExecutionResult, error)`
  </Accordion>

  <Accordion title="ExecuteSQL()">
    Execute raw SQL.

    **Parameters:**

    * `params` (ExecuteSQLParams): Struct with SQL, Performance

    **Returns:** `(*ExecutionResult, error)`
  </Accordion>

  <Accordion title="GetLatestResult()">
    Get most recent results without re-executing.

    **Parameters:**

    * `queryID` (int): Query ID
    * `opts` (\*GetResultOptions): Optional filters, columns, sort

    **Returns:** `(*ResultsResponse, error)`
  </Accordion>

  <Accordion title="GetStatus()">
    Check execution status.

    **Parameters:**

    * `executionID` (string): Execution ID

    **Returns:** `(*ExecutionStatus, error)`
  </Accordion>
</AccordionGroup>

[Full Go SDK documentation →](https://github.com/duneanalytics/duneapi-client-go)

## Comparison

| Feature                   | Python      | TypeScript | Go           |
| ------------------------- | ----------- | ---------- | ------------ |
| **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

<CardGroup cols={3}>
  <Card title="Python Issues" icon="python" href="https://github.com/duneanalytics/dune-client/issues">
    Report Python SDK issues
  </Card>

  <Card title="TypeScript Issues" icon="js" href="https://github.com/duneanalytics/client-sdk/issues">
    Report TypeScript SDK issues
  </Card>

  <Card title="Go Issues" icon="golang" href="https://github.com/duneanalytics/duneapi-client-go/issues">
    Report Go SDK issues
  </Card>
</CardGroup>

<CardGroup cols={2}>
  <Card title="Community Discord" icon="discord" href="https://discord.gg/duneanalytics">
    Get help from the community
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/executions/execution-object">
    View complete API documentation
  </Card>
</CardGroup>
