# DNSSEC Validator (`phoenix2810/dnssec-validator`) Actor

Validate a domain's DNSSEC chain of trust: DS delegation, DNSKEY KSK/ZSK, RRSIG coverage, and AD bit support. Returns score, grade, and recommendations.

- **URL**: https://apify.com/phoenix2810/dnssec-validator.md
- **Developed by:** [Sanskar Jaiswal](https://apify.com/phoenix2810) (community)
- **Categories:** Developer tools, SEO tools, Open source
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## DNSSEC Validator

Validates a domain's DNSSEC chain of trust in one API call. Checks DS delegation records at the parent zone, DNSKEY presence with KSK and ZSK classification, RRSIG coverage on common record types, and AD bit support from public recursive resolvers. Returns a readiness score, letter grade, and actionable recommendations.

### Use cases

- Security audits for DNSSEC deployment across client domains.
- Compliance checks for DNS chain-of-trust standards.
- Onboarding validation when enabling DNSSEC on a new domain or registrar.
- Post-deploy monitoring for DNSSEC key rollovers and DS/DNSKEY drift.
- Email infrastructure checks pairing with SPF, DMARC, and DKIM audits.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `startUrl` | string | Yes | Public domain or URL to validate. The actor extracts the hostname and checks DNS DS, DNSKEY, and RRSIG records. HTTP and HTTPS only. Private IP ranges are blocked. |
| `recordTypes` | array | No | Optional list of DNS record types to check for RRSIG coverage. If empty, the actor checks A, AAAA, MX, TXT, and DNSKEY. |
| `timeoutSeconds` | integer | No | Timeout for each DNS lookup. Default: `10`, range: `3` to `30`. |

### Output

Each run pushes one dataset item.

| Field | Type | Description |
| --- | --- | --- |
| `inputUrl` | string | Original input URL or domain. |
| `domain` | string | Extracted domain name used for DNS lookups. |
| `checkedAt` | string | ISO timestamp for the audit. |
| `dsAtParent` | object | DS delegation records at parent zone (see below). |
| `dnskey` | object | DNSKEY records at the zone with KSK/ZSK classification (see below). |
| `rrsigCoverage` | object | RRSIG coverage check results (see below). |
| `adBitCheck` | object | Recursive resolver AD bit support check. |
| `score` | integer | DNSSEC readiness score from 0 to 100. |
| `grade` | string | Letter grade from A to F. |
| `issues` | array | Human-readable issues found. |
| `recommendations` | array | Recommended fixes. |
| `error` | string or null | Error message, if any. |

#### DS at parent object

| Field | Type | Description |
| --- | --- | --- |
| `found` | boolean | Whether DS records exist at the parent zone. |
| `parentDomain` | string | The parent domain where DS was queried. |
| `recordCount` | integer | Number of DS records found. |
| `records` | array | Parsed DS records with keyTag, algorithm, digestType, and truncated digest. |
| `issues` | array | DS-specific issues. |

#### DNSKEY object

| Field | Type | Description |
| --- | --- | --- |
| `found` | boolean | Whether DNSKEY records exist at the zone. |
| `keyCount` | integer | Total number of DNSKEY records. |
| `keySigningKeys` | array | KSK records (flags bit 15 set, flags 257). |
| `zoneSigningKeys` | array | ZSK records (flags bit 7 set, flags 256). |
| `records` | array | All parsed DNSKEY records with flags, algorithm, keyTag, and truncated public key. |
| `issues` | array | DNSKEY-specific issues. |

#### RRSIG coverage object

| Field | Type | Description |
| --- | --- | --- |
| `checked` | array | Record types checked for RRSIG coverage. |
| `signed` | array | Record types with RRSIG signatures present. |
| `unsigned` | array | Record types with answers but no RRSIG. |
| `details` | array | Per-type check results with hasAnswer and signed booleans. |
| `issues` | array | RRSIG-specific issues. |

#### AD bit check object

| Field | Type | Description |
| --- | --- | --- |
| `supported` | boolean or null | Whether the recursive resolver returned the AD bit (DNSSEC validation enforced upstream). |
| `issues` | array | AD bit specific issues. |

### Example input

```json
{
  "startUrl": "https://example.com",
  "recordTypes": [],
  "timeoutSeconds": 10
}
```

### Example output

```json
{
  "inputUrl": "https://example.com",
  "domain": "example.com",
  "checkedAt": "2026-08-11T00:00:00.000Z",
  "dsAtParent": {
    "found": true,
    "parentDomain": "com",
    "recordCount": 1,
    "records": [
      { "keyTag": 49822, "algorithm": 13, "digestType": 2, "digest": "2e9a5d3c..." }
    ],
    "issues": []
  },
  "dnskey": {
    "found": true,
    "keyCount": 2,
    "keySigningKeys": [
      { "flags": 257, "algorithm": 13, "keyTag": 49822, "protocol": 3, "publicKey": "MIIBIjANBgk..." }
    ],
    "zoneSigningKeys": [
      { "flags": 256, "algorithm": 13, "keyTag": 31406, "protocol": 3, "publicKey": "MIIBIjANBgk..." }
    ],
    "records": [
      { "flags": 257, "algorithm": 13, "keyTag": 49822, "protocol": 3, "publicKey": "MIIBIjANBgk..." },
      { "flags": 256, "algorithm": 13, "keyTag": 31406, "protocol": 3, "publicKey": "MIIBIjANBgk..." }
    ],
    "issues": []
  },
  "rrsigCoverage": {
    "checked": ["A", "AAAA", "MX", "TXT", "DNSKEY"],
    "signed": ["A", "AAAA", "MX", "TXT", "DNSKEY"],
    "unsigned": [],
    "details": [
      { "type": "A", "hasAnswer": true, "signed": true },
      { "type": "AAAA", "hasAnswer": true, "signed": true },
      { "type": "MX", "hasAnswer": true, "signed": true },
      { "type": "TXT", "hasAnswer": true, "signed": true },
      { "type": "DNSKEY", "hasAnswer": true, "signed": true }
    ],
    "issues": []
  },
  "adBitCheck": {
    "supported": true,
    "issues": []
  },
  "score": 100,
  "grade": "A",
  "issues": ["1 DS record(s) found at parent zone", "DNSSEC chain of trust appears complete: DS at parent, DNSKEY with KSK+ZSK, RRSIG on checked types"],
  "recommendations": [],
  "error": null
}
```

### Security

- Accepts only public HTTP and HTTPS URLs or domains.
- Rejects URL credentials.
- Rejects localhost, private IPv4, private IPv6, link-local, and private DNS resolutions.
- Performs DNS DS, DNSKEY lookups and DNS-over-HTTPS RRSIG queries only; does not fetch URLs or require login.
- RRSIG queries use Cloudflare's public DNS-over-HTTPS endpoint (1.1.1.1) with no authentication.
- Does not collect credentials or private data.

### Pricing

Suggested pay-per-event pricing:

| Event | Price |
| --- | ---: |
| Actor start | `$0.005` |
| Domain validated | `$0.01` |

Typical one-domain run cost: about `$0.015` before Apify platform charges. Apify keeps its standard commission and the actor owner receives the remainder.

### FAQ

#### Does this perform full cryptographic DNSSEC validation?

No. It checks for the presence and coverage of DS records at the parent zone, DNSKEY records with KSK/ZSK classification, and RRSIG signatures on common record types. Full cryptographic chain validation (verifying RRSIG signatures against DNSKEY public keys) is not performed. This actor is designed for monitoring and alerting, not forensic validation.

#### What record types are checked for RRSIG coverage?

By default, A, AAAA, MX, TXT, and DNSKEY. You can pass custom record types via the `recordTypes` input.

#### How does the AD bit check work?

The actor queries a public DNS-over-HTTPS resolver (Cloudflare 1.1.1.1) and checks whether the response includes the AD (Authenticated Data) bit, which indicates the resolver validated the DNSSEC chain. This tells you whether upstream resolvers enforce DNSSEC validation.

#### Does it fetch the domain's website?

No. It only performs DNS lookups (DS, DNSKEY) and DNS-over-HTTPS queries (RRSIG, AD bit). The URL input is used to extract the domain name safely.

#### What is the scoring based on?

The score starts at 100 and is reduced for missing DS at parent (-35), missing DNSKEY (-35), missing KSK (-15), missing ZSK (-10), missing RRSIG coverage (up to -45), and missing AD bit support (-10).

#### Kill or keep metric

Keep this actor if it gets organic Store impressions, runs, revenue, or inbound questions within 60 to 90 days. Improve the listing or pricing if impressions arrive without runs. Archive it if there is no discovery or usage.

# Actor input Schema

## `startUrl` (type: `string`):

Public domain or URL to validate. The actor extracts the hostname and checks DNS DS, DNSKEY, and RRSIG records for DNSSEC chain-of-trust validation. HTTP and HTTPS only. Private IP ranges are blocked.

## `recordTypes` (type: `array`):

Optional list of DNS record types to check for RRSIG coverage. If empty, the actor checks A, AAAA, MX, TXT, and DNSKEY. Each type is queried at the domain apex.

## `timeoutSeconds` (type: `integer`):

Timeout for each DNS lookup.

## Actor input object example

```json
{
  "startUrl": "https://example.com",
  "recordTypes": [],
  "timeoutSeconds": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrl": "https://example.com",
    "recordTypes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("phoenix2810/dnssec-validator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrl": "https://example.com",
    "recordTypes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("phoenix2810/dnssec-validator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrl": "https://example.com",
  "recordTypes": []
}' |
apify call phoenix2810/dnssec-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phoenix2810/dnssec-validator"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/TGRHUYXI5h7BFm2Ld/builds/r6AkHUhKRhubjygnb/openapi.json
