---
name: lookproof
description: Check a domain's email authentication (SPF, DMARC, DKIM, MX, MTA-STS, TLS-RPT, BIMI) and mail providers, DNS records, DNSSEC, CAA and reverse DNS, its TLS certificate, HTTP security headers and RDAP registration, or run a full domain or site health report, with Lookproof's pay-per-request API, paid with x402 in USDC on Base. Use when the user asks whether a domain's mail, DNS or website setup is correct, why mail from a domain is rejected or lands in spam, whether a certificate or domain is about to expire, which DNS records a name has, or for an overall security check of a domain or website.
---

# Lookproof

Lookproof runs mail, DNS and web checks and returns structured JSON: an overall `status`, the check's `data`, and `findings` that explain what was found and why it matters.

## Choose a tool

| Task | Endpoint | Request | Price |
|---|---|---|---|
| Show which certificate authorities may issue for a domain, from its CAA records. | `dns.caa` | `GET https://api.lookproof.dev/v1/dns/caa` | $0.01 per request |
| Report whether a domain is DNSSEC-signed and validates, from the resolvers' AD flag. | `dns.dnssec` | `GET https://api.lookproof.dev/v1/dns/dnssec` | $0.01 per request |
| Resolve selected record types with TTL and the resolver that answered. | `dns.lookup` | `GET https://api.lookproof.dev/v1/dns/lookup` | $0.005 per request |
| One report on a domain's mail and DNS security: nine checks with coded findings. | `domain.health` | `GET https://api.lookproof.dev/v1/domain/health` | $0.08 per request |
| Look up a domain's registrar, expiry date, EPP statuses and nameservers over RDAP. | `domain.rdap` | `GET https://api.lookproof.dev/v1/domain/rdap` | $0.01 per request |
| Check HTTP to HTTPS redirects, HSTS, CSP and the other security headers of a site. | `http.security_headers` | `GET https://api.lookproof.dev/v1/http/security-headers` | $0.01 per request |
| Check a domain's BIMI record, its logo and certificate URLs, and DMARC enforcement. | `mail.bimi` | `GET https://api.lookproof.dev/v1/mail/bimi` | $0.01 per request |
| One report covering MX, SPF, DMARC and DKIM for known selectors. | `mail.check` | `GET https://api.lookproof.dev/v1/mail/check` | $0.03 per request |
| Run the mail configuration check on up to 20 domains in one request. | `mail.check.bulk` | `POST https://api.lookproof.dev/v1/mail/check/bulk` | $0.024 per item, minimum $0.03 per request, at most 20 items |
| Check the DKIM public key record for a given selector. | `mail.dkim` | `GET https://api.lookproof.dev/v1/mail/dkim` | $0.01 per request |
| Try 27 common DKIM selectors for a domain and check every key that is found. | `mail.dkim_discover` | `GET https://api.lookproof.dev/v1/mail/dkim-discover` | $0.02 per request |
| Look up and explain a domain's DMARC policy and tags. | `mail.dmarc` | `GET https://api.lookproof.dev/v1/mail/dmarc` | $0.01 per request |
| Check the MTA-STS record and policy file, MX coverage, and the TLS-RPT record. | `mail.mta_sts` | `GET https://api.lookproof.dev/v1/mail/mta-sts` | $0.02 per request |
| List a domain's mail servers with priorities, including null MX. | `mail.mx` | `GET https://api.lookproof.dev/v1/mail/mx` | $0.01 per request |
| Name the mailbox provider, gateways and sending services a domain uses, from MX and SPF. | `mail.provider` | `GET https://api.lookproof.dev/v1/mail/provider` | $0.005 per request |
| Check PTR records and forward confirmation (FCrDNS) for a domain's MX addresses. | `mail.ptr` | `GET https://api.lookproof.dev/v1/mail/ptr` | $0.01 per request |
| Parse and evaluate a domain's SPF policy, including the DNS lookup budget. | `mail.spf` | `GET https://api.lookproof.dev/v1/mail/spf` | $0.01 per request |
| One report on a site's TLS certificate, HTTPS redirects, security headers and domain expiry. | `site.health` | `GET https://api.lookproof.dev/v1/site/health` | $0.025 per request |
| Check the certificate a domain serves on port 443: expiry, name, chain and key. | `tls.certificate` | `GET https://api.lookproof.dev/v1/tls/certificate` | $0.01 per request |
| Run the items of a paid bulk request that failed for technical reasons again, free of charge. | `mail.check.bulk.retry` | `POST https://api.lookproof.dev/v1/mail/check/bulk/retry` | Free |

- Use `mail.check` for a full overview of a domain's mail setup; use a single check when the user asks about one record.
- Use `domain.health` for the mail and DNS side of a domain and `site.health` for the web side (TLS certificate, redirects and security headers, domain expiry).
- Use `mail.check.bulk` for 2 to 20 domains in one request.

## Payment (x402)

Network: Base (`eip155:8453`), asset USDC `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`.

1. Send the request without payment. The API answers `402 Payment Required`; the body and the `PAYMENT-REQUIRED` header state the exact price in `accepts[0].amount` (USDC atomic units, 6 decimals).
2. Check the amount before you sign. One request never costs more than $0.48.
3. Sign the EIP-3009 authorization with an x402 client and send the same request again with the `PAYMENT-SIGNATURE` header.
4. The result comes back with `200` and a `PAYMENT-RESPONSE` header (the settlement receipt).

If the answer is lost after payment, send the same request with the same signature again within 24 hours: the paid result is delivered again without a new charge.

## Input

- `dns.caa`: `domain` (string, required; 1–1024 characters)
- `dns.dnssec`: `domain` (string, required; 1–1024 characters)
- `dns.lookup`: `name` (string, required; 1–1024 characters), `types` (array of one of A, AAAA, CNAME, MX, NS, TXT, SOA, CAA, SRV, optional; 1–9 items; default ["A"])
- `domain.health`: `domain` (string, required; 1–1024 characters)
- `domain.rdap`: `domain` (string, required; 1–1024 characters)
- `http.security_headers`: `domain` (string, required; 1–1024 characters)
- `mail.bimi`: `domain` (string, required; 1–1024 characters), `selector` (string, optional; 1–80 characters; default "default")
- `mail.check`: `domain` (string, required; 1–1024 characters), `dkim_selectors` (array of string, optional; at most 5 items; each 1–200 characters; default [])
- `mail.check.bulk`: `domains` (array of string, required; 1–20 items; each 1–1024 characters)
- `mail.dkim`: `domain` (string, required; 1–1024 characters), `selector` (string, required; 1–200 characters)
- `mail.dkim_discover`: `domain` (string, required; 1–1024 characters)
- `mail.dmarc`: `domain` (string, required; 1–1024 characters)
- `mail.mta_sts`: `domain` (string, required; 1–1024 characters)
- `mail.mx`: `domain` (string, required; 1–1024 characters)
- `mail.provider`: `domain` (string, required; 1–1024 characters)
- `mail.ptr`: `domain` (string, required; 1–1024 characters)
- `mail.spf`: `domain` (string, required; 1–1024 characters)
- `site.health`: `domain` (string, required; 1–1024 characters)
- `tls.certificate`: `domain` (string, required; 1–1024 characters)

Invalid input is answered with `422` before any price is given.

## Reading results

- `status` is the worst finding severity: `ok`, `info`, `warning` or `error`.
- `unknown` means the check was incomplete, for example after a DNS timeout. It is not an error in the domain: do not report it as a failure; try again later.
- Each finding has a `code`, `severity`, `message`, `explanation`, and often a `recommendation` and `evidence`. Every code is explained at https://lookproof.dev/findings
- A result with negative findings is still a delivered result.

## When you are not charged

Errors never cost anything:

- `402`: no payment is taken.
- `400` (bad_request): The request is malformed.
- `409` (payment_in_progress, payment_bound_to_other_request): This payment is already being processed, or it is bound to a different request. No new payment is taken.
- `413` (payload_too_large): The body is larger than 64 KB.
- `422` (invalid_input): The input failed validation on a request that carries a payment; nothing is charged. Without a payment, invalid input gets a 402 whose error field names the problem.
- `429` (rate_limited): Too many requests from this IP address or payer.
- `502` (check_failed): The check could not be completed.
- `503` (busy, unavailable, payments_unavailable): The service is busy or temporarily unavailable.
- `504` (deadline_exceeded): The check ran out of time.
- A bulk request where every item failed (answered `502`).

## Free retry of failed bulk items

1. A paid `mail.check.bulk` response where items failed for a technical reason (`error` on the item) holds a `retry_token`.
2. Within 15 minutes, send `POST https://api.lookproof.dev/v1/mail/check/bulk/retry` with `{"retry_token": "<token>"}` and no `PAYMENT-SIGNATURE` header.
3. The answer is the whole bulk result with the retried items merged in. If items still fail and attempts are left, it holds a new `retry_token`; the old one stops working.

- At most 3 attempts in total. Only the failed items run, with the original domains; the input cannot be changed. Nothing is charged.
- Items with findings are results, not failures: there is nothing to retry.
- `400` (bad_request): The request is malformed.
- `404` (retry_token_invalid): The retry token is unknown, or a newer token from a later attempt has replaced it.
- `409` (retry_in_progress): An attempt with this retry token is already running.
- `410` (retry_token_expired): The retry token has expired (15 minutes after it was issued), all 3 attempts are used, or no failed items are left.
- `413` (payload_too_large): The body is larger than 64 KB.
- `422` (invalid_input): The body is invalid: it must hold only retry_token.
- `429` (rate_limited): Too many requests from this IP address.
- `503` (busy, unavailable): The service is busy or temporarily unavailable. The attempt does not count.

## Limits

- Only public DNS: names are resolved through public resolvers, so private or internal zones cannot be checked.
- No mailbox probing: Lookproof never connects to mail servers to test addresses and never sends mail.
- Web checks read only ports 443 and 80 and the response headers of the start page; page content is never read, and RDAP results never include contact details.
- DKIM needs a selector (for example `s=` in a DKIM-Signature header); keys cannot be listed without one.
- Bulk: at most 20 domains per request.
- Ordinary wallets (EOA) only: smart-contract wallets (ERC-1271/ERC-6492 signatures) are refused with `402` and nothing is charged.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| Status `unknown` | The check was incomplete, for example a DNS timeout | Not a failure of the domain; try again later |
| `422` | The input is invalid | Fix the input; see Input above |
| DKIM check asks for a selector | DKIM keys cannot be listed without one | Read `s=` from a DKIM-Signature header of a real message |
| Bulk is rejected | More than 20 domains | Split the request |

## More

- API reference: https://lookproof.dev/docs/api
- OpenAPI 3.1: https://lookproof.dev/openapi.json
- Payments: https://lookproof.dev/docs/payments
- Findings reference: https://lookproof.dev/findings
