# Sanctions Screening — OFAC SDN & EU List Name Check (KYC/AML) (`yadroo/sanctions-screen`) Actor

Screen names of people, companies and vessels against the US OFAC SDN list and the EU consolidated sanctions list. Fuzzy matching with score, aliases, program, country, listing date. Bulk screening. Built for compliance agents. No API key.

- **URL**: https://apify.com/yadroo/sanctions-screen.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 result items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Screen people, companies, vessels and aircraft against the **US OFAC SDN and Consolidated (non-SDN) lists, the EU Consolidated Financial Sanctions List, the UN Security Council Consolidated List and the UK Sanctions List (FCDO)** in one run. Names are transliterated (Cyrillic → Latin), stripped of legal forms and matched with five explainable similarity methods; every hit tells you *which* listed name matched, *how* and with *what score*. Built for KYC/AML onboarding, counterparty due diligence and agent workflows.

No API key, no proxy, no browser. Lists are downloaded live from the official publishers on every run. Made by Yadroo.

> **A list that cannot be downloaded fails the run.** If a publisher's download is down — the EU file was unreachable for about a day on 1–2 October 2026 — the run stops with that reason and charges no rows, instead of returning "clear" verdicts that never checked that list. Turn on `allowPartial` to screen the other lists instead; every row then says which lists it covers (`complete`, `listsScreened`, `listsFailed`).

### Use cases

- **Customer / supplier onboarding** — batch-screen a list of counterparties, get one row per name with `riskLevel` (`outputMode=summary`) for an analyst queue.
- **Payment pre-check** — screen the beneficiary and the bank (`entities` with `type` and `country`) against OFAC + EU + UN + UK before releasing a wire.
- **Periodic re-screening** — schedule the actor weekly on your client book; compare `hitCount` with the previous run to catch new designations.
- **Russia / Iran exposure review** — restrict to `programs: ["RUSSIA-EO14024", "UKR", "Russia"]` and `countries: ["russia"]` to focus on one regime.
- **Vessel & aircraft checks** — `entityTypes: ["vessel", "aircraft"]` for shipping, chartering and trade-finance desks.
- **Agent tool** — call via MCP from an LLM agent to answer "is X sanctioned, by whom, since when?" with a citable source URL.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `names` | string\[] | — | Names to screen (people, companies, vessels). Cyrillic and diacritics are fine. Max 5,000 names per run in total; see [Limits](#limits--faq) for how many fit in one run. |
| `entities` | object\[] | — | Structured alternative: `{ "name", "type", "country", "ref" }`. `type` narrows to `individual`/`entity`/`vessel`/`aircraft` (also `person`, `company`, `ship`, `plane`); an unknown type stops the run with an error instead of screening against every type. `country` keeps only entries linked to that country; `ref` (your customer id) is echoed back in the output. Can be combined with `names`. |
| `lists` | string\[] | `["ofac", "eu", "un"]` | Any of `ofac_sdn`, `ofac_consolidated`, `eu`, `un`, `uk`. Groups: `ofac` = SDN + Consolidated, `all` = all five. Other spellings: `sdn`, `non-sdn`, `ofsi`/`hmt`/`fcdo` = `uk`. `uk` (the FCDO UK Sanctions List) is the largest download, so add it when you need UK coverage. Letter case does not matter; an unknown name stops the run with the valid ones. |
| `minScore` | text, 0.5–1 | `"0.85"` | Similarity threshold. `1` = exact only (after normalization), `0.95` = typo-tolerant, `0.85` = wide net for manual review. Values outside 0.5–1 are read as the nearest bound and the status says so. Below ~0.8 far more listed names have to be scored, so runs are slower. |
| `entityTypes` | string\[] | — | Keep only these listed types: `individual`, `entity`, `vessel`, `aircraft`, `unknown`. |
| `programs` | string\[] | — | Case-insensitive substring filter on the program / regime code (see Reference). `["RUSSIA"]` matches `RUSSIA-EO14024`, `CAATSA - RUSSIA`, `Russia`… |
| `countries` | string\[] | — | Substring filter on countries linked to the entry (nationality, address, vessel flag). |
| `includeAliases` | boolean | `true` | Match against a.k.a. / f.k.a. names too (recommended — most hits on transliterated names come from aliases). |
| `strictTokenMatch` | boolean | `false` | Disable the token-containment method, so a short query such as "Rosneft" no longer matches "OPEN JOINT-STOCK COMPANY ROSNEFT OIL COMPANY". |
| `allowPartial` | boolean | `false` | Off: a requested list that cannot be downloaded fails the run with the reason, and no rows are charged — a "clear" must never cover a list nobody checked. On: the run screens the lists that loaded; every row has `complete: false` and `listsFailed`, a summary row without a match gets `riskLevel: "incomplete"` instead of `clear`, and the status starts with `INCOMPLETE`. |
| `maxHitsPerName` | integer 1–100 | `10` | Cap on hits per screened name. The best hit of every list that matched is kept first — full-blocking lists (OFAC SDN, UN, EU, UK) before OFAC non-SDN — so a cap never hides an SDN designation behind weaker hits; the remaining places go to the highest scores. Equal scores are ordered OFAC SDN → UN → EU → UK → OFAC consolidated. |
| `outputMode` | `hits` | `summary` | `hits` | `hits`: one row per (name × hit). `summary`: one row per screened name with `riskLevel`, `hitCount` and nested top hits. |
| `includeClear` | boolean | `true` | Emit a row (`matched: false`) for names with no hit so the dataset covers the whole batch. |
| `fields` | string\[] | all | Keep only these output columns, in this order. `query`, `matched` and `complete` are always included. Names depend on `outputMode` (see [Output](#output)); letter case is corrected, an unknown name stops the run with a suggestion. |

`outputMode` and `entityTypes` are fixed lists: Apify refuses any other value before the run starts (no run, no charge).

### Reference

#### Lists

| key | Publisher / list | Entries (Oct 2026) | Status |
|---|---|---|---|
| `ofac_sdn` | US Treasury OFAC — Specially Designated Nationals (SDN.CSV + ALT + ADD) | ~19,500 | downloaded on every run |
| `ofac_consolidated` | OFAC Consolidated non-SDN (SSI, NS-PLC, CMIC, FSE, CAPTA…) | ~480 | downloaded on every run |
| `eu` | EU Consolidated Financial Sanctions List (FSF CSV 1.1) | ~6,200 | downloaded on every run |
| `un` | UN Security Council Consolidated List (XML) | ~1,000 | downloaded on every run |
| `uk` | UK Sanctions List published by the FCDO (XML from sanctionslist.fcdo.gov.uk; the address is read from the gov.uk publication on every run). It replaced OFSI's Consolidated List, which closed on 28 January 2026. | ~6,400 | downloaded on every run |

#### OFAC program codes (most frequent; 73 codes in total)

`RUSSIA-EO14024`, `SDGT`, `IFSR`, `SDNTK`, `NPWMD`, `IRAN-EO13902`, `GLOMAG`, `ILLICIT-DRUGS-EO14059`, `IRAN`, `UKRAINE-EO13662`, `IRAN-EO13846`, `TCO`, `IRGC`, `CYBER2`, `IRAN-HR`, `UKRAINE-EO13661`, `DPRK4`, `BELARUS-EO14038`, `VENEZUELA-EO13850`, `PAARSSR-EO13894`, `VENEZUELA`, `BALKANS`, `DPRK3`, `IRAQ2`, `UKRAINE-EO13660`, `BURMA-EO14014`, `SDNT`, `DPRK2`, `IRAN-EO13876`, `ELECTION-EO13848`, `FTO`, `UKRAINE-EO13685`, `DRCONGO`, `CYBER4`, `CUBA-EO14404`, `CAATSA - RUSSIA`, `NICARAGUA`, `CUBA`, `BELARUS`, `DPRK`, `VENEZUELA-EO13884`, `MAGNIT`, `SUDAN-EO14098`, `LIBYA3`, `IRAN-EO13871`, `IRAN-CON-ARMS-EO`, `IRAN-TRA`, `SOMALIA`, `CAR`, `PEESA-EO14039`, `IFCA`, `SOUTH SUDAN`, `BALKANS-EO14033`, `CAATSA - IRAN`, `HOSTAGES-EO14078`, `LIBYA2`, `ICC-EO14203`, `HRIT-IR`, `LEBANON`, `IRAQ3`, `YEMEN`, `CYBER3`, `RUSSIA-EO14065`, `NICARAGUA-NHRAA`, `DARFUR`, `ETHIOPIA-EO14046`, `MALI-EO13882`, `NS-PLC`, `PAIPA`, `SSIDES`, `DPRK-NKSPEA`, `HRIT-SY`, `UHRPA`. Consolidated-only codes: `CMIC-EO13959`, `HKAA`, `561-Related`. Full descriptions: [OFAC program tag definitions](https://ofac.treasury.gov/specially-designated-nationals-list-sdn-list/program-tag-definitions-for-ofac-sanctions-lists).

#### EU programme codes (34)

`UKR` (Ukraine territorial integrity / Russia), `IRN`, `SYR`, `BLR`, `TAQA` (ISIL/Al-Qaida), `PRK`, `HR` (global human rights), `AFG`, `MMR`, `COD`, `RUSDA` (Russia destabilising activities), `IRQ`, `RUS`, `VEN`, `LBY`, `TERR`, `CHEM`, `MDA`, `TUN`, `CYB`, `SDNZ`, `SOM`, `NIC`, `EUAQ`, `CAF`, `HAM`, `HTI`, `YEM`, `SDN`, `SSD`, `GTM`, `UNLI`, `GIN`, `MLI`. Regime pages: [sanctionsmap.eu](https://www.sanctionsmap.eu/).

#### UK regimes

The UK Sanctions List names each regime by its regulations, e.g. `The Russia (Sanctions) (EU Exit) Regulations 2019`, `The Iran (Sanctions) (Nuclear) (EU Exit) Regulations 2019`, `The Global Human Rights Sanctions Regulations 2020`, `The Cyber (Sanctions) (EU Exit) Regulations 2020`. The `programs` filter is a case-insensitive substring match, so `["Russia"]` keeps these UK entries together with OFAC `RUSSIA-EO14024` and similar; `["Global Human Rights"]`, `["Cyber"]`, `["Iran"]` work the same way. UN list types use committee codes (`Al-Qaida`, `DPRK`, `Iran`, `Libya`, `Taliban`, `DRC`, `Somalia`, `Yemen`, `CAR`, `South Sudan`, `Mali`, `Haiti`, `Sudan`, `Iraq`).

#### Matching methods (`method` field)

| method | meaning | score |
|---|---|---|
| `exact` | identical after normalization (lower-case, transliteration, diacritics and legal forms removed) | 1.0 |
| `token_sort` | same words in a different order ("Putin Vladimir" ↔ "Vladimir Putin") | 0.98 |
| `compact` | same letters, different spacing or hyphens ("Gazprom Bank" ↔ "GAZPROMBANK") | 0.97 |
| `token` | all query words are contained in the listed name ("Rosneft" ⊂ "…ROSNEFT OIL COMPANY"), or all words of the listed name are in the query ("Sberbank of Russia" ⊃ "Сбербанк") — scored by how much of the longer name they cover | 0.75–0.97 |
| `dice` | character-bigram similarity, robust to spelling variants | 0–1 |
| `jaro_winkler` | typo tolerance for short personal names | 0–0.97 |

Normalization removes ~80 legal-form tokens (LLC, LTD, JSC, OOO, AO, GmbH, S.A., PJSC, TOO, LLP…), so "Gazprombank" and "GAZPROMBANK JOINT STOCK COMPANY" are an `exact` match.

Every hit carries **`matchReason`** — a plain-English explanation of the score, e.g. `all query words found in "sberbank russia" (they cover 57% of it)` or `similar spelling "acme" vs "ace" (Jaro-Winkler 0.905); lowered to 0.662: short name (3 letters), length ratio 0.75`.

Speed does not change the result: an index rules out listed names that cannot reach `minScore` (no shared word, too few shared letters or letter pairs) and scores the rest exactly as a full comparison would — the unit tests compare the two on thousands of name pairs at every threshold.

#### Guardrails against false positives

Character metrics are optimistic on short strings, shared prefixes and shared generic words. These rules can only **lower** a score, and each one is named in `matchReason`:

| Rule | Example it stops | Effect |
|---|---|---|
| Short name — fuzzy match where the shorter name has < 5 letters | "Acme Trading LLC" → `acme` vs vessel "ACE" (was 0.905); "Tesla" vs "TESA" | capped at 0.75 |
| Length ratio — shorter/longer (spaces ignored) below 0.85 | "Globex Corporation" vs "GLOBEXBANK" (was 0.892) | score × ratio / 0.85 |
| Weakest word — every distinctive query word needs a close counterpart (Jaro-Winkler bounded by edit distance) | "Kaspi Bank" vs "EKSI BANK", "Yevgeny Prigozhin" vs "Yevgeny Primakov" | capped at that word's similarity |
| Generic words — "bank", "air", "oil", "trading", "electronics", "industries"… (≈100 words) do not make two names similar and cost little when missing | "Air Astana" vs "AIR ALANNA", "Samsung Electronics" vs "Sanam Electronics" | ignored in the word check, weight 0.6 in coverage |
| Numbers must match | vessel "Adrian Darya 2" vs "ADRIAN DARYA 1"; "Grace 1" vs "MARIA GRACE" | capped at 0.8 |
| One word that is only a secondary word of the other name | "Apple Inc" vs "ORIENTAL APPLE COMPANY" | 0.8 |
| One 5–7-letter word contained in a longer name | "Globex" vs "GLOBEX COMMERCIAL BANK" 0.84; "Rosneft" vs "ROSNEFT OIL" 0.93 | 0.75 + 0.22 × coverage (long words such as "Sberbank" keep 0.85 + 0.12 × coverage) |
| Listed name shorter than the query | "Northern Lights Shipping" vs "NORTHERN SHIPPING" | at most 0.9 (low risk) |

Checked against the full OFAC/EU/UN/UK lists: real names and variants still match (Gazprombank / Gazprom Bank / Газпромбанк, Sberbank / Sberbank of Russia / Сбербанк, Rosneft / Роснефть, VTB, Alfa-Bank, Sovcombank / Sovkombank, Promsvyazbank / Promsviazbank, Bank Otkritie / Otkrytie Bank, Putin, Rotenberg, Prigozhin, Kadyrov, vessels ADRIAN DARYA 1, NS CHAMPION, SCF PRIMORYE), while fictional or unrelated names (Acme Trading, Globex, Initech, Tesla, Amazon, Kaspi Bank, Halyk Bank, Air Astana, Maersk, Nestle) come back clear at the default 0.85.

### Examples

**Onboarding batch — one verdict per name**

```json
{ "names": ["Gazprombank", "Acme Trading LLC", "Rosneft", "Maria Ivanova"], "outputMode": "summary", "minScore": "0.9" }
```

**Wire pre-check with typed entities and customer refs, all five lists**

```json
{
  "entities": [
    { "name": "Sberbank", "type": "company", "country": "Russia", "ref": "bene-bank" },
    { "name": "Ivan Petrov", "type": "person", "ref": "bene-1" }
  ],
  "lists": ["all"], "minScore": "0.92", "maxHitsPerName": 5
}
```

**Russia-regime exposure only**

```json
{ "names": ["Alfa-Bank", "Novatek", "Lukoil"], "lists": ["ofac", "eu", "uk"], "programs": ["RUSSIA", "UKR", "CAATSA"], "outputMode": "summary" }
```

**Vessel screening (shipping / trade finance)**

```json
{ "names": ["MAR AZUL", "Pegas", "Sea Dragon"], "entityTypes": ["vessel"], "lists": ["ofac_sdn", "uk", "eu"], "minScore": "0.9" }
```

**Strict mode for automated blocking (few false positives), only the columns you need**

```json
{ "names": ["Apple Inc", "John Smith"], "minScore": "0.97", "strictTokenMatch": true, "fields": ["score", "list", "name", "url"] }
```

**Screen whatever is reachable when a publisher is down (rows say what was covered)**

```json
{ "names": ["Gazprombank"], "lists": ["all"], "allowPartial": true, "outputMode": "summary" }
```

### Output

`outputMode=hits` — one item per (screened name × hit):

```json
{
  "query": "Gazprombank", "queryRef": null, "queryType": null, "queryCountry": null, "queryIndex": 1,
  "matched": true, "score": 1, "method": "exact",
  "matchReason": "identical after normalization (\"gazprombank\")",
  "matchedName": "GAZPROMBANK JOINT STOCK COMPANY", "matchedOn": "name", "commonTokens": ["gazprombank"],
  "list": "ofac_sdn", "listLabel": "OFAC SDN (US Treasury Specially Designated Nationals)",
  "id": "17016", "name": "GAZPROMBANK JOINT STOCK COMPANY", "type": "entity",
  "programs": ["UKRAINE-EO13662", "RUSSIA-EO14024"], "program": "UKRAINE-EO13662; RUSSIA-EO14024",
  "countries": ["Russia", "Mongolia", "Kazakhstan", "India", "China"], "country": "Russia; Mongolia; Kazakhstan; India; China",
  "aliases": ["GAZPROMBANK OPEN JOINT STOCK COMPANY", "BANK GPB JSC", "JOINT STOCK BANK OF THE GAS INDUSTRY GAZPROMBANK"], "listedOn": null,
  "remarks": "SWIFT/BIC GAZPRUMM; Website www.gazprombank.ru; ...",
  "url": "https://sanctionssearch.ofac.treas.gov/Details.aspx?id=17016",
  "listsRequested": ["ofac_sdn", "ofac_consolidated", "eu", "un"], "listsScreened": ["ofac_sdn", "ofac_consolidated", "eu", "un"],
  "listsFailed": [], "complete": true,
  "screenedAt": "2026-10-02T07:57:00.000Z"
}
```

| Field | Description |
|---|---|
| `query`, `queryRef`, `queryType`, `queryCountry` | What you asked for (echoed, including your `ref`). |
| `queryIndex` | 1-based position of the name among the screened names (`names` first, then `entities`); tells repeated names apart. |
| `matched` | `false` on the "clear" row (`includeClear`). |
| `score`, `method`, `matchReason`, `matchedName`, `matchedOn`, `commonTokens` | Match explanation: score 0–1, which method fired, why (including any guardrail that lowered the score), which listed name (primary or alias) matched, shared words. |
| `list`, `listLabel` | Source list key and human label. On clear rows: every list actually screened (`ofac_sdn+ofac_consolidated+eu+un`). |
| `id`, `name`, `type` | Publisher's id (OFAC uid, EU logical id, UN DATAID, UK Sanctions List unique id), primary name, `individual`/`entity`/`vessel`/`aircraft`/`unknown`. |
| `programs` / `program` | Regime codes as array and joined string. |
| `countries` / `country` | Countries linked to the entry (nationality, address, vessel flag). |
| `aliases` | Up to 20 a.k.a. names. |
| `listedOn` | Designation date (ISO) when the list provides it. |
| `remarks` | Publisher's remarks / identifiers, trimmed to 500 chars. |
| `url` | Source page for the entry (OFAC detail page; list home for EU/UN/UK). |
| `listsRequested`, `listsScreened`, `listsFailed`, `complete` | Which lists the verdict covers. `complete` is `true` when every requested list was screened; it is `false` only with `allowPartial` when a list could not be downloaded (`listsFailed` names it). |
| `screenedAt` | ISO timestamp of the screening. |

`outputMode=summary` — one item per name: `query`, `queryRef`, `queryType`, `queryCountry`, `queryIndex`, `matched`, `hitCount`, `hitsOmitted` (further matches above `minScore` left out by `maxHitsPerName`), `topScore`, `riskLevel` (`high` ≥ 0.97 / `medium` ≥ 0.9 / `low` below / `clear` = no match on a complete screen / `incomplete` = no match, but a requested list was not screened), `listsRequested`, `listsScreened`, `listsFailed`, `complete`, `listsHit`, `hits[]` (score, method, matchReason, matchedName, matchedOn, list, id, name, type, programs, countries, listedOn, url), `screenedAt`.

Each run also writes a **`SUMMARY`** record to its key-value store (linked from the run's output): names requested and screened, flagged and clear counts, lists requested / screened / failed (with the reason), entries per list, rows delivered, and why the run stopped if it stopped early. The run's status message says the same in one line.

### Use it from code / agents

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~sanctions-screen/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"names":["Gazprombank","Acme Trading LLC"],"outputMode":"summary"}'
```

`run-sync` endpoints answer only for runs under 300 seconds (about 1,000 names at the default memory); for bigger batches start the run asynchronously (as below) and read the dataset when it finishes.

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/sanctions-screen').call({ names: ['Gazprombank'], lists: ['all'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/sanctions-screen").call(run_input={"names": ["Gazprombank"], "outputMode": "summary"})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

MCP: add `https://mcp.apify.com` to your agent and call the `yadroo/sanctions-screen` tool with the same JSON input.

### Pricing

Pay per event: **$0.001 per run start + $0.003 per dataset item**. In `summary` mode one item = one screened name, so a 100-name batch ≈ $0.301; in `hits` mode heavy hitters produce up to `maxHitsPerName` rows each. List downloads are free. The row price follows your Apify plan (Bronze −10 %, Silver −20 %, Gold and above −30 %); the start event is the same on every plan, and platform usage is included.

Your **maximum cost per run** is respected: the run stops when it would exceed it and says so ("Stopped at your spending limit: N rows delivered"), naming the last screened name and how many of its rows were delivered. A run that fails because a list could not be downloaded charges only the start event.

### Limits & FAQ

- **Freshness** — lists are downloaded from the publishers at run start (no cache); `screenedAt` is on every row.
- **How many names per run** — measured at the default 256 MB: downloading all five lists and indexing their ~93,000 names takes about 10 seconds when Apify's servers are quiet and up to about a minute when they are busy; each name then takes about 0.2 s at the default `minScore` 0.85 (600 names against all five lists: 138 s for the whole run). That is roughly 3,000 names in the default 15-minute run; lower thresholds are slower (below ~0.8 far more listed names have to be scored). More memory means more CPU: give the run 1 GB or more for big batches, or split them. A run that reaches its timeout stops cleanly, keeps every row it saved and says how many names it screened ("Stopped before the run timeout … Screened N of M names").
- **Coverage** — OFAC SDN + Consolidated, EU, UN, UK. Not included: national lists of other countries, PEP databases, adverse media. Use the `url` to verify a hit on the publisher's site before acting.
- **A list that cannot be downloaded** — the run fails with the list and the reason, and charges no rows: a "clear" verdict must never cover a list that was not checked. With `allowPartial` the run screens the other lists instead and every row says which lists it covers (`complete`, `listsScreened`, `listsFailed`).
- **False positives** — guardrails (above) stop short-name, shared-suffix and secondary-word matches, but common personal names ("John Smith") still match at 0.85 — that is what a wide net is for. For automated decisions use `minScore` ≥ 0.95 and `strictTokenMatch`; keep 0.85 for human review and read `matchReason`.
- **What the guardrails cost** — subsidiaries whose name only shares a spelling-similar stem with the query ("Gazprombank" vs "GAZPROM NEFT", "Usama bin Ladin" vs "USAMA BIN LADEN NETWORK") now score below 0.85; lower `minScore` to ~0.8 if you want such related entities in the review queue.
- **Non-Latin input** — Cyrillic (incl. Kazakh/Ukrainian letters) is transliterated; other scripts are matched against the lists' own non-Latin aliases only.
- **Roadmap** — UN/UK per-entry deep links, birth-date and passport matching for individuals, diff mode against the previous run.

***

Made by **Yadroo**. Related actors: [domain-intel](https://apify.com/yadroo/domain-intel), [ip-intel](https://apify.com/yadroo/ip-intel), [wallet-intel](https://apify.com/yadroo/wallet-intel), [sec-edgar-filings](https://apify.com/yadroo/sec-edgar-filings), [github-repo-intel](https://apify.com/yadroo/github-repo-intel).

# Actor input Schema

## `names` (type: `array`):

People, companies, vessels or aircraft to screen — one name per line, any script (Cyrillic is transliterated automatically). Up to 5,000 per run; about 3,000 fit in the default 15-minute run at 256 MB (README → Limits).

## `entities` (type: `array`):

Alternative to `names` (can be combined): objects {name, type?, country?, ref?}. `type` is individual, entity, vessel or aircraft (also person, company, ship, plane) and restricts matches to that kind — an unknown type stops the run with an error; `country` keeps only entries linked to that country (substring); `ref` is echoed back (your customer id).

## `lists` (type: `array`):

Any of: ofac\_sdn, ofac\_consolidated, eu, un, uk. Groups: `ofac` = SDN + consolidated, `all` = all five. Empty = ofac + eu + un. `uk` is the FCDO UK Sanctions List (the largest download, so it is opt-in). If a requested list cannot be downloaded, the run fails with the reason unless allowPartial is on. Unknown names stop the run with the list of valid ones.

## `minScore` (type: `string`):

Similarity threshold from 0.5 to 1, as text (e.g. "0.9"). 1 = exact after normalization; 0.9 = tolerant to word order/legal forms; 0.8 = catches typos and transliteration variants (more false positives). Values outside 0.5–1 are read as the nearest bound and the status says so. Below ~0.8 every listed name has to be scored and runs are much slower.

## `entityTypes` (type: `array`):

Screen only against these entry types. Empty = all.

## `programs` (type: `array`):

Keep only entries under these programs (substring, case-insensitive): OFAC codes like RUSSIA-EO14024, SDGT, IRAN, CYBER2; EU codes like UKR, IRN, BLR; UN list types like Al-Qaida, DPRK; UK regimes like Russia, Cyber. See README reference.

## `countries` (type: `array`):

Keep only entries with an address/nationality/flag in these countries (substring, case-insensitive), e.g. \['Russia', 'Kazakhstan'].

## `includeAliases` (type: `boolean`):

Compare with all known aliases, not only the primary listed name.

## `strictTokenMatch` (type: `boolean`):

By default 'Gazprombank' matches 'GAZPROMBANK JOINT STOCK COMPANY' (all query words contained). Turn on to require whole-name similarity only.

## `allowPartial` (type: `boolean`):

Off (default): if a requested list cannot be downloaded, the run fails with the reason and charges no rows — a "clear" verdict must never cover a list nobody checked. On: screen against the lists that did load; every row then has complete=false and listsFailed, summary rows without a match get riskLevel "incomplete" instead of "clear", and the status starts with INCOMPLETE.

## `maxHitsPerName` (type: `integer`):

Cap on matches returned per screened name. The best match of every list that matched is kept first (OFAC SDN, UN, EU, UK before OFAC non-SDN), so a cap never hides a full-blocking designation; remaining places go to the highest scores.

## `outputMode` (type: `string`):

`summary` is convenient for batch KYC files (one line per customer); `hits` for audit trails.

## `includeClear` (type: `boolean`):

Emit a row for names with no match (matched=false). Turn off to get only alerts.

## `fields` (type: `array`):

Keep only these columns, in this order (empty = all). query, matched and complete are always included. Names depend on outputMode — hits: queryRef, queryType, queryCountry, queryIndex, score, method, matchReason, matchedName, matchedOn, commonTokens, list, listLabel, id, name, type, programs, program, countries, country, aliases, listedOn, remarks, url, listsRequested, listsScreened, listsFailed, screenedAt; summary: queryRef, queryType, queryCountry, queryIndex, hitCount, hitsOmitted, topScore, riskLevel, listsRequested, listsScreened, listsFailed, listsHit, hits, screenedAt. Letter case is corrected; an unknown name stops the run with a suggestion.

## Actor input object example

```json
{
  "names": [
    "Gazprombank",
    "Vladimir Putin",
    "Acme Trading LLC"
  ],
  "entities": [
    {
      "name": "Rosneft",
      "type": "entity",
      "country": "Russia",
      "ref": "customer-1042"
    }
  ],
  "lists": [
    "ofac",
    "eu",
    "un"
  ],
  "minScore": "0.85",
  "includeAliases": true,
  "strictTokenMatch": false,
  "allowPartial": false,
  "maxHitsPerName": 10,
  "outputMode": "hits",
  "includeClear": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "names": [
        "Gazprombank",
        "Vladimir Putin",
        "Acme Trading LLC"
    ],
    "entities": [
        {
            "name": "Rosneft",
            "type": "entity",
            "country": "Russia",
            "ref": "customer-1042"
        }
    ],
    "lists": [
        "ofac",
        "eu",
        "un"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/sanctions-screen").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "names": [
        "Gazprombank",
        "Vladimir Putin",
        "Acme Trading LLC",
    ],
    "entities": [{
            "name": "Rosneft",
            "type": "entity",
            "country": "Russia",
            "ref": "customer-1042",
        }],
    "lists": [
        "ofac",
        "eu",
        "un",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/sanctions-screen").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "names": [
    "Gazprombank",
    "Vladimir Putin",
    "Acme Trading LLC"
  ],
  "entities": [
    {
      "name": "Rosneft",
      "type": "entity",
      "country": "Russia",
      "ref": "customer-1042"
    }
  ],
  "lists": [
    "ofac",
    "eu",
    "un"
  ]
}' |
apify call yadroo/sanctions-screen --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yadroo/sanctions-screen"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DQwDdMFd7fpFUtRog/builds/U6ttwuVdjWiRHDRQk/openapi.json
