Loading workbench page
Fetching primary parquet sources and computing exhibits.
Fetching primary parquet sources and computing exhibits.
This page measures the trade footprint that surrounds the entities on 15 government sanctions and export-control lists. Sanctions lists match entities, not countries. Country-level aggregation is a coarse proxy: a Russian national on a UK list does not make Russia-UK bilateral trade sanctioned, and a London real-estate holding by a listed oligarch is not a sanctioned goods flow. Treat the figures as a pointer to jurisdictions that warrant further due diligence, not a measurement of illicit trade volume. Hufbauer, Schott, Elliott & Oegg (2007, PIIE, Economic Sanctions Reconsidered, 3rd ed.) catalogue the 20th-century shift from comprehensive embargoes to targeted smart designations; Drezner (2003, Int'l Studies Quarterly47(3): 643-659) and Gaibulloev, Oyun & Younas (2020, Public Choice 183: 247-268) model the signalling and coercion mechanics. Source lists: the 15 government lists in sanctions_entities.parquet, built directly from the US Consolidated Screening List (12 US lists including OFAC SDN and the BIS Entity List), the EU Financial Sanctions Files, the FCDO UK Sanctions List and the DHS UFLPA Entity List. The figures below exclude parties positively identified as individuals, vessels or aircraft, since an individual designated at a Russian address does not make Russian exports sanctioned. They do not exclude the BIS and State Department records, which the Consolidated Screening List publishes with no party type at all.
Data not yet ingested. sanctions_entities.parquet is not present on this deployment. Run make sanctions, which fetches the four government sources and writes it via scripts/ingest/build_sanctions_entities.py. The figures below populate once it lands. The auxiliary ECCN control-reason figure at the bottom of the page is grounded in eccn_catalog.parquet, which is a separate ingest.
For every listed party whose address resolves to an ISO3, we count unique entities per home jurisdiction and pair that count with the country's total goods exports in 2024 from CEPII BACI. Designated individuals, vessels and aircraft are excluded: a person designated at a Russian address does not make Russian exports sanctioned, and neither vessels nor aircraft are exporters in BACI. Records the US Consolidated Screening List publishes with no party type at all are kept, because that is every BIS and State Department sublist including the Entity List. The export volume is not a measure of sanctioned trade: it is the legitimate-plus-illicit universe of exports from a jurisdiction that has at least one listed party. The caveat matters most for jurisdictions with broad legitimate trade (UK, UAE, China, Hong Kong) where a handful of listed firms stand alongside a large licit export base. See Felbermayr, Kirilakha, Syropoulos, Yalcin & Yotov (2020) on the identification problem in quantifying sanctions effects, and Ahn & Ludema (2020) on entity-level, smart sanctions targeting in the Russia programs.
WITH counts AS (
SELECT jurisdiction_iso3 AS iso3, COUNT(DISTINCT entity_id) n
FROM 'sanctions_entities.parquet'
WHERE entity_type NOT IN ('Individual', 'Vessel', 'Aircraft')
AND jurisdiction_iso3 IS NOT NULL
GROUP BY 1
)
SELECT counts.iso3, ctry.name, counts.n AS entity_count,
SUM(b.total_value)*1000 AS export_usd
FROM counts
LEFT JOIN 'countries.parquet' ctry ON ctry.iso3=counts.iso3
LEFT JOIN 'bilateral_year/year=2024/*.parquet' b ON b.exporter_code=ctry.code
GROUP BY counts.iso3, ctry.name, counts.n
ORDER BY entity_count DESC LIMIT 20;For USA, EU27 (summed across all 27 member states), Japan, and the United Kingdom, total 2024 goods imports from any ISO3 that is the address country of at least one listed party, split by the list that put it there. Repeat caveat: this is the legitimate import base from those jurisdictions, not an estimate of sanctioned-goods imports. An importer appears under several lists when a jurisdiction is present in more than one: China hosts listed parties on the BIS Entity List, the UFLPA Entity List, OFAC CMIC and OFAC SDN, so it contributes to each of those bars for different reasons. The bar width is the same import base each time and the bars must not be added together.
WITH list_origins AS (
SELECT DISTINCT list_source AS list_id, jurisdiction_iso3 AS iso3
FROM 'sanctions_entities.parquet'
WHERE entity_type NOT IN ('Individual', 'Vessel', 'Aircraft')
AND jurisdiction_iso3 IS NOT NULL
)
SELECT importer, list_id, SUM(b.total_value)*1000 AS import_usd
FROM 'bilateral_year/year=2024/*.parquet' b
JOIN importer_codes ic ON ic.code = b.importer_code
JOIN list_origins lo ON lo.iso3 IN (
SELECT iso3 FROM origin_codes WHERE code = b.exporter_code
)
GROUP BY importer, list_id ORDER BY importer, import_usd DESC;No published sanctions or export-control list carries an HS code for a listed entity, in any of the 15 feeds ingested here, so this figure cannot isolate sanctioned trade at the product level. That is a limit of the source data, not of the query. What we can do with SQL: for the set of countries that host at least one listed party, rank their HS6 export lines by 2024 value, and annotate each with the single largest origin country on that line. Use this to identify HS6 categories where any targeted enforcement action would cover a large underlying trade volume, not as a claim that the trade itself is sanctioned. See Crozet & Hinz (2020) on quantifying sanctions pass-through at the sectoral level for the 2014 Crimea/Donbass measures.
Set aside the entity table for this panel and look instead at the fully aggregated sanctions/country_flags.parquettable, which tallies US OFAC SDN and EU consolidated financial sanctions designations by listing address-country. Hufbauer, Schott, Elliott & Oegg (2007, PIIE, Economic Sanctions Reconsidered, 3rd ed.) argue that the empirical incidence of sanctions has shifted from broad trade embargoes to targeted 'smart' designations since the 1990s; that shift shows up sharply in the distribution of SDN listings by address-country, which concentrates most listings in a few high-risk jurisdictions while leaving hundreds of countries with single- or double-digit counts. The entity ingest behind Figure 1 shows the same shape independently: of 18,470 listed parties carrying a resolved home jurisdiction, the top five (RUS, CHN, IRN, USA, ARE) hold 65.2%, while 74 of the 167 jurisdictions present carry fewer than ten each. Address-country is a coarse proxy (a listed person can reside in a third country) so treat the ranking as enforcement-presence, not national guilt.
Separate from entity-based sanctions, the US Bureau of Industry and Security maintains the Commerce Control List (CCL), which classifies dual-use items by Export Control Classification Number. Each ECCN carries one or more reasons for control under 15 CFR 738.2: NS national security, AT anti-terrorism, MT missile technology, NP nuclear nonproliferation, CB chemical and biological, RS regional stability, FC firearms convention, CC crime control, SI significant items, SS short supply, UN UN embargo, CW chemical weapons convention. The distribution below would be computed from eccn_catalog.parquet, a separate ingest from the entity lists above. No script in this repository builds that file and it is not on disk, so the figure is empty (0 ECCN rows) and no ECCN claim on this page is currently evidenced.
WITH split AS (
SELECT TRIM(u.r) AS reason_code
FROM 'sanctions/eccn_catalog.parquet' c,
LATERAL unnest(string_split(c.reasons,'|')) u(r)
)
SELECT reason_code, COUNT(*) n FROM split WHERE reason_code<>''
GROUP BY reason_code ORDER BY n DESC;A cumulative-by-year trajectory of designations by regime (OFAC, EU, UK) is the natural way to read the modern shift Hufbauer, Schott, Elliott & Oegg (2007) describe, but the ingested country_flags.parquet carries only the current point-in-time tallies for OFAC SDN and EU consolidated financial sanctions. sanctions_entities.parquet does carry a designation date, but coverage is too uneven to build a comparable series across regimes: 100% for the UK, EU and UFLPA lists, 95.5% for the BIS Entity List, and 0% for OFAC SDN, which is the largest list at 19,199 records and publishes no date in the Consolidated Screening List export. So we adapt: among the top-20 address-countries by combined OFAC + EU count, how is the stack composed? A country that scores heavily on OFAC but near-zero on EU is under a primarily US program (Mexico and Colombia, both 0% EU, are cartel rosters); balanced stacks (Russia 27%, Iran 25%, Syria 28%) indicate transatlantic co-ordination; and a handful run EU-dominant, where the EU has listed more parties at that address than OFAC has (Afghanistan 71%, Belarus 55%, DPRK 44%).
The cleanest empirical signal of sanctions leakage is the bilateral export series from nearby or hub jurisdictions into the sanctioned importer. CEPII BACI carries this for every year through 2024. We plot the eight jurisdictions most commonly cited in the 2022-2023 re-export literature: Armenia, Kazakhstan, Kyrgyzstan, Azerbaijan, Georgia (Caucasus and Central Asia), plus Turkey, the UAE, and China (third-party hubs). Chupilkin, Javorcik & Plekhanov (2023, EBRD Working Paper 276, 'The Eurasian roundabout: Trade flows into Russia through the Caucasus and Central Asia') document that CN8 HS lines with the largest Russia sanctions in the EU 2022 packages show the largest 2022-2023 surges from these same origins. Crozet & Hinz (2020, Economic Policy 35(101): 97-146, on the 2014 Russia-Ukraine measures) model the same mechanism: a share of sanctioned trade re-routes via lightly-controlled jurisdictions rather than disappearing.
A canonical stylised fact in the sanctions literature: after the 1990s Iraq and Yugoslavia episodes, the 'comprehensive embargo' instrument fell out of favour and was replaced by 'targeted smart sanctions' against named individuals, entities, and sectors (Hufbauer, Schott, Elliott & Oegg 2007, PIIE, Economic Sanctions Reconsidered, 3rd ed.; Drezner 2011, International Studies Review 13(1): 96-108, 'Sanctions Sometimes Smart'). The ingest carries no reliable listing-date field to trace the annual shift, but the current point-in-time distribution in country_flags.parquet encodes the legacy cleanly. We split the 174 ISO3 rows in country_flags into a comprehensive-regime bucket (CUB, IRN, PRK, SYR, RUS, BLR, MMR, VEN, per OFAC country-program pages and EU Official Journal comprehensive-program decisions) and a targeted-designation bucket (every other country in the flag table). The count gap per country is the size of the regime-type asymmetry.
Absolute counts in Figure 4 reward jurisdictions with large legitimate trade. Russia heads the listing tally, but so does Mexico (a narcotics-program artefact) and China (a BIS / OFAC sectoral artefact). Normalising by the country's export base flips the ranking onto the regime-intensity axis: economies with thin licit exports and three-digit designation counts (DPRK 402 on $0.4B of exports, Syria 371 on $1.1B, Yemen 147 on $0.7B) sit at the top because the numerator is unusually large relative to a tiny denominator, the empirical signature of a comprehensive embargo per Hufbauer, Schott, Elliott & Oegg (2007, PIIE, Economic Sanctions Reconsidered, 3rd ed.) and Felbermayr, Kirilakha, Syropoulos, Yalcin & Yotov (2020, European Economic Review 129: 103561) on the Global Sanctions Data Base. Restricted to is_flagged countries (100+ combined OFAC + EU listings) with at least $100M in 2024 exports to keep the ratio defined.
The 2022 Russia program and the Iran, DPRK, and Myanmar regimes have re-established sanctions as a primary foreign-policy tool, but the entity-targeting structure of the modern system means the binding constraint is compliance-screening capacity at private firms, not the formal roster size. The address-country heat-map in Figure 4 is where a bank's MLRO allocates transaction monitoring spend; the jurisdictional shortlist in Figure 1 is where a supply-chain compliance lead opens enhanced due-diligence files. An outright origin ban (sectoral sanctions, a la the 2022 G7 Russia oil price cap) needs Figures 2 and 3: without a read on the underlying HS6 trade base, sanctions designers cannot anticipate substitution, pass-through to third countries, or the price-cap enforcement cost.
data.trade.gov/downloadable_consolidated_screening_list/v1/consolidated.csv. The SDN count is cross-checked against Treasury's own SDN.XML, which reports the same 19,199.sanctionslist.fcdo.gov.uk/docs/UK-Sanctions-List.csv. This replaced the OFSI Consolidated List, which closed on 28 January 2026 and must not be ingested.make sanctions. No aggregator sits in the path, so no third-party licence attaches to the result.data/parquet/sanctions/country_flags.parquet as per-ISO3 counts (ofac_count, eu_count, total_count, is_flagged at 100-combined threshold), derived from the OFAC SDN and EU FSF rows of the entity table by make sanctions. Drives Figures 4, 6, 8 and 9. The entity-level feed is data/parquet/sanctions_entities.parquet (names, aliases, addresses, programmes, designation dates), which drives Figures 1 to 3.data/parquet/sanctions/eccn_catalog.parquet (0 rows, not currently built). Supplements entity lists with dual-use product controls. is_flagged = true threshold (100+ combined listings). The count is a point-in-time read of the OFAC SDN and EU FSF designations in the entity table; counts will jump materially the day a new program is announced.SELECT f.iso3, f.ofac_count, f.eu_count, f.total_count, f.is_flagged,
SUM(b.total_value) * 1000 AS export_usd
FROM 'sanctions/country_flags.parquet' f
LEFT JOIN (SELECT MIN(code) code, iso3 FROM 'countries.parquet'
WHERE regexp_matches(iso3, '^[A-Z0-9]{3}$') GROUP BY iso3) c ON c.iso3 = f.iso3
LEFT JOIN 'bilateral_year/year=2024/*.parquet' b ON b.exporter_code = c.code
WHERE regexp_matches(f.iso3, '^[A-Z0-9]{3}$')
GROUP BY f.iso3, f.ofac_count, f.eu_count, f.total_count, f.is_flagged
ORDER BY total_count DESC LIMIT 20;SELECT iso3, ofac_count, eu_count,
CAST(eu_count AS DOUBLE) / NULLIF(ofac_count + eu_count, 0) AS eu_share
FROM 'sanctions/country_flags.parquet'
WHERE regexp_matches(iso3, '^[A-Z0-9]{3}$')
ORDER BY ofac_count + eu_count DESC LIMIT 20;SELECT ce.iso3, b.year, SUM(b.total_value) * 1000.0 AS v
FROM 'bilateral_year/**/*.parquet' b
JOIN countries ce ON ce.code = b.exporter_code
JOIN countries ci ON ci.code = b.importer_code
WHERE ci.iso3 = 'RUS'
AND ce.iso3 IN ('ARE','ARM','AZE','CHN','GEO','KAZ','KGZ','TUR')
AND b.year BETWEEN 2019 AND 2024
GROUP BY ce.iso3, b.year ORDER BY ce.iso3, b.year;SELECT CASE WHEN iso3 IN ('CUB', 'IRN', 'PRK', 'SYR', 'RUS', 'BLR', 'MMR', 'VEN')
THEN 'comprehensive regime' ELSE 'targeted' END AS regime,
COUNT(*) AS n_countries,
SUM(total_count) AS grand_total
FROM 'data/parquet/sanctions/country_flags.parquet'
WHERE regexp_matches(iso3, '^[A-Z0-9]{3}$')
GROUP BY regime ORDER BY grand_total DESC;WITH exp AS (
SELECT c.iso3, SUM(b.total_value) * 1000 AS export_usd
FROM 'bilateral_year/year=2024/*.parquet' b
JOIN (SELECT MIN(code) code, iso3 FROM 'countries.parquet'
WHERE regexp_matches(iso3, '^[A-Z0-9]{3}$') GROUP BY iso3) c
ON c.code = b.exporter_code
GROUP BY c.iso3
)
SELECT f.iso3, f.total_count, exp.export_usd,
1e9 * f.total_count / NULLIF(exp.export_usd, 0) AS designations_per_billion
FROM 'sanctions/country_flags.parquet' f
LEFT JOIN exp ON exp.iso3 = f.iso3
WHERE regexp_matches(f.iso3, '^[A-Z0-9]{3}$')
AND f.is_flagged AND exp.export_usd >= 1e8
ORDER BY designations_per_billion DESC LIMIT 20;