ofac-sdn-parser
Fetch and parse the U.S. Treasury OFAC SDN list into crypto addresses. No API key, no account — the export is public.
import asyncio
from ofac_sdn_parser import fetch_sanctioned_addresses
rows = asyncio.run(fetch_sanctioned_addresses())
print(len(rows)) # ~990
print(rows[0].address, rows[0].network, rows[0].entity_name, rows[0].program_label)
pip install git+https://github.com/omnitraceapp/ofac-sdn-parser
python -m ofac_sdn_parser.verify # counts + per-chain breakdown + digest
python -m ofac_sdn_parser.verify --json # machine-readable
python -m ofac_sdn_parser.verify --file SDN_ENHANCED.XML # diff against a downloaded export
Why this exists
Every guide older than mid-2026 points at an endpoint that no longer works, and the two failures that follow are easy to make and hard to notice — both of them look like "OFAC has no crypto addresses today".
1. The old endpoints are gone. Verified 2026-09-06:
| URL | status |
|---|---|
sanctionslist.ofac.treas.gov/api/sdn (old JSON API) |
403 Forbidden |
www.treasury.gov/ofac/downloads/sdn.xml (legacy) |
302 to the new service |
sanctionslistservice.ofac.treas.gov/api/PublicationPreview/exports/SDN.XML |
200 ✅ |
The working URL redirects once more to a signed S3 object. Any HTTP client that follows redirects is fine.
2. Element.iter() silently returns nothing. The export uses a default XML namespace. Python's
iter() does plain string matching and does not honour the {*} wildcard; only the ElementPath
methods do.
root.iter("{*}sdnEntry") # -> nothing, no error
root.iterfind("{*}sdnEntry") # -> works
That one costs an afternoon if you hit it, and it fails quietly — you get an empty list, not an exception.
Proving a parse is complete
Non-empty is not the same as complete. address_set_digest() is an MD5 over the sorted,
de-duplicated address set: compute it over your output and over Treasury's own export, and if the
two agree you are reading the same list.
from ofac_sdn_parser import address_set_digest
print(address_set_digest(rows))
The bundled verifier does this for you and prints the per-chain breakdown:
addresses: 991
bitcoin 536
tron 282
ethereum 124
unknown 27
litecoin 12
dash 5
zcash 4
xrp 1
sdn entries read: 19,329
duplicates: 16
skipped (blank): 0
digest (md5): 3c29b9cfef715f206bcb8c8ec8dd8356
That is a real run against the live feed on 6 September 2026. The digest is not a constant to match - OFAC designates and delists continually, so it changes. It is a fingerprint for comparing two parses of the same download.
Notes worth knowing
- Do not switch to
SDN_ENHANCED.XML. It is 103 MB against 28 MB and contains exactly the same addresses — the extra content is entity metadata and ownership relationships, not more wallets. - OFAC publishes deltas.
/changes/latestis ~15 KB against the 28 MB full export, and/changes/history/{year}[/{month}[/{day}]]lists publication ids. Crypto designations are rare — roughly one publication in eight carries any. Deltas use the namespacehttps://www.treasury.gov/ofac/DeltaFile/1.0and mark each entityaction="add"/"remove". skipped_blankshould be zero. A crypto row with a valididTypeand noidNumbermeans the schema moved and addresses are being dropped. The parser reports the count instead of swallowing it.networkisunknownrather than a guess. A wrong chain label sends a lookup to the wrong explorer, which is worse than no label.- An absence of match is not a clean result. OFAC covers US-designated entities and nothing else.
Install
pip install git+https://github.com/omnitraceapp/ofac-sdn-parser
Not on PyPI yet. Requires Python 3.10+ and aiohttp — though parse_sdn_xml itself is pure and
needs neither, so you can vendor the one file if you already have the XML.
Tests
pip install -e ".[dev]"
pytest
The suite runs against a bundled fixture and makes no network calls.
Licence
MIT.
Maintained by OmniTrace, which tracks USDT and USDC blacklist events on TRON and Ethereum and screens wallets against this list. The same parser runs in production there; measured statistics are published here.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ofac_sdn_parser-1.0.0.tar.gz.
File metadata
- Download URL: ofac_sdn_parser-1.0.0.tar.gz
- Upload date:
- Size: 11.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f763970fc0953c13d33c2c8f384ab800f26d9964172d9faf02bf8036a0d7e4e9
|
|
| MD5 |
13fbd47f575b9e08297e6b266e2f65be
|
|
| BLAKE2b-256 |
56d0d4bd6d7575df0feb066e04682bc0a353b385aa6fad3a2b7156e61aa0dd63
|
File details
Details for the file ofac_sdn_parser-1.0.0-py3-none-any.whl.
File metadata
- Download URL: ofac_sdn_parser-1.0.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a3921f3f282fc766124505ca663db203447b275ef5f44a2c65bf44c98a0c6ed
|
|
| MD5 |
a8e6f9b49e7ad3c94033cf8c850a0211
|
|
| BLAKE2b-256 |
3326349a018ba1d23a9560b420c8252e24d1ec89e56be3d75864433a2d0226fd
|