We'd rather you know the real boundaries of what's checked than have a result imply more confidence than the data supports. This page lists every signal behind every service, with nothing summarized away. If a signal isn't listed here, we don't check it, and we say so explicitly where a gap is a real limitation, not just an omission.
What a result means, and what you do next
Nothing matched on any list we checked, and no warning signals fired.
- You can carry on. In an automated flow, this is the "approve" path.
- The check is saved with a reference and a timestamp, so you can show later that you screened this person or wallet, and against which lists.
- It's closed automatically. Nothing lands in your case queue.
A clear result covers the lists named in the response, as they were on that day. It isn't a guarantee about the person or wallet in general.
Something matched or looked risky. This is not a final answer: a person on your side needs to look at it.
- Pause the onboarding, payout or transfer until it's reviewed.
- Compare the details. Many name matches are someone else with a similar name. The field comparison, included in every name check, puts date of birth, nationality and type side by side with the listed record.
- Decide: clear it if it's clearly not the same person or the warning doesn't apply, or escalate it to your compliance lead if it might be.
- With an account, every hit waits in your case queue with Clear and Escalate buttons, and your decision is recorded next to the check.
We report what matched and how closely. The decision, and anything you report to authorities, is yours.
Email and IP checks: how the risk level is set
These don't match a list. They run several separate tests and combine them. Each test is labelled critical or minor in advance, depending on how serious it would be on its own.
- Any critical test fails: high risk, flagged straight away.
- Only minor tests fail: none is low risk, 1 or 2 is medium, 3 or more is high.
- A test couldn't run (a server didn't answer, say): it's shown as "unknown", never counted as a pass.
For developers: a critical failure sets redFlag: true and
riskLevel: "high"; otherwise riskLevel is low, medium
or high from the count of minor flags.
No AI makes these calls
Every check on this page is plain, fixed code run against a real data source. The same input on the same data always gives the same result.
Sanctions name screening
Fuzzy match against a list of names, not a composite of independent signals: one check, one data source.
| What we check | |
|---|---|
| List coverage | Sanctions lists loaded in our database: OFAC SDN, UN Security Council Consolidated List, EU Consolidated Financial Sanctions List, UK Sanctions List (FCDO). Only lists that are actually loaded are checked, every response names them in listsChecked, and /lists shows the live record count and last refresh date per list. |
| Match method | Trigram similarity against both primary names and known aliases, not an exact string match, so minor spelling differences, transliteration, and word-order changes can still surface a match. |
| What's returned | The single highest-scoring candidate above an internal similarity threshold from each list, so a name that resembles entries on three lists returns up to three hits, one per list, strongest first. Not every candidate within a list. |
Any list not shown in listsChecked or on
/lists. "No match" means no match on the lists
named in the response, nothing broader. Other national lists (Canada,
Australia, Switzerland and others) are not included. We also don't screen for Politically Exposed Persons
(PEP) status or adverse media (negative news). Both are separate,
unbuilt products, not folded into this result.
Crypto wallet address screening
| What we check | |
|---|---|
| List coverage | Every digital-currency address on OFAC's SDN list, read daily from OFAC's own advanced XML file. That covers every asset OFAC lists (Bitcoin, Ethereum, USDT, USDC, Tron, Solana, Litecoin, Dogecoin and more), and each hit names the listed party and its SDN number as OFAC records it. |
| Match method | Exact string match on the address, not fuzzy. EVM-family addresses (0x...) are compared case-insensitively; everything else (Bitcoin, Solana, etc.) is case-sensitive, matching how those address formats actually work. |
| Stablecoin freezes | A separate list: wallets the issuer has frozen. Today that's Tether's USDT freeze list on Tron; USDT on Ethereum and Circle's USDC freezes aren't covered yet. We read it straight from the token contract's public freeze and unfreeze events and refresh it daily, so an unfrozen wallet drops off. Reported as frozenByIssuer, never as a sanctions hit. A frozen wallet can't move its USDT or USDC, so funds sent there are stuck. |
| Known hack proceeds | A second, separate list: addresses publicly identified as attacker-controlled or holding stolen funds in major hacks. Sources are law-enforcement notices (FBI notices on Bybit, Stake.com, and Atomic Wallet, Alphapo and CoinsPaid) and the victims' or security firms' own incident write-ups, each entry linked to where it was published. Reported as hackFunds, never as a sanctions hit. Today it covers Bybit, Kelp DAO, Drift, Truebit, Resolv, Step Finance, Stake.com, and Atomic Wallet, Alphapo and CoinsPaid; /lists shows the current count. |
A sanctions hit gives the listed party's name and SDN number, but not their date of birth or sanctions program; look those up on OFAC's site with the SDN number. "Not sanctioned" means not on this one list. It is not a guarantee the address is otherwise clean, has no transaction history with sanctioned parties, or isn't a mixer/exchange hot wallet.
The hack list only flags the wallets named in its sources. Stolen funds usually move on through many more wallets, bridges and mixers within hours, and we don't follow them. It also only grows when a hack is publicly documented, so a recent incident may be missing.
Email trust check
A "fan-out and score" composite: 10 independent signals run in parallel, each judged pass/flag/unknown, then combined into one risk level. All of them are free and zero-key.
| Signal | Severity | What it actually checks |
|---|---|---|
| Syntax and mail server | critical | Valid address format and the domain has an MX record at all. A domain that can't receive mail is flagged outright. |
| Disposable email provider | critical | Checked against a maintained open-source list of known disposable/temp-mail domains (10minutemail, etc.). |
| Provider type | informational | Consumer free-mail (Gmail, Yahoo, etc.) vs. a custom/corporate domain. Never flags either way on its own. |
| Domain registration age | minor | How long ago the domain was registered, via RDAP. Flagged if under 30 days old. |
| Domain certificate history | minor | Public log of every SSL certificate ever issued for the domain, via crt.sh, an independent age signal. |
| Mailbox verification | critical | Best-effort. We connect to the domain's mail server and ask if the specific mailbox would accept mail (no message sent). Many mail servers block this or accept every address regardless (a "catch-all"), both cases come back unknown, never a false "verified." |
| Mail server reputation (DNSBL) | critical | The mail server's IP checked against the Spamhaus ZEN blocklist, the same blocklist the IP risk check uses. |
| Mail provider | informational | Identifies well-known infrastructure (Google Workspace, Microsoft 365, Zoho, etc.) by fingerprinting the mail server hostname. Informational only. |
| Look-alike domain check | critical | Compares the domain against major free-mail providers using edit distance. It catches deliberate look-alikes like "gmial.com" or "yah00.com." |
| Account type | informational | Flags local parts like admin@, support@, noreply@ as a shared/role mailbox rather than an individual. Informational only. |
The mailbox-verification probe runs on port 25, which some cloud
hosting blocks outbound entirely. If it's blocked on our end, that
signal comes back unknown on every single check, it's
worth checking the detail field on that signal yourself
rather than assuming it ran.
IP risk check (beta)
IPv4 only. Two scored signals and one informational one. The smallest of the checks, and the most honest about it.
| Signal | Severity | What it actually checks |
|---|---|---|
| Blocklist status (Spamhaus ZEN) | critical | DNS-based lookup against Spamhaus's ZEN blocklist. It flags known spam sources, botnet members, and hijacked netblocks. |
| Tor exit node | critical | Checked against the Tor Project's own public exit-node list (refreshed hourly on our side). Flags that the address is a known point where Tor traffic exits to the open internet, origin of the underlying traffic is anonymized. |
| Network allocation | informational | Who the IP block is allocated to, via RDAP. Never scored: plenty of legitimate traffic comes from datacenter or cloud IPs, so this is context, not a verdict. |
VPN/hosting classification and community abuse reports (AbuseIPDB) both need a paid key we haven't provisioned. IPv6 isn't supported at all yet, only IPv4. Private and reserved ranges (RFC 1918, loopback, etc.) are rejected outright with an error rather than a "low risk" result, since there's no public reputation to check for an address that isn't routable on the open internet.
Keeping this page honest
Every response from every endpoint already states exactly which signals
were checked (signalsChecked, the signals
array, or listsChecked). Nothing is checked silently, and
nothing on this page should ever say more than the API itself returns.
If we add a signal, remove one, or change what a severity means, this
page gets updated the same day. See /docs for the
full technical API reference (request/response shapes, pricing,
payment mechanics) and /lists for live record
counts on the list-based checks.