# Sanctions Screening: OFAC, EU and UN Lists in One Pass (`gubidonius/sanctions-screening`) Actor

Screen names against the OFAC SDN, OFAC consolidated, EU and UN sanctions lists. Every row says which name matched, whether the publisher calls that alias weak, and which lists were actually searched. No key and no login.

- **URL**: https://apify.com/gubidonius/sanctions-screening.md
- **Developed by:** [Gregory Bolshakov](https://apify.com/gubidonius) (community)
- **Categories:** Business, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Sanctions Screening

Screen names against the OFAC SDN list, the OFAC consolidated list, the EU list and the UN
list in one pass. Every row says which name matched, what the publisher thinks of that
name, and which lists the answer is actually based on.

### A list that did not download is not a clean answer

This is the rule the Actor is built around. The EU file is 26 MB and took 46 seconds on a
good connection, so a run can lose it. When that happens the run does not quietly report
no match. Every row carries `listsSearched`, `listsUnavailable` and `screeningComplete`,
and a clean row with `screeningComplete` false means only that nothing was found on the
lists that answered.

### Weak aliases

OFAC marks each alias strong or weak, and the list published on 28 August 2026 carries
4,395 weak aliases out of 24,542. Weak is the publisher saying it expects false positives
on that name. The UN does the same thing with Good and Low.

Those matches are returned, because a missed designation is worse than one you have to
read. They are never presented as equal to a hit on the designated name: `matchedOn` says
primary or alias, `aliasQuality` says what the publisher called it, and `weakAliasMatch`
is a column you can filter on.

Not every publisher uses the field. The EU sets strong on all 31,053 of its aliases, so it
draws no distinction at all, and EU rows report no quality rather than a strong that would
look like OFAC's. The UN field also holds a.k.a. and f.k.a., which say nothing about
quality, so those are left unknown with the original word kept.

### The four lists designate different people

Screening only OFAC is not a screen for an EU obligation and the reverse is also true.
That is why all four are on by default. Each row names the list it came from and the
publication date printed on that file, so an answer can be audited months later.

### How a name is matched

Word order is ignored, because the lists write `AL-ZOMOR, Abboud Abdul Latif Hassan` and
people type `Abboud Al-Zomor`. Accents and punctuation are stripped on both sides.

```
100   the same name after normalising
90    every word you typed appears in the name
85    a one word query found as a whole word in the name
```

Below 85 you are looking at people who share a surname, which is why 85 is the default.
`whyItMatched` gives the reason in words on every row.

### What this is not

It is a search of published lists, not a compliance decision. It returns candidates with
the evidence attached so a person can decide. It does not tell you whether a company is
owned by somebody on a list, which is a separate question that no name search answers.

### Access

Free, no key, no login. All four lists are whole-file downloads rather than search APIs,
so the Actor reads 20,000 records to answer a name and parses only the records that share
a word with it. Screening two names against OFAC and the UN read 20,332 records in 225
milliseconds.

# Actor input Schema

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

People or companies. Word order does not matter, so Abboud Al-Zomor and AL-ZOMOR, Abboud both work. A one word name is a broad search and will return everything carrying that word.

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

Leave all four on unless you have a reason. The four authorities designate different people, so screening only OFAC is not a screen for an EU obligation.

## `minScore` (type: `integer`):

100 is an exact match after normalising. 90 means every word you typed appears in the name. 85 is a one word query found as a whole word. Below 85 you are looking at people who share a surname.

## `entryTypes` (type: `array`):

The lists hold ships and aircraft as well as people and companies. Leave empty for all of them.

## `maxMatchesPerName` (type: `integer`):

Highest scoring first. A common one word company name can match dozens of entries.

## Actor input object example

```json
{
  "names": [
    "Vladimir Putin",
    "Gazprom"
  ],
  "lists": [
    "ofac-sdn",
    "un-consolidated"
  ],
  "minScore": 85,
  "maxMatchesPerName": 25
}
```

# Actor output Schema

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

Matches and clean names, with the score and the reason for each.

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

Lists searched, lists missed, publication dates and records read.

# 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": [
        "Vladimir Putin",
        "Gazprom"
    ],
    "lists": [
        "ofac-sdn",
        "un-consolidated"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gubidonius/sanctions-screening").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": [
        "Vladimir Putin",
        "Gazprom",
    ],
    "lists": [
        "ofac-sdn",
        "un-consolidated",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("gubidonius/sanctions-screening").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": [
    "Vladimir Putin",
    "Gazprom"
  ],
  "lists": [
    "ofac-sdn",
    "un-consolidated"
  ]
}' |
apify call gubidonius/sanctions-screening --silent --output-dataset

```

## MCP server setup

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

```

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/w7idanLuicAVKc4ok/builds/a8MvUIcwGJP38t3xq/openapi.json
