Sanctions & AML Screener: OFAC, EU, UK, UN & Crypto Wallets
Pricing
from $2.00 / 1,000 results
Sanctions & AML Screener: OFAC, EU, UK, UN & Crypto Wallets
Batch-screen names, companies and crypto wallets against OFAC SDN by default, or EU, UK, UN and 470+ other lists. Exact and alias name matching; add birth date and country to help confirm or rule out a hit. Each match is scored and explained, each no-match gets an audit row. $2 per 1,000 results.
Pricing
from $2.00 / 1,000 results
Rating
0.0
(0)
Developer
Philip Kirkbride
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 hours ago
Last modified
Categories
Features
Share
Sanctions & Watchlist Screening — OFAC, EU, UK, UN and 470+ lists
Screen a client list — names, companies, vessels and crypto wallet addresses — against official sanctions and watchlists, and get one auditable row per result: which list matched, the match tier, a deterministic score with the reasons behind it, the programs and authorities, the public source link, and an explicit no-match row for every subject that found nothing. Built for AML/KYC onboarding, counterparty due diligence, supplier vetting, shipment and payment checks, and periodic re-screening of a book of clients.
Quick start
Paste your names and addresses and run:
{"queries": ["VTB Bank","Lazarus Group","0xE950DC316b836e4EeFb8308bf32Bf7C72a1358FF"],"subjects": [{"name": "Ivan Ivanov", "birthDate": "1975-02-11", "country": "ru", "id": "client-0042"}],"datasets": ["us_ofac_sdn", "eu_fsf"]}
An empty input ({}) runs a small example (two names and one subject with criteria), so you
can see the output shape before pasting your own list; the status message says it was the
example. A list given but empty ({"queries": []}) stops at once with a message naming it,
so an empty batch never screens the examples by mistake.
What you get
- One row per match — which list(s) matched, the tier (
exactprimary name,aliasAKA,addresswallet), amatchScorewith itsmatchReasons, the entity type, countries and nationalities, sanction programs, authorities, the sanction reason, the OpenSanctions profile link and the official source URL. - One audit row per no-match —
match: false, so a screening file proves every subject was checked, not just the ones that hit. - Birth date and country criteria — submit them with a name and each row reports
birthDateMatch/countryMatchand moves the score, so a common-name hit can be disposed of without re-reading the list. - Wallet screening — sanctioned crypto addresses (BTC, ETH, TRON, USDT, XMR, …) matched by address, including the sanctioned holder when the list links one.
- Freshness on every row —
datasetsMeta[].generatedAtis the list build the row was screened against, and the run summary states the cache age per dataset.
Screening a client batch
Two input lists, screened together in one run (up to 500 entries in total):
queries— plain names and wallet addresses, the original input.subjects— the same, as objects that addbirthDate,countryand your own reference (id, echoed back asqueryId).
{"queries": ["Severnaya Logistics LLC","TQn9Y2khEsLJW1ChVWFMSMeRDow5oK2Sfc"],"subjects": [{"name": "Acme Trading FZE", "country": "ae", "id": "supplier-118"},{"name": "Ivan Ivanov", "birthDate": "1975-02-11", "country": "ru", "id": "client-0042"},{"name": "Ivan Ivanov", "birthDate": "1988-06", "country": "ru", "id": "client-0043"}]}
The two Ivan Ivanov rows are two separate subjects (both are screened, each with its own
queryId and its own birth-date verdict); duplicate spellings of the same subject with the
same criteria are screened once. For a book larger than 500 entries, split it across runs
and join the results on queryId — or schedule the same input, because list data is reused
between runs (see Freshness and cost).
Input
| Name | Type | Default | What it does |
|---|---|---|---|
queries | array | example sample | Up to 500 plain names and/or crypto addresses. |
subjects | array | example sample | Up to 500 objects {name, birthDate, country, id} — the same subjects with criteria. |
datasets | array | ["us_ofac_sdn"] | Up to 8 datasets to screen against — see Datasets covered. |
maxDatasetAgeHours | integer | 168 | Reuse the locally held list data while it is younger than this; re-fetch when older. |
includeAliases | boolean | true | Also match known aliases / AKAs (tier alias). Off = primary names only. |
subjects object fields:
| Field | Required | Example | Notes |
|---|---|---|---|
name | yes | "Ivan Ivanov" | Entity name (case-insensitive) or crypto address. |
birthDate | no | "1975-02-11" | YYYY, YYYY-MM or YYYY-MM-DD; compared on the shared granularity (a year-only list entry compares years). |
country | no | "ru" | ISO 3166-1 alpha-2 code, case-insensitive — the subject's nationality or the company's jurisdiction. |
id | no | "client-0042" | Your reference (≤100 chars), echoed on every row of that subject as queryId. |
Match tiers and match scores
Matching is deterministic and equality-based; there is no fuzzy name similarity. Each
match carries a declared tier and a matchScore derived from it:
| Tier | Meaning | Score base |
|---|---|---|
exact | The query equals the listed primary name (after case, spacing and punctuation normalization). | 0.95 |
alias | The query equals a known alias / AKA of a listed target. | 0.85 |
address | The query equals a sanctioned wallet address (publicKey). | 1.00 |
The score then moves with the criteria you submitted, against the public list record:
| Criterion | Confirmed | Conflicting |
|---|---|---|
birthDate | +0.04 | −0.10 |
country (country or nationality on the record) | +0.04 | −0.10 |
The result is clamped to 0–1 and rounded to two decimals, and matchReasons spells out
why: tier:exact, birthDate:match, birthDate:conflict, birthDate:not-in-list,
country:match, country:conflict, country:not-in-list. A no-match row carries
matchScore: 0.0 and no reasons.
Two rules matter for compliance work:
matchScoreis a ranking, not a probability. A 0.95 does not mean "95 % likely to be sanctioned"; it means "primary-name hit with no criteria evidence either way". Use it to order a review queue, never as a risk decision.- Criteria never remove a match. A conflicting birth date lowers the score and flags
birthDateMatch: false; the row is still delivered, because silently dropping a name hit is how screening tools produce false negatives.nullmeans "not comparable" — the record carries no birth date or country, which is not a conflict.
Datasets covered
Official OpenSanctions bulk data — the same data the paid screening wrappers resell.
The default is the US OFAC SDN list; add more with datasets.
| Dataset | What it covers | Targets | Entities | Bulk size |
|---|---|---|---|---|
us_ofac_sdn (default) | US Treasury OFAC Specially Designated Nationals, including sanctioned wallets | ~20,200 | ~72,000 | ~53 MB |
us_trade_csl | US consolidated screening list (State, Commerce/BIS, Treasury, DHS) | ~24,100 | ~30,500 | ~25 MB |
eu_fsf | EU Financial Sanctions Files (all member states) | ~6,100 | ~15,900 | ~17 MB |
gb_fcdo_sanctions | UK FCDO (OFSI) sanctions list | ~6,300 | ~18,500 | ~22 MB |
un_sc_sanctions | UN Security Council consolidated list | ~1,000 | ~2,900 | ~3 MB |
sanctions | All sanctions lists merged into one deduplicated dataset | ~71,900 | ~291,700 | ~354 MB |
datasets accepts any of the 470+ dataset names in the
OpenSanctions catalog,
including national and thematic lists. Counts and sizes are the 2026-09-06 build and
grow over time; every row reports the exact build (generatedAt) it was screened against.
The merged sanctions dataset screens everything at once but is ~354 MB of list data —
give that run 1024–2048 MB of memory and a longer timeout.
Screening covers sanctions and watchlist designations only. It is not a PEP database, not adverse media, and not identity verification — see the limitations in the run summary.
Output
One JSON row per matched target (an entity hit in several lists merges into one row with
all of them in lists), plus one match: false row per subject with no match.
| Field | What it holds |
|---|---|
recordKey | Stable row key: os:{query}:{entityId}, or os:{query}:nomatch. |
query, queryId, queryType | The subject as submitted, your reference, and name/address. |
queryBirthDate, queryCountry | The criteria you submitted for that subject (or null). |
match, confidence, matchScore, matchReasons | Result, tier, score and the reasons behind the score. |
matchedName, caption | The list label that matched and the OpenSanctions caption. |
targetType | Person, LegalEntity, Company, Organization, Vessel, CryptoWallet, Airplane, … |
lists | Every selected dataset the target matched in. |
countries, nationalities, birthDates | What the public list record carries (union across matched lists). |
birthDateMatch, countryMatch | true / false / null (not comparable) for the criteria you submitted. |
topics, programs, authorities | Sanction topics, programs (e.g. GLOMAG, RUSSIA-EO14024) and issuing authorities. |
sanctions | Per-list designations: program, authority, country, reason, source URL, authority id, dataset. |
sourceUrl, entityUrl | The official source link and the OpenSanctions profile page. |
publicKey, currency, holderName | Wallet address, currency and the sanctioned holder, for address matches. |
datasetsMeta, screenedAt | Provenance: dataset build time, target counts, cache state and age, screening timestamp. |
Example — a person screened with a matching birth date and country:
{"recordKey":"os:michael kuajien:NK-22HtK7WrxZ2sU3rmhz6PuZ","source":"opensanctions-bulk","kind":"sanctions_screen","query":"Michael Kuajien","queryId":"client-0042","queryType":"name","queryBirthDate":"1979-01-01","queryCountry":"ke","match":true,"confidence":"exact","matchScore":1.0,"matchReasons":["tier:exact","birthDate:match","country:match"],"matchedName":"Michael Kuajien","caption":"Michael Kuajien","targetType":"Person","lists":["us_ofac_sdn"],"countries":["ke"],"nationalities":["ss"],"birthDates":["1979-01-01"],"birthDateMatch":true,"countryMatch":true,"topics":["sanction"],"programs":["GLOMAG"],"authorities":["Office of Foreign Assets Control"],"sanctions":[{"dataset":["us_ofac_sdn"],"program":["GLOMAG"],"authority":["Office of Foreign Assets Control"],"reason":["Executive Order 13818 (Global Magnitsky)"],"sourceUrl":["https://www.treasury.gov/resource-center/sanctions/Pages/default.aspx"],"authorityId":["28033"]}],"sourceUrl":"https://sanctionssearch.ofac.treas.gov/Details.aspx?id=28033","entityUrl":"https://www.opensanctions.org/entities/NK-22HtK7WrxZ2sU3rmhz6PuZ/","publicKey":null,"currency":null,"holderName":null,"datasetsMeta":[{"dataset":"us_ofac_sdn","generatedAt":"2026-09-06T14:10:01","targets":20234,"cache":"hit","ageHours":2.1}],"screenedAt":"2026-11-10T04:20:00+00:00"}
And the audit row for a subject that found nothing:
{"recordKey":"os:acme trading fze:nomatch","query":"Acme Trading FZE","queryId":"supplier-118","queryType":"name","queryCountry":"ae","match":false,"confidence":null,"matchScore":0.0,"matchReasons":[],"matchedName":null,"targetType":null,"lists":[],"countries":[],"birthDateMatch":null,"countryMatch":null,"datasetsMeta":[{"dataset":"us_ofac_sdn","generatedAt":"2026-09-06T14:10:01","targets":20234,"cache":"hit"}],"screenedAt":"2026-11-10T04:20:00+00:00"}
Run summary
The default key-value store record OUTPUT reports: status, usedExample, subjects and
criteria counts, matched vs no-match subjects, rows by tier and by score band
(1.00, 0.90-0.99, below-0.90), per-dataset coverage (build time, target count, cache
hit/miss and age), the scoring method, warnings naming the subjects with no match, and the
limitations of the run.
Freshness and cost
Price — $0.005 per Actor start (per GB of memory, minimum one event) plus $0.002 per result row. List data is included; there is no per-download or per-query fee.
| Batch | Result rows* | Result cost | Start | About |
|---|---|---|---|---|
| 10 subjects | ~10 | $0.02 | $0.005 | $0.025 |
| 100 subjects | ~100 | $0.20 | $0.005 | $0.205 |
| 500 subjects (one run) | ~500 | $1.00 | $0.005 | $1.005 |
| 1,000 subjects (two runs) | ~1,000 | $2.00 | $0.010 | $2.01 |
* A subject that hits several listed entities returns one row per target, so a match-heavy
list costs a little more; the run summary reports the rows, and the run's usage panel the
exact charge. A 512 MB run is enough for the default dataset; the merged sanctions
dataset wants 1024–2048 MB.
Freshness — list data is held per dataset and re-used across runs of the same Actor,
so a daily or weekly schedule pays the price once per run, not per download.
maxDatasetAgeHours (default 168 = one week) sets how old the held data may be before it
is re-fetched; lower it (for example 24) for daily re-screening against fresher builds.
Every row states the build it was screened against, so an audit file is attributable to an
exact dataset version.
FAQ
How does matching work? Deterministic tiers only: exact primary name, known alias/AKA, or wallet address, after NFKC/casefold/spacing/punctuation normalization. There is no fuzzy similarity scoring — near-misses come back as no-match rather than as low-confidence hits you have to dismiss.
Then what is matchScore for? Ranking and audit. It restates the tier and whether your
birth date and country criteria were confirmed or contradicted on the public record, so a
reviewer can order a queue and see why. It is not a probability and not a risk rating.
Why does a conflicting birth date still return a row? Because a screening tool that
drops name hits on a date mismatch hides sanctioned parties with a wrong or missing date in
the list. The row tells you birthDateMatch: false and lowers the score; the disposition
is yours.
What if the list has no birth date or country? The corresponding match field is null
("not comparable") and the score is unchanged — no evidence is not evidence against.
Why are there two input lists? queries stays the simple list of names and addresses —
existing runs and schedules keep working unchanged — and subjects is the same screening
with birth date/country criteria attached. Both lists are screened in one pass, so a run can
mix them freely.
Can I submit partial birth dates? Yes: 1975, 1975-02 or 1975-02-11. A partial
query date and a fuller list date compare on the shared granularity, so 1979 confirms
against 1979-01-01.
Do countries work for companies? country compares against the record's country and
nationality values (persons) or jurisdiction (organisations). If the list record carries no
country, the field is null rather than false.
Which lists can I screen against? Any of the 470+ OpenSanctions datasets — OFAC SDN by
default, plus EU FSF, UK FCDO, UN Security Council, the US trade consolidated list, or the
full merged sanctions dataset. Browse the catalog for the rest.
Are wallet addresses matched exactly? Hex (0x…) and uniformly-cased bech32 addresses
match case-insensitively; base58 (BTC/TRON) is case-sensitive — screen the exact address
you transact with. Birth date and country do not apply to address queries.
How fresh is the data? Each row carries the list build it was screened against
(datasetsMeta[].generatedAt). A run reuses the held copy while it is younger than
maxDatasetAgeHours and re-fetches when it is older.
What does a no-match mean? No match in the selected datasets at their build time. It is audit evidence that the subject was screened — never clearance, proof of sanction absence, or legal compliance.
Is this legal or compliance advice? No. It is a data tool: the lists are finite, the copy is as fresh as its build, and the method is equality-tiered. Your compliance programme decides what a hit or a no-match means.
Support
For questions or issues, contact Apify Support from the Actor page and include the run URL.