Technical writing

Trade, Sanctions, and Export Controls: Joining the Rules to the Goods That Move

· 13 min read· AI Analytics
TradeSanctionsExport ControlsOFACData Engineering

When the United States sanctions a country or adds a company to a blacklist, the rule lands in one database, the violations that follow land in a second, and the actual cargo—the containers, the chips, the machine tools, the dollar values by port—is counted in a third. Read separately, each tells half a story. Joined together by the country, the commodity, and the party, the OFAC sanctions lists, the BIS export-enforcement record, and the Census foreign-trade statistics let an analyst set a restriction against the goods it was meant to stop and watch what the trade actually did.

This article covers the three federal trade-control datasets and why they belong in one view; the distinct mandates behind them—OFAC in the Treasury administering economic sanctions, BIS in the Commerce Department running the Export Administration Regulations and its enforcement, and the Census Bureau compiling the official import and export statistics; the structure of each, from the Specially Designated Nationals list and the Entity List to the Harmonized System commodity codes; the three join keys—country, HS commodity, and party—that align the rules, the violations, and the flows; transshipment and how controls push trade toward third countries; how penalties compare to the trade at stake; a Python workflow that pulls trade with a country by HS code over time from the Census international-trade API and overlays sanctions and export-enforcement dates to measure the shift; the analytical questions the assembled data answers; and the caveats—party-name matching, classification differences, and reporting lag—that govern how far the joins can be trusted.

Three datasets, one system

US trade controls and the trade they govern are administered by three agencies that rarely publish their data together, even though they describe the same system from different angles. The first is the Office of Foreign Assets Control (OFAC), part of the Treasury, which administers the country's economic and trade sanctions and publishes the lists of barred parties and countries. The second is the Bureau of Industry and Security (BIS), part of the Commerce Department, which runs the Export Administration Regulations that govern which dual-use goods and technology can ship where, maintains the Entity List of restricted end users, and publishes its enforcement actions against export-control violators. The third is the Census Bureau, which compiles the official US import and export statistics—the dollar value and quantity of goods that actually cross the border, broken out by commodity, country, and port.

They sit at different points of the same machinery. OFAC and BIS write and enforce the rules—who may not be dealt with, and what may not be shipped to whom. Census measures the consequence—what was in fact bought and sold across the border. The premise of this article is that the three are far more useful together than apart, because a trade restriction is only legible against the trade it was aimed at. Our database keeps them as three keyed tables—ofac_sanctions, bis_export_enforcement, and census_foreign_trade—three federal trade-control datasets aligned on shared keys, with Customs and Border Protection (CBP) trade data available alongside, so the work of analysis is matching the country and commodity codes and reconciling party names across them.

OFAC: the sanctions lists

OFAC administers and enforces economic and trade sanctions under authorities that include the International Emergency Economic Powers Act (IEEPA)and the Trading with the Enemy Act, together with the country- and program-specific statutes that Congress passes. Sanctions come in two broad shapes. There are comprehensive country programs, which broadly prohibit US persons from trade and financial dealings with a sanctioned jurisdiction, and there are list-based, targeted sanctions aimed at specific persons, companies, vessels, and aircraft. The flagship list is the Specially Designated Nationals and Blocked Persons (SDN) list: parties whose property and interests in the US financial system are blocked and with whom US persons are generally prohibited from transacting. OFAC also publishes a broader Consolidated Screening List that gathers the SDN list together with several non-SDN lists into one screening file.

For data work, two facts about the OFAC lists matter most. First, every designation carries the sanctions program under which it was made—a short code tying the entry to a country or a thematic program—and most carry an effective date, so the lists can be read not just as a roster but as a timeline of when countries and parties were acted on. Second, the entries are party records, rich with names, aliases, addresses, identifiers, and dates of birth or registration, which is what makes them screenable against counterparties and against the violating companies named in enforcement actions. The program code is the natural country join key; the name-and-alias block is the party join key. Both are explored at length in the dedicated OFAC piece linked at the end.

BIS: export controls and enforcement

Where OFAC governs who may be dealt with, BIS governs what may be shipped. The Export Administration Regulations (EAR) control the export and reexport of dual-use items—goods, software, and technology with both civilian and potential military or proliferation applications. The EAR work through the Commerce Control List, which assigns each controlled item an Export Control Classification Number, and through a country chart that pairs the item with its destination to determine whether a license is required. BIS also maintains the Entity List—named foreign parties for whom a license is required (often with a presumption of denial) for items that would otherwise ship freely—along with related restricted-party lists. The Entity List is where export controls become party-specific, naming the companies and institutions in a destination that are judged to pose national-security or foreign-policy concerns.

When the rules are broken, BIS's enforcement arm pursues the violations and publishes the results. The export-enforcement record documents settled and adjudicated cases—unlicensed exports, shipments to prohibited destinations or end users, evasion and transshipment schemes, and antiboycott violations—naming the violating company or individual, the destination country, the commodity or technology involved, and the penalty imposed. For the join, the enforcement record is the connective tissue: it carries a party(matchable against OFAC and against the trade data), a destination country (matchable against both the sanctions programs and the Census country dimension), and a commodity or technology description (mappable, with care, onto the Harmonized System). That triple is what lets export-control actions be set against the actual flow of goods.

Census: the foreign-trade statistics

The Census Bureau is the official compiler of US international-trade statistics. Working from the export and import documentation filed with CBP, Census publishes the monthly value and quantity of goods crossing the US border, broken out by commodity, by partner country, by customs district and port, and by mode of transport. The commodity dimension is organized by the Harmonized System (HS), the international standard for classifying traded goods. The HS is hierarchical: a two-digit chapter (for example, chapter 85, electrical machinery) contains four-digit headings, which contain six-digit subheadings harmonized worldwide; the United States extends the code to ten digits for its own statistical detail (the Schedule B for exports and the HTS for imports). This nesting is precisely what lets an analyst zoom from a whole sector down to a single product line.

Census exposes all of this through the international-trade API at api.census.gov/data/timeseries/intltrade, which returns time series of imports and exports filtered by country code, HS commodity, and month. The API is public and key-optional—small pulls work anonymously, and a free registered key lifts the rate limits for serious work. Because the data is a time series indexed by country and HS code, it is the dimension against which the discrete events in the sanctions and enforcement records can be plotted: the rules and the violations are points in time tied to a country and a party; the trade statistics are the continuous flow those points act upon.

The join keys: country, commodity, party

The whole exercise rests on three join keys, each linking a different pair of the datasets. Aligning them carefully is the central data-engineering task, and each carries its own friction. Our database stores the three tables—ofac_sanctions, bis_export_enforcement, and census_foreign_trade—with these keys exposed so the joins can be built directly:

-- ofac_sanctions (one row per designated party)
party_name            -- primary name of the blocked person / entity
aliases               -- alternate names and spellings
sanctions_program     -- program code (country / thematic)
country               -- jurisdiction associated with the entry
effective_date        -- date of designation

-- bis_export_enforcement (one row per enforcement action)
respondent_name       -- the violating company or individual (party)
destination_country   -- where the controlled goods were headed
commodity_desc        -- item / technology involved (maps to HS)
penalty_amount        -- civil/criminal penalty imposed
action_date           -- date of the order or settlement

-- census_foreign_trade (one row per country x HS x month)
cty_code              -- Census partner-country code
hs_code               -- Harmonized System commodity code
flow                  -- imports or exports
value                 -- monthly trade value (USD)
month                 -- reporting month

The country key ties all three together, and it is the cleanest of the three—though not free. Census uses its own numeric country-code scheme; OFAC programs reference countries by program code and name; BIS names destination countries in narrative form. Building a single country crosswalk (Census code to OFAC program to ISO name) is a one-time investment that pays off across every analysis. With it, an analyst can line up a country's sanctions history, the export-enforcement actions naming it as a destination, and its month-by-month trade with the United States.

The commodity key links BIS enforcement to Census trade through the Harmonized System, and it is the hardest. Census trade is HS-coded by construction; BIS enforcement actions describe the goods in prose—“semiconductor manufacturing equipment,” “avionics,” “machine tools”— and the controlled-item classification (the Export Control Classification Number) does not map one-to-one to HS. The practical approach is to work at the HS chapter or heading level, mapping a class of controlled technology onto the HS chapters that contain it, and to treat the result as indicative rather than exact. The party key links OFAC and BIS—and either of them to a counterparty being screened—through names and aliases, which is the messiest join of all and the subject of the caveats below.

Transshipment and the shift to third countries

One of the most important things the joined data can reveal is what controls do not stop. When the United States sanctions a country or tightens export controls on it, the demand for the restricted goods does not simply vanish; it often reroutes. Goods are exported to a third country that is not under the same restriction and then onward—legally reexported, or illegally diverted—to the original intended destination. This is transshipment, and it is one of the central cat-and-mouse dynamics of trade-control enforcement.

The trade statistics make the pattern visible in a way that a single country's data cannot. When a sanction bites, an analyst frequently sees US exports of a controlled commodity to the sanctioned country fall—while, in the same window, US exports of the same HS code to one or more nearby third countries rise out of proportion to those countries' own apparent consumption. A small economy that suddenly imports far more high-end electronics or industrial components than its market could plausibly absorb is a classic transshipment signal. The export-enforcement record corroborates the suspicion: BIS cases naming intermediary jurisdictions and diversion schemes point to exactly the corridors the trade data flags. Reading the Census flows and the BIS enforcement actions together is what turns a hunch about evasion into a documented corridor—a country pair and a commodity where the rules and the goods have visibly diverged.

Penalties versus the trade at stake

A second question the assembled data answers is one of proportionality: how do the penalties imposed for export-control and sanctions violations compare to the value of the trade they concern? The enforcement record carries a penalty amount per action; the trade statistics carry the value of the underlying flows. Setting them side by side reframes enforcement as a question of magnitude rather than incident count. A single landmark settlement against a large exporter can dwarf the combined penalties of hundreds of smaller cases, and a commodity or destination that draws frequent small actions may represent a far smaller slice of trade than one that draws rare but enormous ones.

The comparison also sharpens the interpretation of where enforcement concentrates. Ranking destinations and commodities by the number and size of enforcement actions, and then normalizing by the trade at stake in each, distinguishes a destination that is genuinely a hotspot of violation from one that simply does a great deal of legitimate trade. The same normalization separates a commodity under heavy, effective scrutiny from one that is merely voluminous. Done carefully—and with the caveat that enforcement reflects where agencies look as much as where violations occur—this is the analysis behind the policy question of whether the enforcement effort is aimed where the risk and the value actually are.

Analytical uses

Assembled and keyed, the three datasets answer the questions that sit behind trade and national-security policy—questions no one of them can answer alone.

How trade with a country changed after it was sanctionedis the most direct use. Overlaying a sanction's effective date on the Census time series of trade with that country—in aggregate and by HS commodity—measures the before-and-after shift in the flow the restriction targeted, and distinguishes commodities that fell sharply from those that barely moved. Which commodities and destinations draw the most export-enforcement actions aggregates the BIS record by HS chapter and by destination country, surfacing the goods and corridors where violation is most concentrated, then weights each by the trade at stake to separate hotspots from high-volume legitimate trade.

Whether flows shift to third countries after controls tighten is the transshipment analysis: tracking exports of a controlled HS code to a sanctioned destination and to its plausible intermediaries in the same window, and flagging the third countries whose imports rise as the direct route closes. And how penalties compare to the trade at stake brings the enforcement and trade values together to judge the proportionality and the targeting of the enforcement effort. Each of these is a question that the rules, the violations, and the flows can only answer in combination—which is the entire reason to join them.

Python workflow: trade over time with action dates overlaid

The script below pulls US trade with a country by HS code over time from the Census international-trade API and overlays an action date—a sanction or an export-enforcement order—to measure the shift in the flow around it. It computes two metrics: the total trade in the pulled window, and the change in mean monthly trade in the year before the action versus the year after. The Census API takes an optional key; small pulls run without one. The sanctions and enforcement dates here are illustrative anchors—in production they should be loaded from the OFAC effective_date and the BIS action_date columns, so the overlay is driven by the real records rather than hard-coded.

import requests, pandas as pd

# Three public, key-optional federal sources, joined by country / HS / party.
#   1. Census international-trade API -- monthly imports and exports
#      by country and Harmonized System (HS) code. (api.census.gov)
#   2. OFAC sanctions program dates -- when a country/program was acted on.
#   3. BIS export-enforcement actions -- violations by destination/commodity.
# The Census API takes an optional key (CENSUS_KEY); small pulls work
# without one. The sanctions/enforcement dates here are illustrative
# anchors -- load them from the OFAC and BIS records for production use.
CENSUS = "https://api.census.gov/data/timeseries/intltrade"


def census_trade(flow, country_code, hs, start, end, key=None):
    # flow: "imports" or "exports". country_code is the Census country
    # code; hs is a Harmonized System prefix (chapter, heading, or full).
    base = f"{CENSUS}/{flow}/hs"
    val_col = "GEN_VAL_MO" if flow == "imports" else "ALL_VAL_MO"
    comm_col = "I_COMMODITY" if flow == "imports" else "E_COMMODITY"
    params = {
        "get": f"{val_col},CTY_CODE,{comm_col},time",
        "CTY_CODE": country_code,
        "COMM_LVL": "HS" + str(len(hs)),
        "time": f"from {start} to {end}",
        comm_col: hs,
    }
    if key:
        params["key"] = key
    r = requests.get(base, params=params, timeout=120)
    r.raise_for_status()
    rows = r.json()
    df = pd.DataFrame(rows[1:], columns=rows[0])
    df["value"] = pd.to_numeric(df[val_col], errors="coerce")
    df["month"] = pd.to_datetime(df["time"], errors="coerce")
    return df.dropna(subset=["month"]).sort_values("month")


def shift_around(df, event_date, window_months=12):
    # Compare mean monthly trade in the window before vs. after an
    # action date (a sanction or an export-enforcement order).
    ev = pd.Timestamp(event_date)
    before = df[(df.month < ev) &
                (df.month >= ev - pd.DateOffset(months=window_months))]
    after = df[(df.month >= ev) &
               (df.month < ev + pd.DateOffset(months=window_months))]
    b, a = before.value.mean(), after.value.mean()
    pct = (a - b) / b * 100 if b else float("nan")
    print(f"  before: ${b:,.0f}/mo   after: ${a:,.0f}/mo   "
          f"change: {pct:+.1f}%")
    return b, a


# Example: US exports of an HS chapter to a country, around an action date.
exp = census_trade("exports", "5520", "85", "2020-01", "2024-12")
print(f"Months pulled: {len(exp)}   "
      f"total exports: ${exp.value.sum():,.0f}")
shift_around(exp, "2022-03-01")    # overlay the sanctions / BIS action date

Two practical notes apply. First, the before-and-after comparison is a blunt first pass: a real causal reading must account for the general trend in trade with the country, for seasonality, and for confounding events in the same window, ideally by comparing the sanctioned country against a control group of similar unsanctioned trading partners over the same period. The Census time series supplies everything needed to build that difference-in-differences design; the script leaves it as the natural next step. Second, the transshipment extension is a small addition—run the same census_trade pull for each plausible intermediary country and watch which third-country flows of the controlled HS code rise as the direct route falls. For national-scale work spanning many countries and commodities, the Census bulk downloads and the Consolidated Screening List and BIS bulk files are far more efficient than thousands of paginated API calls.

Limitations and analytical caveats

The joined trade-control datasets are uniquely powerful, but the joins are approximations, and every conclusion drawn from them inherits the weakest link in the chain.

Party-name matching is the hardest and least reliable join.Linking an OFAC designation, a BIS respondent, and a real-world counterparty rests on names, aliases, and transliterations that vary across languages and scripts, that change as shell companies are spun up and dissolved, and that are deliberately obscured by parties trying to evade controls. Exact string matching misses true links; loose fuzzy matching invents false ones. Serious screening uses purpose-built name-matching with transliteration and alias handling and treats every match as a candidate for human review, never as a settled fact. Any analysis that joins these datasets on party names should report the matching method and its error characteristics, not just the result.

Commodity classification does not line up cleanly. The Harmonized System that organizes the trade data and the Export Control Classification Numbers that organize the controls are different taxonomies built for different purposes, and the enforcement record describes goods in prose. Mapping a controlled technology onto HS codes is inherently lossy: a single HS line can contain both controlled and uncontrolled items, and a single controlled item can span HS lines. Work at the chapter or heading level, treat the commodity join as indicative, and resist reporting it as if it were a precise measurement of controlled-goods trade.

The trade statistics measure recorded trade, not all trade.Census captures what is documented to CBP. Smuggling, undervaluation, and misclassification are by their nature under-counted—and they are exactly the behaviors that controls provoke. A drop in recorded trade with a sanctioned country may reflect a genuine fall, a shift into transshipment that the recorded data attributes to a third country, or a move into channels the statistics never see. Recorded trade is the floor of the true flow, not the flow itself, and the gap is largest precisely where the controls bite hardest.

Timing and reporting lags differ across the three. The Census statistics are revised after initial release and are reported monthly with a lag; sanctions take effect on a designation date but their economic impact builds over months as counterparties adjust; enforcement actions are dated to the settlement or order, which can fall years after the underlying conduct. Aligning the three on a single timeline requires keeping straight which date each event carries—designation versus conduct versus settlement—and accepting that the most recent months in every series are the least settled. Held with these limits in mind, the join of ofac_sanctions, bis_export_enforcement, and census_foreign_trade is the clearest public view of US trade controls and the trade they govern: the rules, the violations, and the goods that move, finally read in one frame.

Related writing

OFAC Sanctions Lists: The Treasury Database Every Financial Institution Must Screen Against — The party and country side of this join in full: the SDN list, the consolidated screening list, the sanctions-program codes, and the name-and-alias screening that supplies the country and party keys used here.

BIS Export Enforcement: The Federal Database Behind US Export Control Violations — The violations side in detail: the Export Administration Regulations, the Entity List, and the enforcement record that carries the respondent, destination, commodity, and penalty fields this article joins to the trade data.

Census Foreign Trade Statistics: The HS-Code Import and Export Database Behind Every US Trade Policy Decision — The flows side: how the Harmonized System organizes the import and export statistics by commodity, country, and port, and how the international-trade API delivers the time series that the sanctions and enforcement dates are overlaid on.