Production-grade OSINT CLI tool to query a commercial Domains/Subdomains Discovery dataset and enumerate domains and subdomains that match user-defined include/exclude patterns (wildcards supported as literal strings), built for cybersecurity analysts and investigation workflows.
Repository: https://github.com/haltman-io/sub-alter
During investigations, brand monitoring, vendor review, or infrastructure mapping, you often need to pivot from a known term (e.g., example.com) to discover:
- domains ending with a term (
*example.com) - domains starting with a term (
example.com*) - domains containing a term anywhere (
*example.com*) - subdomains matching patterns (e.g.,
aws*) while excluding noise (e.g.,*portal*)
This tool provides a repeatable CLI interface with robust configuration, proxy support, and clean output suitable for piping into other tools.
-
Query a commercial domains/subdomains discovery API
-
Include/exclude filters:
domains.include[],domains.exclude[]subdomains.include[],subdomains.exclude[]
-
Accepts multiple values per flag:
- repeatable flags (
-di a -di b) - comma-separated lists (
-di a,b)
- repeatable flags (
-
Provider constraints enforced:
- maximum 4 items per include/exclude array
-
API key handling:
--api-keytakes priority- fallback YAML config near the executable:
.sub-alter.yaml - supports multiple keys with round-robin rotation (per request)
-
Network features (baseline):
- HTTP/HTTPS and SOCKS5 proxy support via
--proxy - respect
HTTP_PROXY,HTTPS_PROXY,NO_PROXYunless--no-proxy - TLS bypass via
--insecure/-k(curl-style)
- HTTP/HTTPS and SOCKS5 proxy support via
-
Rate limiting:
--rate-limit/-rlglobal max requests/sec- API hard limit: 30 rps (tool rejects values > 30)
-
Output:
- ANSI colored terminal output (subtle: only content inside
[]is colored), disable with--no-color/-nc --output/-o/-outwrites clean, deduplicated results for tooling chains
- ANSI colored terminal output (subtle: only content inside
Endpoint:
https://domains-subdomains-discovery.whoisxmlapi.com/api/v1
Required header:
Content-Type: application/json
apiKey(required)domains.include(optional, max 4)domains.exclude(optional, max 4)subdomains.include(optional, max 4)subdomains.exclude(optional, max 4)
Note: This provider API can be billed per query. This tool constructs the JSON body strictly based on user input and does not send unused properties.
The tool prints structured lines for easy parsing:
-
Count line:
[domainsCount: <n>]
-
Domain lines:
[domain: <value>]
Example:
[domainsCount: 26]
[domain: thehackerschoice.fallguysmania.com]
[domain: hackerschoice.github.io]
...
When --output is provided:
-
stdout remains normal (colored if enabled)
-
the output file receives only the clean, deduplicated domain list:
- no ANSI escape codes
- one domain per line
- overwrite behavior
Example:
sub-alter --api-key "$API_KEY" -di "*thc.org*" -o results.txtresults.txt:
thehackerschoice.fallguysmania.com
hackerschoice.github.io
hackerschoice.workers.dev
...
Overwrite behavior: if results.txt exists, it is overwritten.
Note: Parent directories are not created automatically. Invalid paths cause the tool to exit with an error.
- Go 1.22+
git clone https://github.com/haltman-io/sub-alter.git
cd sub-alter
go mod tidy
go build -o sub-alter ./cmd/sub-alter
./sub-alter -hgo install github.com/haltman-io/sub-alter/cmd/sub-alter@latest
sub-alter -hIf the binary is not found, ensure:
$GOBINor$(go env GOPATH)/binis in yourPATH.
On startup, the tool checks for a YAML file next to the executable:
.sub-alter.yaml
If it does not exist, it is created automatically with:
api_keys: []-
If
--api-key <KEY>is provided → used for the request. -
Else,
.sub-alter.yamlis read:- if
api_keysis empty → tool exits with an error - if multiple keys exist → keys rotate round-robin (per request)
- if
API
--api-key <key>Provide API key (overrides YAML config).
Domains filters
--domain-include <value>(alias:-di) Add to.domains.include[](repeatable / comma-separated, max 4).--domain-exclude <value>(alias:-de) Add to.domains.exclude[](repeatable / comma-separated, max 4).
Subdomains filters
--subdomain-include <value>(alias:-si) Add to.subdomains.include[](repeatable / comma-separated, max 4).--subdomain-exclude <value>(alias:-se) Add to.subdomains.exclude[](repeatable / comma-separated, max 4).
Proxy / TLS
--proxy <url>Proxy URL:http://,https://,socks5://--no-proxyIgnoreHTTP_PROXY/HTTPS_PROXY/NO_PROXY.--insecure(alias:-k) Skip TLS certificate verification.
Rate limit / concurrency
--rate-limit <rps>(alias:-rl) Max requests per second, must be1..30(API limit).--threads <n>Worker threads baseline flag (validated; current tool makes a single request per execution).
Output & logging
--output <path>(aliases:-o,-out) Write clean, deduplicated domain results to file (overwrite).--silent(alias:-s) /--quiet(alias:-q) Hide banner (results only).--verbose(alias:-v) /--debugDebug logs (stderr).--no-color(alias:-nc) Disable ANSI colors.
sub-alter --api-key "$API_KEY" -di "*example.com"sub-alter --api-key "$API_KEY" -di google.com,twitter.com
sub-alter --api-key "$API_KEY" -di google.com -di twitter.comsub-alter --api-key "$API_KEY" -si "aws*" -se "*portal*" -se "*beta*"sub-alter --api-key "$API_KEY" -di google.com -di twitter.com -se "*portal*"sub-alter --api-key "$API_KEY" -di "*thc.org*" -o results.txtHTTP proxy:
sub-alter --api-key "$API_KEY" -di "*example.com*" --proxy http://127.0.0.1:8080SOCKS5 proxy:
sub-alter --api-key "$API_KEY" -di "*example.com*" --proxy socks5://127.0.0.1:9050Ignore environment proxies:
sub-alter --api-key "$API_KEY" -di "*example.com*" --no-proxysub-alter --api-key "$API_KEY" -di "*example.com*" -kWarning:
--insecure/-kdisables TLS verification. Use only when you understand the implications.
The tool maps provider HTTP errors to direct user-facing messages:
400 Bad Request: missing/invalid request fields401 Unauthorized: missing/invalid API key403 Forbidden: restricted access / credits issue / wrong key408 Request Timeout: provider timeout410 Gone: API version deprecated422 Unprocessable Entity: invalid parameters / search term429 Too Many Requests: provider throttling5XX: provider internal error (contact provider support)
- Intended for authorized investigations and cybersecurity assessment workflows.
- API keys are sensitive credentials. Do not hardcode or commit them.
- Output file contains only domain strings (deduplicated) to support safe downstream tooling.
git clone https://github.com/haltman-io/sub-alter.git
cd sub-alter
go mod tidycmd/sub-alter/— CLI entrypointinternal/cli/— flags, validation, usageinternal/api/— HTTP client and request/response modelsinternal/ratelimit/— rate limiter utilitiesinternal/output/— banner, colors, formatting/printerinternal/util/— helpers (YAML keys, output file writer, etc.)
- Keep code/comments/logging in English
- Keep dependencies minimal
- Preserve stable output format unless necessary (document changes)
- Add tests where feasible
- Provide clear summary and rationale
- Include before/after output snippets if formatting changes
- Update documentation when behavior changes
If you discover a security issue in this repository:
-
Do not open a public GitHub issue.
-
Send a report with:
- a clear description of the issue
- impact assessment
- reproduction steps / PoC (if applicable)
- suggested remediation
-
Contact:
- Create a private advisory (recommended) via GitHub Security Advisories (if enabled), or
- Email the maintainers:
[email protected]
This project is licensed under the Unlicense, see the LICENSE file for details.
go build -o sub-alter ./cmd/sub-alter
./sub-alter -h



