# Sanctions Change Tracker (`taroyamada/sanctions-change-digest`) Actor

Automate OFAC compliance checks by extracting daily additions and removals from the SDN list. Generate precise JSON diffs for counterparty screening.

- **URL**: https://apify.com/taroyamada/sanctions-change-digest.md
- **Developed by:** [naoki anzai](https://apify.com/taroyamada) (community)
- **Categories:** Business, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 results

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/platform/actors/running/actors-in-store#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

## OFAC Sanctions List Change Watch Scraper

Use this actor to monitor public OFAC sanctions list changes and configured watch-term matches for internal review workflows.
Input OFAC program/type filters or watch terms, then receive source-linked JSON digest rows for additions, removals, and matches.
This actor is informational only and is not an OFAC clearance, customer-due-diligence, legal determination, or certification product.

### Store Quickstart

- Start with `store-input.example.json` for a two-watch (SDGT entities + Cuba programs) dataset run.
- If that matches your workflow, switch to `store-input.templates.json` and pick one of:
  - `SDGT Quickstart (2-program starter)` for first-run validation
  - `Named Entity Watch` for counterparty name-screening against the SDN list
  - `Russia & Iran Program Digest` for geo-targeted sanctions tracking
  - `Individuals-Only Watch` for people-focused screening
  - `Webhook Upgrade` for compliance automation with action-needed handoff

### Key Features

- 📋 **Summary-first output** — 1 watch = 1 digest row; raw SDN entries nested under `entries`
- 🔄 **Change detection** — snapshot-backed diff flags new additions and list removals between runs
- 🔍 **Watch-term matching** — watch-term matching across SDN entry names and all aliases (case-insensitive)
- 🗂️ **Program & type filtering** — scope any watch to OFAC program codes or entity types
- 🪝 **Webhook delivery** — route action-needed digests to Slack, compliance tools, or any HTTP endpoint
- ✅ **No auth required** — OFAC publishes the SDN XML as a public feed

### Use Cases

| Who | Why |
|-----|-----|
| Compliance teams | Daily/weekly digest of SDN additions for public list-change review |
| Compliance operations | Watch-term alerting for public OFAC list changes |
| Risk systems | Track geo-targeted programs (Russia, Iran, Cuba) for jurisdictional exposure |
| Procurement & finance | Review whether watched vendor or supplier names appear in public OFAC list changes |

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| watches | array | — | One entry per watch target. Each watch produces one summary digest row. Set programs and/or sdnTypes to narrow the scope |
| sdnXmlUrl | string | `"https://www.treasury.gov/ofac/downloads/sdn.xml"` | Override the OFAC SDN XML feed URL. The default legacy URL (https://www.treasury.gov/ofac/downloads/sdn.xml) redirects t |
| maxEntriesPerWatch | integer | `50` | Default upper bound on SDN entries in the nested output per watch. Can be overridden per-watch with the maxEntries field |
| requestTimeoutSeconds | integer | `60` | Timeout for the SDN XML fetch. The file is several MB so allow at least 60 seconds. |
| delivery | string | `"dataset"` | dataset stores results in the Apify dataset. webhook posts the digest JSON to webhookUrl. |
| webhookUrl | string | — | POST target for the digest payload. Leave empty for dataset delivery. |
| datasetMode | string | `"all"` | all emits every watch digest row. action\_needed emits only watches with name-match hits. new\_only emits only watches wit |
| snapshotKey | string | `"sanctions-change-digest-state"` | Stable key used to persist seen SDN entry UIDs across recurring runs so new\_only and action\_needed modes stay comparable |

#### Input Example

```json
{
  "watches": [
    {
      "id": "sdgt-entities",
      "name": "SDGT Entities",
      "programs": "SDGT",
      "sdnTypes": "Entity",
      "maxEntries": 20
    },
    {
      "id": "name-screen",
      "name": "Counterparty Screen",
      "watchTerms": "Acme Corp,Example Bank",
      "maxEntries": 10
    }
  ],
  "delivery": "dataset",
  "datasetMode": "all",
  "snapshotKey": "sanctions-change-digest-state"
}
```

### Input Examples

#### Example: Single-target audit

```json
{
  "targets": [
    "example-target-1"
  ],
  "maxResultsPerTarget": 30
}
```

#### Example: Bulk portfolio

```json
{
  "targets": [
    "target-1",
    "target-2",
    "target-3"
  ],
  "maxResultsPerTarget": 50,
  "snapshotKey": "sanctions-change-digest-state"
}
```

#### Example: Recurring delta watch

```json
{
  "targets": [
    "target-1"
  ],
  "snapshotKey": "sanctions-change-digest-state",
  "emitChangedOnly": true
}
```

### Output

| Field | Type | Description |
|-------|------|-------------|
| `meta` | object |  |
| `errors` | array |  |
| `digests` | array |  |
| `digests[].watchId` | string |  |
| `digests[].watchName` | string |  |
| `digests[].programs` | array |  |
| `digests[].sdnTypes` | array |  |
| `digests[].watchTerms` | array |  |
| `digests[].checkedAt` | timestamp |  |
| `digests[].status` | string |  |
| `digests[].newEntryCount` | number |  |
| `digests[].removedEntryCount` | number |  |
| `digests[].totalMatchCount` | number |  |
| `digests[].changedSinceLastRun` | boolean |  |
| `digests[].actionNeeded` | boolean |  |
| `digests[].recommendedAction` | string |  |
| `digests[].signalTags` | array |  |
| `digests[].watchTermHits` | array |  |
| `digests[].typeBreakdown` | object |  |
| `digests[].programBreakdown` | object |  |
| `digests[].removedUids` | array |  |
| `digests[].entries` | array |  |
| `digests[].error` | null |  |

#### Output Example

```json
{
  "meta": {
    "generatedAt": "2026-04-03T12:00:00.000Z",
    "sdnPublishDate": "04/03/2026",
    "sdnRecordCount": 18698,
    "newEntries": 3,
    "actionNeededCount": 0,
    "executiveSummary": {
      "overallStatus": "watch",
      "brief": "3 new SDN addition(s) and 0 removal(s) detected across 2 watch(es)."
    }
  },
  "digests": [
    {
      "watchId": "sdgt-entities",
      "status": "watch",
      "newEntryCount": 3,
      "removedEntryCount": 0,
      "totalMatchCount": 1847,
      "entries": [...]
    }
  ]
}
```

### API Usage

Run this actor programmatically using the Apify API. Replace `YOUR_API_TOKEN` with your token from [Apify Console → Settings → Integrations](https://console.apify.com/account/integrations).

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/taroyamada~sanctions-change-digest/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "watches": [ { "id": "sdgt-entities", "name": "SDGT Entities", "programs": "SDGT", "sdnTypes": "Entity", "maxEntries": 20 }, { "id": "name-screen", "name": "Counterparty Screen", "watchTerms": "Acme Corp,Example Bank", "maxEntries": 10 } ], "delivery": "dataset", "datasetMode": "all", "snapshotKey": "sanctions-change-digest-state" }'
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("taroyamada/sanctions-change-digest").call(run_input={
  "watches": [
    {
      "id": "sdgt-entities",
      "name": "SDGT Entities",
      "programs": "SDGT",
      "sdnTypes": "Entity",
      "maxEntries": 20
    },
    {
      "id": "name-screen",
      "name": "Counterparty Screen",
      "watchTerms": "Acme Corp,Example Bank",
      "maxEntries": 10
    }
  ],
  "delivery": "dataset",
  "datasetMode": "all",
  "snapshotKey": "sanctions-change-digest-state"
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### JavaScript / Node.js

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('taroyamada/sanctions-change-digest').call({
  "watches": [
    {
      "id": "sdgt-entities",
      "name": "SDGT Entities",
      "programs": "SDGT",
      "sdnTypes": "Entity",
      "maxEntries": 20
    },
    {
      "id": "name-screen",
      "name": "Counterparty Screen",
      "watchTerms": "Acme Corp,Example Bank",
      "maxEntries": 10
    }
  ],
  "delivery": "dataset",
  "datasetMode": "all",
  "snapshotKey": "sanctions-change-digest-state"
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Tips & Limitations

- Run daily for active watchlists; weekly for passive monitoring.
- Webhook delivery works well for compliance team Slack channels — include docket URL for 1-click access.
- Use `watchKeywords` generously — false positives are cheap to triage, false negatives miss filings.
- Pair with `regulatory-change-monitor` for cross-agency coverage.
- Archive Dataset rows weekly for long-term compliance evidence retention.

### FAQ

**How far back does history go?**

This actor monitors forward-only — new items since first run. For historical data, use the agency's own search tool.

**What timezones are used?**

All timestamps are UTC. Use your downstream pipeline to convert to agency-local time if needed.

**Does it translate non-English content?**

No — original language is preserved. Use downstream translation services if needed.

**Is the data official?**

Yes — sourced directly from official government websites and feeds. Not a third-party aggregator.

**Can I use this for legal research?**

For alerting and monitoring, yes. For litigation research, cross-verify with primary sources (agency websites) — this actor is a monitoring tool, not a legal database.

### Related Actors

Government & Regulatory cluster — explore related Apify tools:

- [EPA Enforcement Digest | ECHO Compliance Risk Monitor](https://apify.com/taroyamada/epa-enforcement-digest) — Monitor EPA ECHO all-media facility search, corporate compliance screener, and enforcement case feeds with one summary-first digest row per watched company, facility, or case feed.
- [FDA Warning Letters Digest | Summary-First Feed](https://apify.com/taroyamada/fda-warning-letter-digest) — Monitor public FDA warning letters with one summary-first digest row per configured feed.
- [Federal Register Digest | Agency Rule & Notice Monitor](https://apify.com/taroyamada/federal-register-digest) — Monitor Federal Register documents — rules, proposed rules, and notices — per configured agency feed.
- [Government Contract Award Monitor | Award & Competitor Watch](https://apify.com/taroyamada/government-contract-award-monitor) — Monitor public-sector contract award notices for new wins, notable awardees, incumbent recompetes, and competitor signals — one digest row per configured feed without brittle broad crawling.
- [Grants.gov Funding Digest | Opportunity Watch & Signal Digest](https://apify.com/taroyamada/grants-gov-funding-digest) — Monitor Grants.
- [NHTSA Vehicle Recall Digest | Recalls + Complaints Watch](https://apify.com/taroyamada/nhtsa-vehicle-recall-digest) — Monitor official NHTSA vehicle recall and complaint endpoints for watched model-family, VIN, and manufacturer feeds.
- [Product Safety Recall Digest | CPSC + openFDA Alerts](https://apify.com/taroyamada/product-safety-recall-digest) — Monitor CPSC saferproducts.
- [Regulatory Change Monitor API](https://apify.com/taroyamada/regulatory-change-monitor) — Monitor official regulator update feeds, government bulletin pages, and public compliance notices with one action-oriented digest row per monitored source.
- [Tariff Trade Change Digest | Federal Register + HTS Monitor](https://apify.com/taroyamada/tariff-trade-change-digest) — Monitor U.
- [Treasury Fiscal Data Digest | Debt, Rates & Budget Monitor](https://apify.com/taroyamada/treasury-fiscal-data-digest) — Monitor the U.
- [USPTO Patent Monitor API | JSON + Webhook](https://apify.com/taroyamada/uspto-patent-scraper) — Search and monitor US patent filings with multi-source fallback.
- [Campaign Finance & Lobbying Digest | FEC + LDA Watch](https://apify.com/taroyamada/campaign-finance-lobbying-digest) — Monitor official FEC OpenFEC committee reports and LDA.

### Cost

**Pay Per Event**:

- `actor-start`: $0.01 (flat fee per run)
- `dataset-item`: $0.003 per output item

**Example**: 1,000 items = $0.01 + (1,000 × $0.003) = **$3.01**

No subscription required — you only pay for what you use.

### ⭐ Was this helpful?

If this actor saved you time, please [**leave a ★ rating**](https://apify.com/taroyamada/sanctions-change-digest/reviews) on Apify Store. It takes 10 seconds, helps other developers discover it, and keeps updates free.

Bug report or feature request? Open an issue on the [Issues tab](https://apify.com/taroyamada/sanctions-change-digest/issues) of this actor.

### Compliance Guardrails

This actor is independently operated and has no source-agency affiliation, sponsorship, or approval. It uses public data from OFAC Sanctions List Service and public OFAC sanctions list downloads (https://ofac.treasury.gov/sanctions-list-service). Results are informational only and may be delayed, incomplete, amended, withdrawn, or superseded by the source. Verify all records with the linked official source before relying on them.

- Use only public OFAC list/download/search surfaces.
- Do not market as an OFAC clearance, customer-due-diligence, legal determination, or certification product.
- Output source URLs, retrieval timestamps, list names, and watch-term match context; users must verify records with OFAC.

# Actor input Schema

## `watches` (type: `array`):

One entry per watch target. Each watch produces one summary digest row. Set programs and/or sdnTypes to narrow the scope; add watchTerms for name-match alerting. If omitted, a single all-programs default watch is used.

## `sdnXmlUrl` (type: `string`):

Override the OFAC SDN XML feed URL. The default legacy URL (https://www.treasury.gov/ofac/downloads/sdn.xml) redirects to the current sanctions list service endpoint. Change only if the URL moves.

## `maxEntriesPerWatch` (type: `integer`):

Default upper bound on SDN entries in the nested output per watch. Can be overridden per-watch with the maxEntries field.

## `requestTimeoutSeconds` (type: `integer`):

Timeout for the SDN XML fetch. The file is several MB so allow at least 60 seconds.

## `delivery` (type: `string`):

dataset stores results in the Apify dataset. webhook posts the digest JSON to webhookUrl.

## `webhookUrl` (type: `string`):

POST target for the digest payload. Leave empty for dataset delivery.

## `datasetMode` (type: `string`):

all emits every watch digest row. action\_needed emits only watches with name-match hits. new\_only emits only watches with entries not seen in the previous run.

## `snapshotKey` (type: `string`):

Stable key used to persist seen SDN entry UIDs across recurring runs so new\_only and action\_needed modes stay comparable. Use the same key across scheduled runs.

## `notifyOnNoNew` (type: `boolean`):

When true, every watch always produces a digest row even if no new entries were found. When false, watches with no new entries are omitted from the output.

## `dryRun` (type: `boolean`):

Fetch and process without persisting state or posting webhooks. Safe for testing input shapes.

## `nowIso` (type: `string`):

Set to a fixed ISO timestamp to make runs deterministic against fixture data.

## `fixturePath` (type: `string`):

Local XML or JSON fixture for offline tests. When set, the live OFAC SDN URL is not fetched.

## Actor input object example

```json
{
  "sdnXmlUrl": "https://www.treasury.gov/ofac/downloads/sdn.xml",
  "maxEntriesPerWatch": 50,
  "requestTimeoutSeconds": 60,
  "delivery": "dataset",
  "datasetMode": "all",
  "snapshotKey": "sanctions-change-digest-state",
  "notifyOnNoNew": true,
  "dryRun": false
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("taroyamada/sanctions-change-digest").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 = {}

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

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

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

```

## CLI example

```bash
echo '{}' |
apify call taroyamada/sanctions-change-digest --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=taroyamada/sanctions-change-digest",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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