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

# Introduction

> The Scriptable DNS allows you to dynamically respond to DNS queries using JavaScript scripts. The following pages contain sample documentation to help you get started.

## Quickstart

Create a DNS script, test it, publish it, and attach it to a hostname in your zone.

**Dashboard**

**1. Create a DNS Script**

In the bunny.net dashboard, go to [**DNS Scripts**](https://dash.bunny.net/dns/scripts) and click **Add DNS Script**.

**2. Write your script**

The Code editor opens with a starter script that answers every query with a TXT record:

```javascript theme={null}
/*
    Handle the DNS query!
*/
export default function handleQuery(event) {
    return new TxtRecord("Hello world!");
}
```

Edit the script to return the response you need, such as an `ARecord` for IP-based routing. See the [entry function](#entry-function) below for the query details available to your script.

**3. Test it**

Use the fields below the editor to simulate a query: set the **Type**, **Hostname**, **Client IP**, **EDNS IP**, and **Location**, then click **Run**.

The **Response** panel shows the DNS response your script returned, so you can try different request parameters and evaluate how your script behaves. Output from `console.log` appears in the **Console** tab.

**4. Publish the script**

Click **Save** to store your changes, then **Publish** to make the script live.

**5. Attach it to a DNS Zone**

A script only answers queries once a record points at it:

1. Go to **DNS** and select your DNS Zone
2. Click **Add DNS Record**
3. Enter a **Hostname**
4. Select **SCR** as the **Type**
5. Select the script you just published in the **Script** dropdown
6. Click **Add Record**

Queries for that hostname are now answered by your script.

**CLI**

> [!NOTE]
>
> Don't have the CLI installed? See the [CLI quickstart](/docs/cli/quickstart.md) to install and authenticate.

**1. Scaffold a project**

```bash theme={null}
bunny dns scripts init hello-dns
```

This writes a `handleQuery` entry file, a `tsconfig.json`, and a `package.json` with the [type definitions](#type-safety) preconfigured, and links the directory to the script. Pass `--example` to start from a template (`empty`, `geo`, `closest`, `weighted`, `failover`, `pullzone`).

**2. Write your script**

Edit the entry file to return the response you need. See the [entry function](#entry-function) below for the query details available to your script.

**3. Deploy the script**

Upload and publish the linked script's entry file:

```bash theme={null}
bunny dns scripts deploy
```

**4. Attach it to a DNS Zone**

A script only answers queries once a record points at it. Add a `SCRIPT` record to a zone:

```bash theme={null}
bunny dns scripts attach example.com api
```

The command confirms before writing the record. Verify it by querying the record type your script answers:

```bash theme={null}
dig api.example.com A
```

See the [`bunny dns` command reference](/docs/cli/commands/dns) for the full list of script commands.

## Entry function

The Scriptable DNS pipeline executes through a statically defined function **handleQuery**.

To return a response to the query, you can return one of the DNS response objects as documented in the [Query Response Object Types](/docs/dns/scriptable/query-response-object-types.md).

```javascript theme={null}
export default function handleQuery(query) {
  return new ARecord("111.111.111.111", 30);
}
```

> [!WARNING]
>
> `console.log` is intended for use within the Script Editor only. Please remove
> all logging statements before saving or publishing, as they may cause your
> script to fail at runtime.

## Query object

The entry function is passed a DnsRequest object parameter called **query** that contains the information about the request, such as the hostname, country, remote IP, etc.

### DnsRequest

| Field | Type | Description |
| - | - | - |
| `request` | DnsQuery | The DNS query request that contains the details about the query |

### DnsQuery

| Field | Type | Description |
| - | - | - |
| `hostname` | string | The hostname that is being queried |
| `clientIP` | string | The IP of the remote client that sent the DNS query |
| `queryType` | string | The query question type (A, AAAA, TXT) |
| `ednsIP` | string | The EDNS0 IP of the DNS query that was attached by the client |
| `geoLocation` | GeoLocation | The geo location of the client |
| `serverZone` | string | The server zone of the DNS server that received the query (DE, UK, SG, etc.) |

### GeoLocation

| Field | Type | Description |
| - | - | - |
| `latitude` | double | The latitude location of the client |
| `longitude` | double | The longitude location of the client |
| `country` | string | The detected two letter ISO country code of the client |
| `asn` | long | The detected ASN number of the client |

## Type safety

The Scriptable DNS runtime injects its globals (such as `ARecord` and the other [response object types](/docs/dns/scriptable/query-response-object-types.md)) directly into your script, and does not support `import`. The [`@bunny.net/scriptable-dns-types`](https://github.com/BunnyWay/cli/tree/main/packages/scriptable-dns-types) package provides ambient TypeScript declarations for these globals, giving you editor autocomplete and optional type checking without any runtime imports.

Install it as a development dependency:

```bash theme={null}
npm install --save-dev @bunny.net/scriptable-dns-types
```

Then reference the types from within your script file with a triple-slash directive:

```javascript theme={null}
/// <reference types="@bunny.net/scriptable-dns-types" />

/** @param {DnsRequest} query */
export default function handleQuery(query) {
  if (query.request.geoLocation.country === "DE") {
    return new ARecord("203.0.113.20", 30);
  }
  return new ARecord("203.0.113.10", 30);
}
```

Or enable them project-wide through `tsconfig.json`:

```json theme={null}
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
    "types": ["@bunny.net/scriptable-dns-types"]
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.