DOCUMENTATION

Evidence you can inspect.

Learn the CLI, understand every confidence level, and run careful public DNS research at scale.

Get started

Quickstart

Node.js 20 or newer is the only runtime requirement. Run vendorprint directly from npm without installing it globally.

Terminal
npx vendorprint@latest example.com --pretty

Keep the command installed

Install vendorprint globally when you use it regularly. Add --findings-only for compact output without raw DNS detail.

Terminal
npm install --global vendorprint
vendorprint example.com --findings-only --pretty
DNS only

vendorprint queries the configured recursive DNS resolver. It does not request company websites, tracking endpoints, login pages, or application APIs.

CLI

Command reference

Use positional domains for quick scans, or file and stream inputs for larger jobs.

Input

--input <path>
Read newline, comma, or space-separated domains.
--stdin
Read domains from standard input.
--labels <a,b,c>
Add known candidate tracking labels.
--preserve-hostname
Scan the supplied hostname instead of its base domain.

Coverage and safety

--mode <value>
Choose full, balanced, or fast. Full is the default.
--timeout <ms>
Set the DNS attempt timeout. Default: 1800.
--concurrency <n>
Set concurrent domains. Default: 4. Maximum: 12.
--max-inflight-dns <n>
Set the global attempt ceiling. Default: 32.
--qps <n>
Limit DNS attempt starts per second. Default: 100.
--ct
Add bounded, opt-in certificate-transparency labels before DNS validation.
--ct-cache <path>
Reuse and update a local certificate discovery cache.

Output

--findings-only
Return compact findings without raw DNS records.
--format <value>
Choose JSON or streaming NDJSON.
--output <path>
Write to a new file instead of stdout.
--pretty
Pretty-print JSON. It cannot be used with NDJSON.

Diagnostics and resume

--include-unclassified
Include generic verification-like TXT diagnostics.
--resume <path>
Append remaining results to an NDJSON checkpoint.
--help
Print usage, options, and exit codes.

Exit codes

0Scan completed. Individual domains may still contain DNS errors.
1The CLI input was invalid.
Normalization

Domain inputs

URLs and hostnames normalize to the registrable company domain using the Public Suffix List.

Input https://www.example.co.uk/pricing
Scanned domain example.co.uk

Use --preserve-hostname only when a delegated hostname is intentionally the scan target. Invalid inputs are retained under invalidInputs instead of silently disappearing.

JSON

Output model

Compact output keeps evidence, confidence, and safety diagnostics while omitting raw DNS answers.

Shape
{
  "domain": "string",
  "status": "ok | error",
  "email": {
    "provider": "string | Unknown",
    "confidence": "low | medium | high",
    "securityGateways": []
  },
  "infrastructure": {
    "dnsProvider": {},
    "domainVerifications": [],
    "authorizedEmailSenders": [],
    "dmarcMonitoringServices": [],
    "cnameServices": []
  },
  "querySafety": {},
  "technologyProfile": {
    "aiWorkspaces": [],
    "crm": [],
    "marketingAutomation": [],
    "emailDelivery": [],
    "salesEngagement": [],
    "customerData": [],
    "productAnalytics": [],
    "customerSupport": [],
    "eventsAndWebinars": [],
    "inferenceGraph": {}
  },
  "technologyFingerprint": "sha256:...",
  "salesEngagement": {
    "status": "detected | not_detected",
    "detected": []
  }
}

Identity

domain, status, and normalized input diagnostics.

Observed technology

Mail routing, ownership proofs, sending authorization, CNAME services, and sales engagement.

Derived technology

Normalized categories plus explicit inferred findings and non-exhaustive candidate sets.

Operational evidence

Query budgets, skipped labels, retries, and wildcard-like CNAME diagnostics.

Catalog

Signature maintenance

Inspect the versioned catalog, find recurring unknown records offline, and compare two scan snapshots.

Terminal
vendorprint signatures --pretty
vendorprint signatures audit findings.ndjson --pretty
vendorprint diff before.json after.json --pretty

Audit output contains aggregate unknown prefixes and target domains only. It excludes account domains and verification tokens, and it performs no network requests.

Confidence

Evidence and inference

vendorprint separates direct observations from derived relationships and unresolved candidates.

DirectObserved in DNS

A vendor-owned MX or CNAME target, or a self-identifying ownership proof.

InferredDerived by a named rule

A product dependency or suite relationship, with rationale and caveats attached.

CandidatePossible, not asserted

A non-exhaustive set that may be prioritized by independent corroborating evidence.

Relationship levels

platform_configuration

An attributable custom hostname points to vendor infrastructure.

domain_relationship

A vendor-specific TXT record proves that domain ownership was configured.

sending_authorization

SPF authorizes a service to send mail but does not prove broader product use.

Absence is not proof

DNS cannot list arbitrary subdomains. Proxies, disabled branded tracking, and customer-selected labels can hide an otherwise active product.

Streaming

Batch scanning

Use NDJSON for long-running jobs. Each completed domain is appended immediately and becomes a durable checkpoint.

Terminal
vendorprint --input accounts.txt \
  --format ndjson \
  --findings-only \
  --output findings.ndjson

Resume after interruption

Terminal
vendorprint --input accounts.txt \
  --findings-only \
  --resume findings.ndjson

Resume skips normalized domains already present, tolerates one partial final line, and appends only remaining results. New output files are created without overwriting an existing file.

Node.js

Library API

Import the scanner without invoking the CLI, or consume completion-order events as an async iterator.

JavaScript
import { scanDomains } from "vendorprint";

const report = await scanDomains(["example.com"], {
  concurrency: 4,
  maxInflightDns: 32,
  qps: 100,
});
Streaming JavaScript
import { scanDomainEvents } from "vendorprint";

for await (const event of scanDomainEvents(domains)) {
  process.stdout.write(`${JSON.stringify(event)}\n`);
}
Operating policy

Responsible use

Keep the evidence attached, preserve unknown values, and use the built-in DNS limits.

What it does

  • Queries public DNS through the configured recursive resolver.
  • Checks a bounded set of records and candidate hostnames.
  • Redacts ownership tokens while retaining provider identity.
  • Reports confidence, evidence, and caveats together.

What it does not do

  • Request company websites or vendor tracking endpoints.
  • Attempt DNS zone transfers or arbitrary subdomain brute force.
  • Bypass authentication, access controls, or rate limits.
  • Prove that a subscription or employee seat is active.

Only research domains you are permitted to process. Follow applicable law, provider terms, data-governance rules, and retention policies.

Boundaries

Limits and caveats

These constraints protect the resolver and keep downstream decisions honest.

80 DNS attempts maximum per domain
4 Logical queries in flight per domain
32 Global in-flight attempts by default
100 DNS attempt starts per second by default

Stale records

A configured record can remain after a tool is no longer actively used.

Hidden targets

Cloudflare and other proxies can hide the vendor-owned CNAME target.

Wildcard DNS

Wildcard-like answers are collapsed so repeated guesses do not inflate evidence.

Product scope

A platform relationship does not prove a specific module, plan, seat, or recent activity.

Ready to inspect a domain?

Open the interactive demo