HTTP API

Drive it from anything

Everything the interface does is available over HTTP with Basic credentials — from a browser address bar, a shell, a script or a scheduler. No session, no tokens to juggle.

Authentication

Every endpoint except the index requires HTTP Basic credentials — the same username and password used to sign in. The probe engine makes outbound connections on your behalf, so it is never exposed anonymously.

Shell
curl -u 'USERNAME:PASSWORD' 'https://webtool.nosiaht.com/api/v1/scan?sub=example.com'

Credentials also work inline in a URL, which makes a result viewable straight from the address bar. Percent-encode reserved characters in the password (@ becomes %40).

URL
https://USERNAME:PASSWORD@webtool.nosiaht.com/api/v1/scan?sub=example.com

Endpoints

Base URL https://webtool.nosiaht.com/api/v1

GET /api/v1/ no credentials

Machine-readable index: endpoints, port profiles and the batch limit.

Request
curl 'https://webtool.nosiaht.com/api/v1/'
GET /api/v1/scan?sub=<domain>

Enumerate subdomains across six sources and merge them. Add &probe=1 to probe the results in the same call.

Each entry in sources carries ok and count. A source that contributed nothing reports error: "unavailable" and nothing further — the reason describes upstream state and this deployment's configuration, so it is written to the server log instead.

ParameterMeaning
subApex domain to enumerate. Required.
probe1 also probes each host found.
profileWhich ports to scan when probing. Default quick.
Request
curl -u 'USER:PASS' 'https://webtool.nosiaht.com/api/v1/scan?sub=example.com&probe=1'
GET /api/v1/probe?target=<host[,host]>

Probe specific hosts. Up to 100 per call, comma-separated.

Request
curl -u 'USER:PASS' \
  'https://webtool.nosiaht.com/api/v1/probe?target=example.com,www.example.com&profile=full'
GET /api/v1/inspect/<domain>

Deep inspection of one host: all 17 ports with banner confirmation, full TLS certificate, security headers, redirect chain and MX / NS / TXT records.

Request
curl -u 'USER:PASS' 'https://webtool.nosiaht.com/api/v1/inspect/example.com'
POST /api/v1/probe/stream

Same as /probe but emits newline-delimited JSON, one object per host, written the moment each probe finishes. Use this for anything large.

Request
curl -sN -u 'USER:PASS' -X POST \
  -H 'Content-Type: application/json' \
  -d '{"domains":["example.com","www.example.com"],"profile":"quick"}' \
  'https://webtool.nosiaht.com/api/v1/probe/stream'

Port profiles

The profile parameter selects how much of each host is scanned.

ProfilePortsUse
quick default 80, 443 Bulk scanning. Web ports only.
standard 21, 22, 25, 80, 443, 8080, 8443 Common services alongside the web.
full 21, 22, 25, 53, 80, 110, 143, 443, 465, 587, 993, 995, 3306, 5432, 6379, 8080, 8443 Single-host inspection, with DNS records.

Response fields

Each probed host returns the following. Fields are null when they do not apply.

FieldMeaning
state online · offline (refused — host is up, nothing listening) · filtered (no response at all) · unresolved · blocked · invalid
unreachable_reasonWhy, when the state is not online.
protocolScheme of the final URL after redirects, not the one dialled.
status_codeHTTP status of the final response.
addresses, ipv6Resolved A and AAAA records.
http.final_urlWhere the request actually ended up.
http.redirect_chainEvery hop, with its status code.
http.http_versionHTTP/1.1 or HTTP/2.
http.security_headersSix headers as {name: true|false}.
http.server, http.titleServer banner and page title.
tls.gradeA–F. F means the certificate failed validation.
tls.valid, tls.errorWhether it verified, and why not.
tls.days_remainingNegative once expired.
tls.self_signed, tls.covers_hostSelf-signed, and whether the name matches.
open_ports[].bannerService banner, where the protocol announces itself.
open_ports[].confirmedWhether the banner matched the expected service.
cnameCNAME chain and whether its target still resolves.
takeoverDangling-CNAME assessment, or null.
latency_ms, elapsed_msResponse time, and total probe time.

Large scans

A single call probes at most 100 hosts and has to finish inside the platform's request timeout. For a domain with hundreds of subdomains, enumerate first and then stream the probing in batches — results arrive as each host finishes rather than at the end.

Shell
# 1. enumerate only
curl -s -u 'USER:PASS' 'https://webtool.nosiaht.com/api/v1/scan?sub=example.com' \
  | jq -r '.subdomains[]' > hosts.txt

# 2. probe in batches of 100, streamed
split -l 100 hosts.txt batch_
for f in batch_*; do
  jq -Rsc '{domains: (split("\n") | map(select(length > 0))), profile: "quick"}' "$f" \
    | curl -sN -u 'USER:PASS' -X POST -H 'Content-Type: application/json' \
        -d @- 'https://webtool.nosiaht.com/api/v1/probe/stream'
done

Examples

Only hosts with a problem
curl -s -u 'USER:PASS' 'https://webtool.nosiaht.com/api/v1/scan?sub=example.com&probe=1' \
  | jq '.results[]
      | select(.tls.valid == false or .status_code >= 400)
      | {domain, status_code, tls: .tls.grade, reason: .tls.error}'
Certificates expiring within 30 days
curl -s -u 'USER:PASS' 'https://webtool.nosiaht.com/api/v1/scan?sub=example.com&probe=1' \
  | jq -r '.results[]
      | select(.tls.days_remaining != null and .tls.days_remaining < 30)
      | "\(.domain)\t\(.tls.days_remaining) days"'

Errors

Failures return JSON with a stable code you can branch on.

StatuscodeMeaning
400invalid_domainNot a hostname, or an IP address was supplied.
400missing_targetNo target or sub given.
400invalid_profileUnknown profile name.
401unauthorizedMissing or wrong credentials.
403blockedTarget resolves into private address space.
413batch_too_largeMore than 100 hosts in one call.
429rate_limitedToo many requests. Slow down.
503misconfiguredThe server is missing required configuration.

Reachability is measured from this server's network. A host that firewalls or geo-restricts it reports filtered, which means no answer — not that the host is down.