npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dnspacket-ts

v2.0.0

Published

Node/Browser module for encoding and decoding DNS packet

Readme

DNS Packet

A Node.js/Deno/Bun and browser module for encoding and decoding DNS packets. This library is designed to facilitate DNS over HTTPS (DoH) and other DNS-based applications. It supports the core DNS protocol as defined in RFC 1035 and includes modern extensions like EDNS0 (RFC 6891).

Version 2.0.0 Highlights

  • Multiple Questions Support: Encoder/decoder now support multiple questions per packet (QDCOUNT > 1)
  • 15+ New DNS Record Types: CAA, DNSKEY, DS, NSEC, NSEC3, TLSA, SSHFP, SPF, DNAME, CDS, CDNSKEY, OPENPGPKEY, CSYNC, ZONEMD, SVCB, HTTPS, and more
  • Critical Bug Fixes: Fixed EDNS option endianness, getQR logic, OPT record offset handling, Opcode type mismatches
  • Strict TypeScript: Enabled strict: true, noUncheckedIndexedAccess, exactOptionalPropertyTypes
  • Extended Protocol Support: Additional OPCODEs (IQUERY, STATUS, NOTIFY, UPDATE), RCODEs (YXDOMAIN, YXRRSET, NXRRSET, NOTAUTH, NOTZONE), CLASSes (CH, HS)

Installation

npm install dnspacket-ts
# or
yarn add dnspacket-ts
# or
pnpm add dnspacket-ts

Usage

Basic DoH Query (AAAA record)

import { decode, encode } from "dnspacket-ts";
import axios from "axios";

const query = {
  id: 153,
  flags: {
    RD: 1, // Recursion Desired
  },
  questions: [
    { CLASS: "IN", NAME: "google.com", TYPE: "AAAA" },
  ],
};

const data = encode(query);

(async () => {
  try {
    const rdr = await axios({
      url: "https://cloudflare-dns.com/dns-query",
      method: "POST",
      data: data,
      headers: { "Content-Type": "application/dns-message" },
      responseType: "arraybuffer",
    });

    console.log(decode(rdr.data));
  } catch (error) {
    console.error("Error during DNS query:", error);
  }
})();

Multiple Questions in One Packet

import { decode, encode } from "dnspacket-ts";

const query = {
  id: 12345,
  flags: { RD: 1 },
  questions: [
    { NAME: "example.com", TYPE: "A", CLASS: "IN" },
    { NAME: "example.com", TYPE: "AAAA", CLASS: "IN" },
    { NAME: "example.com", TYPE: "MX", CLASS: "IN" },
  ],
};

const encoded = encode(query);
// QDCOUNT will be 3
const decoded = decode(encoded);
console.log(decoded.questions); // Array of 3 questions

EDNS with DNSSEC OK

import { decode, encode } from "dnspacket-ts";

const query = {
  id: 1234,
  flags: { RD: 1 },
  questions: [{ NAME: "dnssec-test.sidnlabs.nl", TYPE: "A", CLASS: "IN" }],
  edns: {
    udpPayloadSize: 4096,
    extendedRCODE: 0,
    version: 0,
    flags: { DO: 1 }, // DNSSEC OK
    options: [
      { code: 8, data: new Uint8Array([0, 10, 0, 1]) } // EDNS Client Subnet
    ]
  }
};

const encoded = encode(query);
// ARCOUNT will be 1 (OPT record included)

Decode Various Record Types

import { decode } from "dnspacket-ts";

// The library now decodes many record types:
const decoded = decode(buffer);

// A record -> RDATA: "192.168.1.1"
// AAAA record -> RDATA: "2607:f8b0:4009:80b::200e"
// CNAME/NS/PTR/DNAME -> RDATA: "target.example.com"
// MX record -> RDATA: { PREFERENCE: 10, EXCHANGE: "mail.example.com" }
// TXT/SPF record -> RDATA: ["v=spf1 ...", "google-site-verification=..."]
// SRV record -> RDATA: { PRIORITY: 10, WEIGHT: 5, PORT: 443, TARGET: "sip.example.com" }
// SOA record -> RDATA: { MNAME: "ns1.example.com", RNAME: "admin.example.com", SERIAL: 20240101, ... }
// CAA record -> RDATA: { flags: 0, tag: "issue", value: "letsencrypt.org" }
// DNSKEY record -> RDATA: { flags: 256, protocol: 3, algorithm: 13, key: Uint8Array }
// DS record -> RDATA: { keyTag: 12345, algorithm: 13, digestType: 2, digest: Uint8Array }
// NSEC record -> RDATA: { nextDomain: "next.example.com", types: [1, 2, 28, 5] }
// NSEC3 record -> RDATA: { hashAlgorithm: 1, flags: 0, iterations: 10, salt: Uint8Array, nextHashedOwnerName: Uint8Array, types: [...] }
// TLSA record -> RDATA: { certificateUsage: 3, selector: 1, matchingType: 1, certificateAssociationData: Uint8Array }
// SSHFP record -> RDATA: { algorithm: 2, fingerprintType: 1, fingerprint: Uint8Array }
// Unknown types -> RDATA: Uint8Array (raw wire format)

API Reference

encode(query: DNSQuery): Uint8Array

Encodes a DNS query object into a binary packet (Uint8Array).

DNSQuery properties:

  • id?: number - Transaction ID (random if omitted)
  • flags?: object - Header flags:
    • QR?: 'QUERY' | 'RESPONSE' - Query/Response (default: 'QUERY')
    • Opcode?: 'QUERY' | 'IQUERY' | 'STATUS' | 'NOTIFY' | 'UPDATE' - Operation code (default: 'QUERY')
    • AA?: 0 | 1 - Authoritative Answer
    • TC?: 0 | 1 - Truncation
    • RD?: 0 | 1 - Recursion Desired (default: 1)
    • RA?: 0 | 1 - Recursion Available
    • Z?: 0-7 - Reserved (must be 0)
    • RCODE?: string - Response code (default: 'NOERROR')
  • questions: Question[] - Required. Array of question objects (supports multiple)
  • edns?: EDNS - EDNS0 extension (adds OPT record to additional section)

Question: { NAME: string, TYPE: string, CLASS: string }

EDNS: { udpPayloadSize: number, extendedRCODE: number, version: number, flags: { DO: 0 | 1 }, options?: { code: number, data: Uint8Array }[] }

decode(buffer: ArrayBuffer | Uint8Array | Buffer): DNSResponse

Decodes a binary DNS packet into a structured object.

DNSResponse properties:

  • id: number - Transaction ID
  • flags: object - Header flags with string values for QR, Opcode, RCODE
  • questions: Question[] - Array of questions
  • answers: Answer[] - Answer records
  • authorities: Answer[] - Authority records
  • additionals: Answer[] - Additional records
  • edns?: EDNS - EDNS data from OPT record (if present)

Answer: { NAME: string, TYPE: string, CLASS: string, TTL: number, RDLENGTH: number, RDATA: unknown }

Supported Record Types

| Type | Value | RDATA Format | |------|-------|--------------| | A | 1 | "192.168.1.1" | | AAAA | 28 | "2001:db8::1" | | CNAME | 5 | "target.example.com" | | NS | 2 | "ns1.example.com" | | PTR | 12 | "target.example.com" | | DNAME | 39 | "target.example.com" | | MX | 15 | { PREFERENCE: number, EXCHANGE: string } | | TXT | 16 | string[] | | SPF | 99 | string[] | | SRV | 33 | { PRIORITY: number, WEIGHT: number, PORT: number, TARGET: string } | | SOA | 6 | { MNAME: string, RNAME: string, SERIAL: number, REFRESH: number, RETRY: number, EXPIRE: number, MINIMUM: number } | | CAA | 257 | { flags: number, tag: string, value: string } | | DNSKEY | 48 | { flags: number, protocol: number, algorithm: number, key: Uint8Array } | | DS | 43 | { keyTag: number, algorithm: number, digestType: number, digest: Uint8Array } | | NSEC | 47 | { nextDomain: string, types: number[] } | | NSEC3 | 50 | { hashAlgorithm: number, flags: number, iterations: number, salt: Uint8Array, nextHashedOwnerName: Uint8Array, types: number[] } | | TLSA | 52 | { certificateUsage: number, selector: number, matchingType: number, certificateAssociationData: Uint8Array } | | SSHFP | 44 | { algorithm: number, fingerprintType: number, fingerprint: Uint8Array } | | OPT | 41 | Handled as EDNS (not in answer sections) | | Unknown | N | Uint8Array (raw wire format) |

Supported Classes

| Class | Value | Description | |-------|-------|-------------| | IN | 1 | Internet (default) | | CH | 3 | Chaos | | HS | 4 | Hesiod | | ANY | 255 | Any class |

Supported OPCODEs

| Opcode | Value | Description | |--------|-------|-------------| | QUERY | 0 | Standard query (default) | | IQUERY | 1 | Inverse query (obsolete) | | STATUS | 2 | Server status request | | NOTIFY | 4 | Zone change notification | | UPDATE | 5 | Dynamic update |

Supported RCODEs

| RCODE | Value | Description | |-------|-------|-------------| | NOERROR | 0 | No error | | FORMERR | 1 | Format error | | SERVFAIL | 2 | Server failure | | NXDOMAIN | 3 | Non-existent domain | | NOTIMP | 4 | Not implemented | | REFUSED | 5 | Query refused | | YXDOMAIN | 6 | Name exists when it shouldn't | | YXRRSET | 7 | RR set exists when it shouldn't | | NXRRSET | 8 | RR set that should exist doesn't | | NOTAUTH | 9 | Not authoritative | | NOTZONE | 10 | Name not in zone |

Resources

  • RFC 1035: Domain Names - Implementation and Specification
  • RFC 1034: Domain Names - Concepts and Facilities
  • RFC 6891: Extension Mechanisms for DNS (EDNS0)
  • RFC 8484: DNS Queries over HTTPS (DoH)
  • RFC 3596: DNS Extensions for IPv6 (AAAA record)
  • RFC 2782: Service Location (SRV record)
  • RFC 2181: Clarifications to DNS Specification
  • RFC 6844: Certification Authority Authorization (CAA record)
  • RFC 4034/4035/5155: DNSSEC (DNSKEY, DS, NSEC, NSEC3)
  • RFC 6698: TLSA record
  • RFC 4255: SSHFP record
  • RFC 7208: SPF record
  • RFC 8499: DNS Terminology

License

MIT