← Blog
August 20, 2026 Esteve Castells 8 min

Reverse MX Lookup in DomScan: Scope, Limits, and Safer Use

DomScan's deprecated Reverse MX API searches a short-lived cache built from prior DNS lookups. Learn exactly what a result means, where gaps come from, and how to verify each lead.

Reverse MXDNSEmailOSINTAPISecurity

A normal MX lookup starts with a domain and returns the hostnames that accept mail for it. RFC 1035 defines an MX record as a preference value followed by an exchange hostname. RFC 5321 then tells sending mail systems to prefer lower values and to resolve the selected hostname to an A or AAAA address.

A reverse MX lookup asks a different question: which previously observed domains pointed their MX records to one exact mail server hostname? DNS has no standard query that answers that question. A service must build an index from earlier forward lookups or another collection process. The scope of that collection determines the scope of every reverse result.

What the DomScan index contains

The reverse MX index is populated only when DomScan successfully handles a GET /v1/dns/all lookup for a domain and that lookup returns one or more MX records. The route normalizes each MX hostname to lowercase, removes a trailing dot, and attempts to add the queried domain under that exact hostname. Other DNS endpoints, outside passive DNS feeds, zone files, certificate logs, and web crawls do not populate this index.

Those writes are deliberately best effort. DomScan waits for the indexing attempts to settle, but a KV failure does not turn an otherwise successful DNS response into an API error. This protects the forward DNS lookup, but it also means the reverse index can have holes. A missing domain can mean that nobody queried it through /v1/dns/all during the relevant window, that its MX answer was empty, or that an index write failed.

Each per-MX-host key has a seven-day TTL. A repeated observation moves the domain to the newest end of the list and refreshes the key's retention. The service keeps at most 10,000 recent domain entries for one MX hostname. This is a rolling cache with a hard cap, not historical coverage. It does not expose a first-seen timeline or preserve old provider migrations after the cache expires.

The TTL belongs to the whole MX key, not to each domain in its list. A write for any domain on that MX host rewrites the list and resets the key's TTL, so an older member can remain while other observations keep the key alive. Per-domain enrichment expires separately. Treat seven days as the index retention mechanism, not a guarantee that every returned row was observed within the past seven days.

Request contract

The endpoint accepts `mx` as the primary query parameter. The legacy `mailserver` alias still works, but `mx` takes precedence if both are present. Hostnames are normalized to lowercase without a final dot before lookup, so `ASPMX.L.GOOGLE.COM.` and `aspmx.l.google.com` address the same cache key.

  • `mx`: the exact mail server hostname to search. Example: `aspmx.l.google.com`.
  • `mailserver`: a deprecated alias for `mx`.
  • `match`: optional, defaults to `exact`, and no other value is supported.
  • `limit`: the number of recent raw index entries to evaluate, from 1 to 1000. The default is 100.
  • `include_apex_only`: defaults to `true`. Set it to `false` to preserve observed hostnames rather than returning one row per apex domain.
Exact-host reverse MX request
curl --get 'https://domscan.net/v1/reverse/mx' \
  --data-urlencode 'mx=aspmx.l.google.com' \
  --data-urlencode 'match=exact' \
  --data-urlencode 'include_apex_only=true' \
  --data-urlencode 'limit=100' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Substring, suffix, wildcard, provider-family, and IP-equivalence matching are not implemented. A request such as `match=suffix` returns a 400 response. Querying `aspmx.l.google.com` does not also search `alt1.aspmx.l.google.com`, and it does not group different hostnames that happen to resolve to the same address. Run a separate exact query for each MX hostname you want to inspect.

Limit is applied before apex deduplication

The ordering of operations matters. DomScan first takes the newest `limit` entries from the raw per-host index. It then applies apex-domain deduplication when `include_apex_only=true`. If the newest 100 raw entries contain several observed hostnames under the same registrable domain, the response can contain fewer than 100 rows even when older distinct apex domains remain elsewhere in the index. Increasing `limit` changes the raw window being evaluated. It is not pagination, and `next_cursor` is always null.

With apex-only mode enabled, the response rewrites `domain` to the derived apex while retaining an `apex` field. With the option disabled, the response preserves the observed hostname in `domain`. The apex calculation is a convenience for grouping results, not evidence that the root domain itself published the MX record.

How to read the response

Representative response with incomplete observation evidence
{
  "query": {
    "mx": "aspmx.l.google.com",
    "match": "exact",
    "include_apex_only": true
  },
  "deprecated": true,
  "results": [
    {
      "domain": "example.com",
      "apex": "example.com",
      "mx": "aspmx.l.google.com",
      "all_mx": [
        { "host": "aspmx.l.google.com", "priority": null }
      ],
      "last_seen": null,
      "reason": {
        "type": "HAS_MX",
        "matched": "aspmx.l.google.com"
      }
    }
  ],
  "summary": {
    "total_found": 1,
    "returned": 1
  },
  "freshness_summary": {
    "source": "passive_dns",
    "cache_status": "passive_cache_only",
    "warnings": ["passive_cache_only"],
    "last_seen_span_days": null
  },
  "page": { "limit": 100, "next_cursor": null },
  "cache": {
    "hit": null,
    "age_s": null,
    "ttl_s": null,
    "key": null
  }
}

`summary.total_found` is the number of raw entries currently stored for that exact MX key before the request limit and apex deduplication. `summary.returned` is the number of rows left afterward. The freshness summary reports whether the source was the passive cache, how many apex rows were removed, and warnings such as `passive_cache_only`, `no_cached_matches`, `result_limited`, or `passive_index_unavailable`.

Do not treat nullable fields as precise history. DomScan stores a separate per-domain MX observation for enrichment, but that record can be missing or unreadable even when the reverse key still contains the domain. In that case `last_seen` is null, and `all_mx` can fall back to the matched hostname with a null priority. The legacy `cache` object is also entirely nullable because the endpoint cannot measure cache hit, age, TTL, or key provenance for the response.

What a shared MX host does and does not prove

A match means DomScan previously observed a domain returning that exact hostname in an MX answer. That is all. It does not prove that the domain still uses the host, that two results share an owner, or that the mail provider controls any customer domain. MX records are routing declarations, not corporate records.

Shared providers create the largest association trap. A result for `aspmx.l.google.com` can contain unrelated Google Workspace customers. The same problem appears with hosting companies, managed service providers, forwarding platforms, and regional mail operators. Even a custom-looking hostname can serve independent customers. A common MX target is useful as a pivot, but it is weak evidence of an organizational relationship.

The cache can also preserve stale-looking relationships for up to seven days after a provider change, depending on the last write to that key. Conversely, a current relationship may be absent because no qualifying /v1/dns/all lookup populated it. An empty response is not proof that no other domain uses the mail server.

A defensible investigation workflow

Start with a domain you already have reason to examine. Run a fresh DNS lookup and record every exact MX hostname and preference value. Query the deprecated reverse endpoint separately for each hostname. Treat every returned domain as a candidate, then verify it with a fresh /v1/dns/all lookup before drawing conclusions.

  1. Confirm that the candidate currently publishes the matched MX hostname.
  2. Compare its complete MX set and priorities, not just one shared target.
  3. Check whether the target belongs to a broad provider or a narrowly used server.
  4. Review current DNS, registration data, certificates, web content, and reputation signals for independent support.
  5. Record the API warnings and nullable evidence so later reviewers can see the limits of the lead.

This workflow is suitable for triage, a scoped watchlist, or revisiting domains already queried through DomScan. It is not suitable for enumerating every customer of a mail provider, mapping an organization's complete domain portfolio, proving a phishing cluster, or reconstructing provider migrations. Those jobs require broader collection, historical retention, and independent attribution evidence.

MX facts that still matter

RFC 5321 requires SMTP senders to order MX records by preference, with lower values preferred. Equal-preference destinations should be randomized when there is no reason to favor one. That means priority describes delivery order, not ownership or server quality. A secondary MX can be just as relevant to a reverse lookup as the primary one.

The MX value is a hostname, not an IP address. RFC 2181 also says the hostname used as an MX target must not be a CNAME alias. Reverse MX therefore operates on the literal exchange hostname published in the MX record. Grouping targets by resolved IP would answer a different question and can create more false associations on shared infrastructure. DomScan does not perform that grouping in /v1/reverse/mx.

When to use something else

Use /v1/dns/all when you need the current MX records for a known domain. Use a dedicated passive DNS provider when you need broad collection, long retention, first-seen history, or internet-scale reverse search. Use the deprecated DomScan endpoint only when its narrow cache provenance fits the question and you can validate every result independently.

That narrower framing makes the endpoint less dramatic, but more useful. A cache hit is a concrete prior observation. The correct next step is verification, not a claim that DomScan found every domain on the server.

Key Takeaways

  • DomScan's /v1/reverse/mx endpoint is deprecated and does not search an internet-wide passive DNS database.
  • The endpoint supports exact MX hostname matching only and reads a best-effort seven-day index populated by prior /v1/dns/all lookups.
  • Each MX key retains at most 10,000 recent domain entries, while the request limit defaults to 100 and is applied before optional apex deduplication.
  • Observation fields such as last_seen and MX priority can be null, and failed or missing index writes can leave gaps.
  • A shared MX host is a lead, not proof of common ownership, control, intent, or organizational affiliation.

Related Articles