Sanctions & AML Screener: OFAC, EU, UK, UN & Crypto Wallets avatar

Sanctions & AML Screener: OFAC, EU, UK, UN & Crypto Wallets

Pricing

from $2.00 / 1,000 results

Go to Apify Store
Sanctions & AML Screener: OFAC, EU, UK, UN & Crypto Wallets

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

Philip Kirkbride

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 hours ago

Last modified

Categories

Features

Limited permissions

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 (exact primary name, alias AKA, address wallet), a matchScore with its matchReasons, 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 / countryMatch and 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[].generatedAt is 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 add birthDate, country and your own reference (id, echoed back as queryId).
{
"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

NameTypeDefaultWhat it does
queriesarrayexample sampleUp to 500 plain names and/or crypto addresses.
subjectsarrayexample sampleUp to 500 objects {name, birthDate, country, id} — the same subjects with criteria.
datasetsarray["us_ofac_sdn"]Up to 8 datasets to screen against — see Datasets covered.
maxDatasetAgeHoursinteger168Reuse the locally held list data while it is younger than this; re-fetch when older.
includeAliasesbooleantrueAlso match known aliases / AKAs (tier alias). Off = primary names only.

subjects object fields:

FieldRequiredExampleNotes
nameyes"Ivan Ivanov"Entity name (case-insensitive) or crypto address.
birthDateno"1975-02-11"YYYY, YYYY-MM or YYYY-MM-DD; compared on the shared granularity (a year-only list entry compares years).
countryno"ru"ISO 3166-1 alpha-2 code, case-insensitive — the subject's nationality or the company's jurisdiction.
idno"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:

TierMeaningScore base
exactThe query equals the listed primary name (after case, spacing and punctuation normalization).0.95
aliasThe query equals a known alias / AKA of a listed target.0.85
addressThe query equals a sanctioned wallet address (publicKey).1.00

The score then moves with the criteria you submitted, against the public list record:

CriterionConfirmedConflicting
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:

  • matchScore is 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. null means "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.

DatasetWhat it coversTargetsEntitiesBulk size
us_ofac_sdn (default)US Treasury OFAC Specially Designated Nationals, including sanctioned wallets~20,200~72,000~53 MB
us_trade_cslUS consolidated screening list (State, Commerce/BIS, Treasury, DHS)~24,100~30,500~25 MB
eu_fsfEU Financial Sanctions Files (all member states)~6,100~15,900~17 MB
gb_fcdo_sanctionsUK FCDO (OFSI) sanctions list~6,300~18,500~22 MB
un_sc_sanctionsUN Security Council consolidated list~1,000~2,900~3 MB
sanctionsAll 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.

FieldWhat it holds
recordKeyStable row key: os:{query}:{entityId}, or os:{query}:nomatch.
query, queryId, queryTypeThe subject as submitted, your reference, and name/address.
queryBirthDate, queryCountryThe criteria you submitted for that subject (or null).
match, confidence, matchScore, matchReasonsResult, tier, score and the reasons behind the score.
matchedName, captionThe list label that matched and the OpenSanctions caption.
targetTypePerson, LegalEntity, Company, Organization, Vessel, CryptoWallet, Airplane, …
listsEvery selected dataset the target matched in.
countries, nationalities, birthDatesWhat the public list record carries (union across matched lists).
birthDateMatch, countryMatchtrue / false / null (not comparable) for the criteria you submitted.
topics, programs, authoritiesSanction topics, programs (e.g. GLOMAG, RUSSIA-EO14024) and issuing authorities.
sanctionsPer-list designations: program, authority, country, reason, source URL, authority id, dataset.
sourceUrl, entityUrlThe official source link and the OpenSanctions profile page.
publicKey, currency, holderNameWallet address, currency and the sanctioned holder, for address matches.
datasetsMeta, screenedAtProvenance: 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.

BatchResult rows*Result costStartAbout
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.