DEV Community

easysolutions906
easysolutions906

Posted on

How to Screen Names Against the OFAC SDN List Programmatically

How to Screen Names Against the OFAC SDN List Programmatically

If your company processes payments, onboards customers, or moves money across borders, you are legally required to screen those parties against the OFAC SDN list. The Office of Foreign Assets Control maintains a list of roughly 18,000 individuals, entities, vessels, and aircraft that US persons are prohibited from doing business with. Penalties for violations start at $356,579 per occurrence, and the Treasury Department does not care whether you missed a match on purpose or by accident.

This article walks through what the SDN list contains, why simple string matching is not enough, and how to integrate sanctions screening into your application with a few lines of code.

What the SDN list actually contains

The Specially Designated Nationals list is published as XML by the US Treasury at treasury.gov/ofac/downloads/sdn.xml. Each entry includes:

  • Primary name and aliases (a single person can have 10+ aliases in different scripts)
  • Entity type: Individual, Entity, Vessel, or Aircraft
  • Sanctions programs: RUSSIA-EO14024, SDGT, IRAN, CUBA, DPRK, CYBER2, and 70+ others
  • Identifying information: dates of birth, nationalities, passport numbers, addresses

The challenge is not downloading this data. The challenge is matching against it accurately. Names appear in multiple transliterations. "Vladimir Vladimirovich PUTIN" also appears as "Vladimir PUTIN." A naive exact-match search for "Putin" would miss both.

Why fuzzy matching matters

Consider a KYC onboarding flow. A customer enters "V. Putin" as their name. An exact-match lookup returns zero results. Your system clears them, and you have just onboarded a sanctioned individual.

Production-grade OFAC screening requires multiple matching strategies working together:

  • Jaro-Winkler similarity to handle transpositions and typos
  • Token-set matching to handle reordered words ("BANK OF IRAN" vs "IRAN BANK")
  • Phonetic matching (Double Metaphone) to catch spelling variations of same-sounding names
  • Substring containment for partial name queries

Each strategy contributes a weighted score, and the system returns a confidence level: exact, strong, partial, or weak.

Screening a name with the REST API

Here is a curl request that screens the name "Putin" with a country filter:

curl -X POST https://ofac-screening.up.railway.app/screen \
  -H 'Content-Type: application/json' \
  -d '{"name": "PUTIN", "country": "Russia"}'
Enter fullscreen mode Exit fullscreen mode

The response includes scored matches with detailed explanations:

{
  "query": { "name": "PUTIN", "country": "Russia" },
  "threshold": 0.85,
  "matchCount": 1,
  "matches": [{
    "entity": {
      "name": "Vladimir Vladimirovich PUTIN",
      "sdnType": "Individual",
      "programs": ["RUSSIA-EO14024"],
      "title": "President of the Russian Federation"
    },
    "score": 0.86,
    "matchType": "strong",
    "matchedOn": "alias",
    "matchedName": "Vladimir PUTIN"
  }],
  "listVersion": "03/13/2026",
  "screenedAt": "2026-03-15T17:27:07.651Z"
}
Enter fullscreen mode Exit fullscreen mode

The listVersion and screenedAt fields serve as an audit trail, which regulators expect to see in your compliance documentation.

Screening in JavaScript

const screenCustomer = async (name, country = null) => {
  const res = await fetch('https://ofac-screening.up.railway.app/screen', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name, country, threshold: 0.85 }),
  });

  const data = await res.json();

  if (data.matchCount > 0) {
    console.log(`ALERT: ${data.matchCount} potential match(es) for "${name}"`);
    data.matches.forEach((m) => {
      console.log(`  ${m.entity.name} (score: ${m.score}, type: ${m.matchType})`);
    });
  } else {
    console.log(`CLEAR: No matches for "${name}"`);
  }

  return data;
};

// Screen a batch during onboarding
const names = ['John Smith', 'PUTIN', 'Acme Trading LLC'];
for (const name of names) {
  await screenCustomer(name);
}
Enter fullscreen mode Exit fullscreen mode

Using the MCP server in Claude Desktop

If you work in compliance and want to screen names conversationally without writing code, install the MCP server and ask Claude directly.

npx @easysolutions906/mcp-ofac
Enter fullscreen mode Exit fullscreen mode

Add this to your Claude Desktop configuration (claude_desktop_config.json):

{
  "mcpServers": {
    "ofac": {
      "command": "npx",
      "args": ["-y", "@easysolutions906/mcp-ofac"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Once connected, you can ask Claude things like "Screen the name Ali Hassan against the OFAC sanctions list" and it will call the ofac_screen tool, returning scored matches with confidence levels and program details. This is useful for one-off checks during manual reviews, or when a compliance officer needs to investigate a flagged transaction without opening a separate tool.

How this compares to enterprise solutions

Traditional OFAC screening platforms like Dow Jones, LexisNexis, and Accuity charge $10,000 to $100,000 per year. They bundle sanctions screening with broader compliance suites that many smaller companies do not need.

This API embeds the full SDN dataset locally (updated from Treasury.gov), runs multi-strategy fuzzy matching, and returns results in under 100ms. The free tier allows 10 screens per day -- enough for early-stage startups validating their compliance workflow. Paid plans start at $4.99/month for 100 screens/day.

The SDN data updates frequently. The API includes a /data-info endpoint that returns the publish date and record count so you can verify freshness at any time.

Next steps

  • REST API: Send a POST to /screen with a name. No signup required for the free tier.
  • MCP server: Run npx @easysolutions906/mcp-ofac and add it to Claude Desktop or Cursor.
  • Batch screening: POST to /screen/batch with up to 100 names per request.
  • npm: npm install @easysolutions906/mcp-ofac

Sanctions compliance is not optional. But it does not have to be expensive or complicated.

Top comments (0)