# Sanctions List New-Addition Delta Monitor (OFAC/EU/UN/UK) (`gp005/sanctions-delta-monitor`) Actor

Continuously tracks OFAC SDN, EU Consolidated, UN Security Council and UK FCDO sanctions lists and alerts on NEW additions since the last check. Official government/EC/UN sources only; no scraping, no API key needed.

- **URL**: https://apify.com/gp005/sanctions-delta-monitor.md
- **Developed by:** [Geo](https://apify.com/gp005) (community)
- **Categories:** Developer tools, Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 sanctions list checkeds

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?

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

## Sanctions List New-Addition Delta Monitor (OFAC, EU, UN, UK)

**A sanctions watchlist change monitor.** Schedule it daily or weekly and it tells you **who was newly added** to the OFAC SDN list, the EU Consolidated Sanctions List, the UN Security Council Consolidated List and the UK FCDO Sanctions List since the previous run. Each new designation arrives as one structured JSON record. Data comes only from the official government/EC/UN XML files: no scraping, no login, no API key.

### What is the Sanctions Delta Monitor?

Most sanctions tools answer "is *this* name on a list right now?". This actor answers a different question: **"what changed since I last looked?"**

On every run it downloads the current XML of each list you select, compares the entity IDs with the snapshot saved by the previous run, and emits one dataset record per newly added entity. The snapshot lives in a named Apify key-value store (`sanctions-delta-state`) that is shared across all runs of your copy of the actor, so state survives between scheduled runs.

It is built for **continuous, unattended compliance monitoring**. If you instead need to screen a specific company name against the lists on demand, use our [Sanctions Screening API — GLEIF LEI & OFAC/EU/UN/UK Checker](https://apify.com/gp005/gleif-sanctions-screener). The two are complementary: screen a counterparty once with the screener, then watch for new designations with this monitor.

### What data does it return?

| Field | Description |
|---|---|
| `source` | `OFAC`, `EU`, `UN` or `UK` |
| `changeType` | `NEW_ADDITION`, `REMOVED`, `BASELINE_SNAPSHOT` or `ERROR` |
| `entityId` | The list's own stable identifier (OFAC `uid`, EU `logicalId`, UN `DATAID`/`REFERENCE_NUMBER`, UK `UniqueID`) |
| `name` | Primary name |
| `entityType` | `individual`, `entity`, `vessel` or `other` |
| `programs` | Sanctions programs / regimes listed for the entity |
| `aliases` | Alternative names (up to 25) |
| `listedDate` | Listing date where the source provides one (EU, UN, UK; not OFAC's SDN file) |
| `detectedAt` | ISO timestamp of the run that detected the change |
| `sourceUrl` | The official file the record came from |
| `entityCount`, `message` | On `BASELINE_SNAPSHOT` rows: size of the stored snapshot |
| `errorCode`, `errorMessage` | On `ERROR` rows |

Identity is always the list's own ID, never the name, so formatting changes in a name do not produce false alerts.

### How to monitor sanctions list changes

1. Open the actor and choose the lists to monitor (the default is OFAC only).
2. Run it once. **The first run only captures a baseline** for each list (see below), so nothing is flagged as new.
3. Create an **Apify schedule** for the actor (daily or weekly, for example `0 7 * * *`). This is the intended usage pattern: every later run reports only what is new since the previous one.
4. Add a webhook or integration (Slack, email, Make, n8n, your own API) on run success to forward `NEW_ADDITION` records to your compliance team.

#### First run = baseline, not a flood of alerts

The very first run for a list has nothing to compare with. Instead of flagging thousands of existing entries as "new", the actor stores the snapshot and pushes **one** `BASELINE_SNAPSHOT` record per list. No `new-addition-alert` is charged for a baseline. Monitoring starts from that moment.

#### Input

```json
{
  "lists": ["OFAC", "UN"],
  "detectRemovals": false,
  "maxTotalChargeUsd": 1
}
```

| Field | Type | Description |
|---|---|---|
| `lists` | array (required) | Any of `OFAC`, `EU`, `UN`, `UK`. Default prefill: `["OFAC"]`. |
| `detectRemovals` | boolean | Also report de-listings as `REMOVED` records. Default `false`. |
| `maxTotalChargeUsd` | number | Per-run spend cap. Once the next charge would exceed it, the actor stops charging and exits cleanly. |

#### Output example: new addition

The values below show the record shape, not a real designation:

```json
{
  "source": "UN",
  "changeType": "NEW_ADDITION",
  "entityId": "6908123",
  "name": "EXAMPLE ENTITY NAME",
  "entityType": "entity",
  "programs": ["Al-Qaida"],
  "aliases": ["EXAMPLE ALIAS"],
  "listedDate": "2026-11-03",
  "detectedAt": "2026-11-05T07:00:12.431Z",
  "sourceUrl": "https://scsanctions.un.org/resources/xml/en/consolidated.xml"
}
```

#### Output example: baseline snapshot

```json
{
  "source": "OFAC",
  "changeType": "BASELINE_SNAPSHOT",
  "entityCount": 17000,
  "message": "Baseline snapshot captured, 17000 entities, monitoring starts now.",
  "detectedAt": "2026-11-05T07:00:12.431Z",
  "sourceUrl": "https://sanctionslistservice.ofac.treas.gov/api/PublicationPreview/exports/SDN.XML"
}
```

(`entityCount` above is illustrative; the real record carries the actual count.)

### Pricing

Pay-per-event. You pay for the monitoring work, and a little more only when something actually changes.

| Event | Price | When charged |
|---|---|---|
| `actor-start` | $0.01 | Once per run in which at least one list was checked |
| `list-checked` | $0.01 | Once per list fetched, parsed and compared (**primary event**; includes the baseline run) |
| `new-addition-alert` | $0.03 | Once per newly added entity (never on a baseline run) |
| `delisting-alert` | $0.02 | Once per removed entity, only if `detectRemovals` is on |

**Typical run, all 4 lists, nothing new** (the common case; these lists rarely change day to day): $0.01 + 4 × $0.01 = **$0.05**.
**Run that finds 3 new additions:** $0.05 + 3 × $0.03 = **$0.14**.
**Daily OFAC-only monitoring:** $0.02 per quiet day, roughly $0.60 per month.

For comparison, a compliance analyst manually re-checking four government sites each day spends minutes per site per day and can easily miss an update; the free government feeds give you the full file, not a diff. Treat the per-run cost above as the price of the diff, delivered on a schedule.

Set `maxTotalChargeUsd` to cap spend per run. When the cap (or the platform's own charge limit) is reached, the actor stops gracefully and does not advance the stored snapshot for the affected list, so unreported changes are picked up by the next run.

### Limitations

- **Baseline first.** The first run per list only stores a snapshot. You will not see existing designations as additions.
- **State is per Apify account.** The snapshot is kept in the named store `sanctions-delta-state`. Deleting that store resets monitoring to a new baseline. Each list is tracked independently, so adding a list later baselines just that list.
- **EU file is large** (about 25 MB). Fetch and parse take noticeably longer and need more memory than the other lists; the actor allows up to 120 seconds for the download. Start with OFAC if you want a quick first test.
- **UK source.** The UK list is read from the current FCDO Sanctions List (`sanctionslist.fcdo.gov.uk`). The old OFSI Consolidated List closed in January 2026 and is not used. The actor keys UK designations on `UniqueID` (falling back to a name+regime hash with a warning if a record has no ID), based on the XML layout the parser expects. If the FCDO changes its XML layout, the UK source will report an `ERROR` row until the parser is updated.
- **OFAC scope.** Only the SDN list is monitored. The non-SDN consolidated list (CONS_PRIM) is not included in this version.
- **Removals are opt-in.** With `detectRemovals` on, de-listings are reported as `REMOVED` records with ID and name only. New additions are detected by ID only, so a change to an existing entry (new alias, new program) is *not* reported.
- **Safety checks.** If a download parses to zero entities, or to fewer than half of the stored snapshot, it is treated as a bad download: an `ERROR` row is pushed and the stored snapshot is left untouched.
- **Failures are isolated.** If one list fails after up to 3 attempts, you get an `ERROR` row for it and the other lists still run and are billed normally. If every selected list fails, or the input is invalid (empty `lists`, unknown code), the run pushes an `ERROR` row and ends as failed. It is never a silent empty success.
- Each list is fetched at most 3 times per run, with a descriptive `User-Agent`.

### FAQ

#### Is this a replacement for a KYC/AML screening vendor?

No. It is a compliance-screening aid that surfaces new entries on four public lists. It does not cover other lists (for example, national lists not named here), does not do fuzzy name matching against your customers, and is not legal advice. Keep a licensed KYC/AML provider for regulated decisions and verify every hit against the official source before acting.

#### Is it legal to use these lists?

The actor reads only the official publications of the US Treasury (OFAC), the European Commission, the UN Security Council and the UK FCDO, at their published public file URLs. It is not affiliated with or endorsed by any of these bodies.

#### How is this different from the GLEIF sanctions screener?

The [screener](https://apify.com/gp005/gleif-sanctions-screener) checks names you supply against the lists, on demand. This monitor needs no names: it watches the lists themselves and reports additions over time.

#### Can I run it without a schedule?

Yes, but it only reports changes since your *previous* run, so it is most useful on a daily or weekly schedule.

#### Support

Questions, bugs or ideas? Open an issue on the actor's Issues tab. Feedback and custom solutions are welcome.

# Actor input Schema

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

Which official sanctions lists to check for new additions: OFAC (US SDN), EU (Consolidated), UN (Security Council), UK (FCDO). The EU file is large (~25 MB) and slower to fetch.

## `detectRemovals` (type: `boolean`):

Also detect and report de-listings (entities removed since last check). Each removal is billed as a delisting-alert event.

## `maxTotalChargeUsd` (type: `number`):

Per-run spend cap in USD. Once the next charge would exceed it, the actor stops charging and exits gracefully; unreported changes are picked up on the next run. Leave empty for no cap.

## Actor input object example

```json
{
  "lists": [
    "OFAC",
    "UN"
  ],
  "detectRemovals": false,
  "maxTotalChargeUsd": 1
}
```

# Actor output Schema

## `dataset` (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 = {
    "lists": [
        "OFAC"
    ],
    "maxTotalChargeUsd": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("gp005/sanctions-delta-monitor").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 = {
    "lists": ["OFAC"],
    "maxTotalChargeUsd": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("gp005/sanctions-delta-monitor").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 '{
  "lists": [
    "OFAC"
  ],
  "maxTotalChargeUsd": 1
}' |
apify call gp005/sanctions-delta-monitor --silent --output-dataset

```

## MCP server setup

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

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/gpnW9cJCDNQim1VL9/builds/WUfHxE694xC4kM8wf/openapi.json
