# Domain Typosquatting Audit (`appreciative_lobster-owner/dnstwist-domain-typosquat-audit`) Actor

Audit bounded lookalike-domain mutations with DNS-only A, AAAA, MX, NS, and UNKNOWN evidence.

- **URL**: https://apify.com/appreciative\_lobster-owner/dnstwist-domain-typosquat-audit.md
- **Developed by:** [Chris Prosser](https://apify.com/appreciative_lobster-owner) (community)
- **Categories:** Developer tools
- **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

## Domain Typosquatting Audit

Audit lookalike-domain mutations with bounded, DNS-only evidence. The Actor
returns observed `A`, `AAAA`, `MX`, and `NS` records plus an explicit `UNKNOWN`
state for resolver failures. It does **not** determine domain availability, use
HTTP or browser scanning, query WHOIS/RDAP, recommend purchases, or make a
phishing verdict.

Use it as a typosquat checker, lookalike-domain inventory, domain impersonation
review, brand-protection input, or reproducible DNS audit. Treat every result as
a point-in-time DNS observation, not as ownership, intent, or registrability
evidence.

### Input

| Field | Required | Default | Contract |
| --- | --- | --- | --- |
| `domains` | Yes | `example.com` in the Store UI | One to five ICANN registrable root domains |
| `mutationFamilies` | No | `bitsquatting`, `hyphenation`, `omission`, `transposition` | Allowlisted `dnstwist` mutation families |
| `maxVariantsPerDomain` | No | `200` | Deterministic hard cap, range `25`–`400` |
| `dnsTimeoutMs` | No | `1000` | Per-record timeout, capped by the remaining run deadline |
| `overallDeadlineSec` | No | `60` | One absolute deadline for the full batch, range `5`–`300` |

Example:

```json
{
  "domains": ["example.com"],
  "mutationFamilies": ["bitsquatting", "hyphenation"],
  "maxVariantsPerDomain": 100,
  "dnsTimeoutMs": 1000,
  "overallDeadlineSec": 60
}
```

Domains are normalized to lowercase ASCII IDNA. The Actor accepts only an ICANN
eTLD+1 recognized by the offline Public Suffix List bundled with pinned
`tld==0.13.2`. It rejects URLs, credentials, ports, IPs, subdomains, public
suffixes, unknown or reserved suffixes, and PSL PRIVATE-section hosting suffixes
before mutation generation or DNS work.

### Dataset rows

Each variant row contains:

- normalized `inputDomain`, generated `variantDomain`, and `fuzzer`;
- `status`: `REGISTERED_EVIDENCE`, `NO_DNS_EVIDENCE`, or `UNKNOWN`;
- DNS arrays `dnsA`, `dnsAAAA`, `dnsMX`, and `dnsNS`;
- `hasMx`, `evidenceAt`, `latencyMs`, and exact `queryCount`;
- domain-level `scanStatus`, stable `failureCode`, and truncation state.

`REGISTERED_EVIDENCE` means at least one target DNS record was observed without
a resolver anomaly. `NO_DNS_EVIDENCE` means a complete NODATA pass or
authoritative NXDOMAIN produced no target record. It does not mean the domain is
available. Timeout, `SERVFAIL`, `REFUSED`, missing nameservers, and other DNS
faults remain `UNKNOWN`; they are never rewritten as no-evidence results.

Non-result conditions use the same flat schema with `rowType = DIAGNOSTIC`.
Trustworthy rows are retained when a later deadline, billing, or runtime failure
stops the run.

### OUTPUT summary

The `OUTPUT` key-value record contains run and per-domain completeness,
generated/selected/scanned/query counts, typed status counts, and:

```json
{
  "billing": {
    "pricingModel": "FREE",
    "eventName": "domain-audit-completed",
    "eligibleDomainCount": 1,
    "chargedDomainCount": 0,
    "billingLimitReached": false,
    "billingFailureCode": null
  }
}
```

No price, user budget, token, account information, raw resolver exception, or
monitoring payload is emitted.

### Pay per event behavior

The same source supports private `FREE` operation and pay-per-event operation.
Charging is dormant unless the effective Apify pricing model is PPE. When PPE is
active, the only custom event is `domain-audit-completed`, issued at most once
for one domain after its dataset rows and latest `OUTPUT` are durable.

A domain is eligible only when it is `COMPLETE`, generated and scanned at least
one variant, has `unknownCount == 0`, and was not truncated or stopped by a
deadline, generator, PSL, billing, or persistence failure. The exact Store daily
test—one `example.com` with all schema defaults—is non-billable. Diagnostics,
summaries, `UNKNOWN`, incomplete domains, and synthetic events are not separately
charged.

Before each PPE domain, the Actor checks the remaining event budget. If it cannot
fund another event, it performs no mutation or DNS work for that domain or any
remaining domain, returns `BILLING_LIMIT_REACHED`, and preserves an `INCOMPLETE`
summary. A failed charge never changes the DNS status and fails the run with
`BILLING_CHARGE_FAILED` after preserving the result.

### Determinism, safety, and limits

- Python 3.14, 512 MiB, and a 360-second platform timeout are the release
  contract; the Actor's own maximum input deadline is 300 seconds.
- Mutations come from official `elceef/dnstwist` tag `20250130`, commit
  `4e6e477e95049067a7fe41fd8512e332abe26e95`, then are normalized, deduplicated,
  sorted, and capped.
- The Actor uses platform DNS only. There is no user-controlled resolver,
  executable, argument list, URL, proxy, secret, task, schedule, or Standby mode.
- A durable same-run execution guard blocks resurrection or retry from repeating
  DNS work or billing.

### Attribution and validation

The upstream Apache-2.0, `tld` tri-license, and Public Suffix List MPL-2.0
notices are preserved in [NOTICE](NOTICE). Runtime dependencies and the Python
3.14 base image are pinned by exact versions, hashes, and image digest.

In a full source checkout, the dependency-free contract suite is:

```bash
~/.codex/bin/codex-python -m unittest discover -s tests -v
~/.codex/bin/codex-python -m compileall -q dnstwist_actor tests scripts
```

Dependency installation, `apify run`, Docker, live DNS canaries, benchmarks,
private cloud builds, and browser QA run only through the registered OpenClaw
workspace. Tests, operational scripts, receipts, GO cards, and monitor state are
excluded from the Actor upload.

# Actor input Schema

## `domains` (type: `array`):

One to five ICANN registrable root domains. Public suffixes alone, subdomains, private-hosting suffixes, reserved or unknown suffixes, URLs, and IPs are rejected before DNS work.

## `mutationFamilies` (type: `array`):

Optional allowlist of supported dnstwist fuzzers. The default set stays inside a conservative DNS-only probe.

## `maxVariantsPerDomain` (type: `integer`):

Deterministic hard cap after sorting. If the cap truncates the generated set, the scan becomes INCOMPLETE.

## `dnsTimeoutMs` (type: `integer`):

Maximum per-record DNS timeout in milliseconds. Each A, AAAA, MX, or NS lookup is capped again by the remaining whole-run deadline.

## `overallDeadlineSec` (type: `integer`):

One absolute whole-run deadline shared by generation and all DNS records across the full batch. Trustworthy partial rows are preserved; a domain with no row becomes FAILED.

## Actor input object example

```json
{
  "domains": [
    "example.com"
  ],
  "mutationFamilies": [
    "bitsquatting",
    "hyphenation",
    "omission",
    "transposition"
  ],
  "maxVariantsPerDomain": 200,
  "dnsTimeoutMs": 1000,
  "overallDeadlineSec": 60
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing variant rows and any non-billable diagnostics.

## `summary` (type: `string`):

Run-level completeness, counts, per-domain summaries, and billing state without price or budget data.

# 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 = {
    "domains": [
        "example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("appreciative_lobster-owner/dnstwist-domain-typosquat-audit").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 = { "domains": ["example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("appreciative_lobster-owner/dnstwist-domain-typosquat-audit").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 '{
  "domains": [
    "example.com"
  ]
}' |
apify call appreciative_lobster-owner/dnstwist-domain-typosquat-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,appreciative_lobster-owner/dnstwist-domain-typosquat-audit"
        }
    }
}
```

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/fD2XIMuIVoQR0iraw/builds/rHqumyJxBUZWk2mRL/openapi.json
