# Jones Act Waiver Tracker 

---

Documenting domestic cargo movements under the 
**March 17, 2026-November 15, 2026 waiver**

**On March 17, 2026, the Department of Homeland Security issued** [**the longest and broadest waiver of the Jones Act since at least 1950**](https://www.cato.org/commentary/defenders-jones-act-have-lost)**.** Using official government data provided by the US Maritime Administration, this interactive dashboard tracks the economic activity that has emerged since the waiver was issued. As [explained here](https://www.cato.org/blog/jones-act-waiver-has-moved-more-energy-official-numbers-show), however, **this data is not comprehensive and should be considered a floor** for the quantity of cargo moved under the waiver.

#### Additional context 

In nonwaiver times, the [Jones Act](http://cato.org/jonesact) restricts the transportation of cargo between US ports to vessels that are American-built, American-flagged, American-owned, and American-crewed. When the government determines that compliant vessels are unavailable or insufficient to meet national defense needs, it may issue emergency waivers allowing foreign-flagged ships to carry domestic cargo.

The March 17 waiver initially covered energy commodities and fertilizer inputs across [619 unique HTS product categories](https://content.govdelivery.com/accounts/USDHSCBP/bulletins/40f1204), including crude oil, refined petroleum products, natural gas, coal, ammonia, and fertilizers. The 60-day waiver was set to expire May 17, 2026, and was extended for 90 days through August 16. On August 13, 2026, DHS issued a second 90-day extension, through November 15, 2026, alongside a revised list [covering 228 categories](https://content.govdelivery.com/accounts/USDHSCBP/bulletins/424c996) that removed coal and most non-fuel industrial chemicals while adding soybean oil and fuel ethanol.

Operators using the waiver must file voyage reports with the US Maritime Administration (MARAD), which publishes them [on its website](https://www.maritime.dot.gov/ports/domestic-shipping/domestic-shipping). The tracker above is built from those reports. Each voyage on the map is a domestic cargo movement that would have been unlawful had the Jones Act’s restrictions not been temporarily waived.

Under the original waiver, operators notified CBP after a voyage was already underway or completed. Beginning with the August 13 extension, operators must instead [submit a written request](https://content.govdelivery.com/bulletins/gd/USDHSCBP-424c996?wgt_ref=USDHSCBP_WIDGET_2) to DHS, MARAD, and CBP *before* a voyage, triggering a MARAD survey of coastwise-qualified US vessels. DHS then determines whether the foreign vessel is authorized or a domestic vessel must be used instead. That pre-voyage request and survey are not published, so the tracker — built from post-voyage reports — does not capture voyages that were requested and denied in favor of a US-flagged vessel.

body { margin: 0; } 

import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@5/dist/runtime.js";
import define from "https://api.observablehq.com/d/3a87558830e6537f.js?v=4";
new Runtime().module(define, name => {
if (name === "viewof dashboard") return new Inspector(document.querySelector("#observablehq-viewof-dashboard-948ed421"));
});

// Report content height to the parent whenever it changes.
function sendHeight() {
parent.postMessage(
{ type: "observable-embed-height", height: document.documentElement.scrollHeight },
"*"
);
}
new ResizeObserver(sendHeight).observe(document.body);
window.addEventListener("load", sendHeight);

## Key Findings

- **The Gulf Coast to West Coast fuel trade springs to life**: In the waiver’s first 50 days, foreign-flagged tankers moved approximately 1.59 million barrels of energy products (excluding renewable diesel) from the Gulf Coast to the West Coast, which is roughly four times the volume moved by water on that route in all of 2025. In the waiver’s first 70 days, more gasoline and jet fuel [were moved](https://x.com/cpgrabow/status/2059273368948428967) from the Gulf Coast to the West Coast than in the entirety of 2020–2025.
- **Puerto Rico purchases US propane**: No liquefied petroleum gas (LPG) tankers exist in the Jones Act fleet. As a result, Puerto Rico had been effectively barred from bulk US propane purchases and was forced to import from [distant sources](https://x.com/cpgrabow/status/1868670472680083959). The waiver opened the global LPG fleet to domestic routes, allowing bulk propane to reach Puerto Rico from the US mainland for the first time.
- **Ammonia reaches American farmers**: Three voyages have carried anhydrous ammonia — a fertilizer and key precursor to other fertilizers — aboard LPG tankers.
- **Crude reaches Pennsylvania**: The waiver’s first 60 days saw four movements of crude oil, both Bakken oil and West Texas Intermediate, from Texas to the East Coast. In 2017, the CEO of a Jones Act tanker company [acknowledged](https://www.ft.com/content/b1ea86dc-ade6-11e7-aab9-abaa44b1e130) that without the law, “there probably would be more movements of crude oil from Texas to Philadelphia.” The waiver has borne that out.
- **Foreign vessels have supplemented, not replaced, the Jones Act fleet**: With the Jones Act tanker fleet [fully employed](https://jonesacttankertracker.com/), each foreign-flagged voyage represents demand that would otherwise have gone unmet.

(function () {
var SCRIPT = document.currentScript; // captured synchronously

function mount(node) {
if (SCRIPT && SCRIPT.parentNode) SCRIPT.parentNode.insertBefore(node, SCRIPT);
else document.body.appendChild(node);
}

(async function () {
var SHEET_ID = "1P6MDZYvjLlH5xu8YibvniiCjv9Fkm1tVSRCrpIL8lKo";
var GID = 0;
var PAD = 24; // right padding (px)
var PADL = 12; // left padding (px) — smaller so the arrow sits evenly in the corner

// ---- fetch ----
const res = await fetch(
`https://docs.google.com/spreadsheets/d/${SHEET_ID}/export?format=csv&gid=${GID}`);
if (!res.ok) throw new Error(`Sheet fetch failed: ${res.status} ${res.statusText}`);
const text = await res.text();
if (text.trim().startsWith("<"))
throw new Error("Sheet returned HTML, not CSV — set sharing to 'Anyone with the link'.");

// ---- minimal CSV parser (quoted fields, embedded commas + newlines) ----
function parseCSV(str) {
const rows = []; let row = [], f = "", q = false;
for (let i = 0; i < str.length; i++) {
const c = str[i];
if (q) { if (c === '"') { if (str[i + 1] === '"') { f += '"'; i++; } else q = false; } else f += c; }
else if (c === '"') q = true;
else if (c === ",") { row.push(f); f = ""; }
else if (c === "\r") { /* skip */ }
else if (c === "\n") { row.push(f); rows.push(row); row = []; f = ""; }
else f += c;
}
if (f.length || row.length) { row.push(f); rows.push(row); }
const h = rows.shift().map(x => x.trim());
return rows
.filter(r => r.length > 1 || (r.length === 1 && r[0].trim() !== ""))
.map(r => Object.fromEntries(h.map((k, i) => [k, r[i] ?? ""])));
}

// ---- state + port extraction ----
const STATES = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado",
"Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana",
"Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan",
"Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire",
"New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma",
"Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee",
"Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming",
"District of Columbia","Puerto Rico","Guam","Bahamas"];
const STSET = new Set(STATES);
const norm = (s) => String(s ?? "").replace(/\s+/g, " ").trim();

// earliest known state name in the field (handles "A / B" + trailing junk)
const deriveState = (field) => {
const s = norm(field);
let best = null, bp = Infinity, bl = 0;
for (const st of STATES) {
const i = s.indexOf(st);
if (i !== -1 && (i < bp || (i === bp && st.length > bl))) { best = st; bp = i; bl = st.length; }
}
return best;
};
// primary (first) port of an endpoint, as a bare city label
const portCanon = (field) => {
const state = deriveState(field);
let seg = norm(field).split(" / ")[0].split(" via ")[0].replace(/\s*\(.*$/, "").trim();
let parts = seg.split(",").map(p => p.trim()).filter(Boolean);
if (parts.length && STSET.has(parts[parts.length - 1])) parts = parts.slice(0, -1);
const city = parts.join(", ").trim();
return { state, label: (city || state || seg) };
};

// ---- aggregate ----
// State rows: route crosses the state line => import for the arrival state,
// export for the departure state; same state => intra.
// Port rows: a route arriving at a port => import there, departing => export,
// loaded & discharged at the same port => intra.
const states = new Map();
const portsByState = new Map();
const esf = (s) => { if (!states.has(s)) states.set(s, { state: s, import: 0, export: 0, intra: 0 }); return states.get(s); };
const epf = (s, p) => {
if (!portsByState.has(s)) portsByState.set(s, new Map());
const m = portsByState.get(s);
if (!m.has(p)) m.set(p, { label: p, import: 0, export: 0, intra: 0 });
return m.get(p);
};
for (const r of parseCSV(text)) {
const L = portCanon(r.load_port), U = portCanon(r.unload_port);
if (!L.state || !U.state) continue;
if (L.state === U.state) esf(L.state).intra++;
else { esf(L.state).export++; esf(U.state).import++; }
if (L.label === U.label && L.state === U.state) epf(L.state, L.label).intra++;
else { epf(L.state, L.label).export++; epf(U.state, U.label).import++; }
}
const total = (d) => d.import + d.export + d.intra;
const byTotal = (a, b) => total(b) - total(a) || a.label.localeCompare(b.label);
const stateRows = [...states.values()]
.sort((a, b) => total(b) - total(a) || a.state.localeCompare(b.state));

// Size the name column to the widest label across ALL rows — including
// ports inside collapsed states — so the width is fixed and doesn't shift
// when states expand/collapse. Measured with the actual font.
// ---- render ----
const root = document.createElement("div");
root.className = "srt";
root.innerHTML = `<style>
.srt { font: 18px/1.4 "Inter", system-ui, sans-serif; color: #222; width: 680px; max-width: 100%; box-sizing: border-box; padding: 0; margin: 0 auto; container-type: inline-size; }
.srt.srt-head,.srt.srt-state,.srt.srt-port {
display: grid; grid-template-columns: minmax(0, 1fr) 76px 76px 76px; column-gap: 8px; align-items: center;
}
.srt.srt-head {
color: #555; padding: 0 ${PAD}px 6px ${PADL}px; border-bottom: 2px solid #999;
}
.srt.srt-head.n,.srt.num { text-align: right; font-variant-numeric: tabular-nums; padding-right: 6px; }
.srt.srt-head.n { font-weight: 700; }
.srt.srt-group { position: relative; }
.srt.srt-state {
cursor: pointer; user-select: none; padding: 7px ${PAD}px 7px ${PADL}px; border-bottom: 1px solid #ececec;
}
.srt.srt-group.open.srt-state { border-bottom: none; }
.srt.name { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.srt.chevron { width: 14px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
line-height: 0; transition: transform 0.15s ease; transform: rotate(-135deg); }
.srt.chevron svg { width: 8px; height: 8px; stroke: #555; stroke-width: 1.5;
stroke-linecap: square; fill: none; }
.srt.srt-group.open.chevron { transform: rotate(-45deg); }
.srt.st-name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.srt.srt-ports {
display: none; background: #fbfbfb; margin: 6px 0; border-radius: 2px; padding: 6px 0;
box-shadow: inset 0 4px 6px -4px rgba(0,0,0,0.18), inset 0 -2px 4px -3px rgba(0,0,0,0.10);
}
.srt.srt-group.open.srt-ports { display: block; }
.srt.srt-port { padding: 3px ${PAD}px 3px ${PADL}px; }
.srt.srt-port.name { padding-left: 42px; }
.srt.srt-port.p-name { color: #444; min-width: 0; overflow-wrap: anywhere; }
.srt.zero { color: #cfcfcf; }
.srt.srt-foot {
display: grid; grid-template-columns: minmax(0, 1fr) 76px 76px 76px; column-gap: 8px;
font-weight: 600; padding: 7px ${PAD}px 0 ${PADL}px; border-top: 2px solid #999;
}
.srt.srt-foot.num { text-align: right; font-variant-numeric: tabular-nums; }
.srt.srt-head.n.abbr { display: none; }
@container (max-width: 400px) {
.srt.srt-head,.srt.srt-state,.srt.srt-port,.srt.srt-foot {
grid-template-columns: minmax(0, 1fr) 44px 44px 44px;
}
.srt.srt-head.n.full { display: none; }
.srt.srt-head.n.abbr { display: inline; }
}
`;

const head = document.createElement("div");
head.className = "srt-head";
head.innerHTML = `<span>State / port` +
`<span class="n"><span class="full">Import<span class="abbr">Im` +
`<span class="n"><span class="full">Export<span class="abbr">Ex` +
`<span class="n"><span class="full">Intra<span class="abbr">In`;
root.appendChild(head);

const num = (v) => `<span class="num${v === 0 ? " zero" : ""}">${v}`;
const chevronSVG = `<span class="chevron"><svg viewBox="0 0 10 10"><path d="M 2 1 L 2 8 L 9 8"/>`;

const rowsWrap = document.createElement("div");
rowsWrap.className = "srt-rows";

for (const s of stateRows) {
const group = document.createElement("div");
group.className = "srt-group";

const header = document.createElement("div");
header.className = "srt-state";
header.innerHTML =
`<span class="name">${chevronSVG}<span class="st-name">${s.state}` +
num(s.import) + num(s.export) + num(s.intra);

const ports = document.createElement("div");
ports.className = "srt-ports";
const plist = [...portsByState.get(s.state).values()].sort(byTotal);
ports.innerHTML = plist.map(p =>
`<div class="srt-port"><span class="name"><span class="p-name">${p.label}` +
num(p.import) + num(p.export) + num(p.intra) + `

` ).join(""); header.addEventListener("click", () =&gt; group.classList.toggle("open")); group.appendChild(header); group.appendChild(ports); rowsWrap.appendChild(group); } root.appendChild(rowsWrap); const sum = (k) =&gt; stateRows.reduce((t, d) =&gt; t + d[k], 0); const foot = document.createElement("div"); foot.className = "srt-foot"; foot.innerHTML = `Total` + `${sum("import")}${sum("export")}${sum("intra")}`; root.appendChild(foot); mount(root); })().catch(function (err) { var e = document.createElement("div"); e.style.cssText = "font:14px system-ui,sans-serif;color:#b00;"; e.textContent = "Routes table failed to load: " + (err &amp;&amp; err.message ? err.message : err); mount(e); }); })(); 

#### Further Reading 

[![oil tanker jones](/sites/cato.org/files/styles/content_teaser/public/2023-12/oil%20tanker%20ship%203.jpg?itok=mTjhW5dW)](https://www.cato.org/blog/jones-act-waiver-unlocks-new-trade-routes) 

blog 

### [Jones Act Waiver Unlocks New Trade Routes](/blog/jones-act-waiver-unlocks-new-trade-routes) 

By [Colin Grabow](https://www.cato.org/people/colin-grabow) 

Since a Jones Act waiver took effect in March, foreign-flagged tankers have carried cargo on at least six domestic routes without precedent in twenty years of shipping data

[![Jones Act Reform Project Page Hover Card](/sites/cato.org/files/styles/content_teaser/public/2025-02/GettyImages-2153829073.jpg?itok=8Xj8cJCF)](https://www.cato.org/commentary/defenders-jones-act-have-lost) 

Commentary 

### [Defenders of the Jones Act Have Lost](/commentary/defenders-jones-act-have-lost) 

By [Scott Lincicome](https://www.cato.org/people/scott-lincicome) 

For more than a century, the Jones Act has survived on purported economic and security grounds.

[![What to Expect on Trade Policy in the Biden Administration](/sites/cato.org/files/styles/content_teaser/public/2021-03/sponsor-ebriefing-trade-biden.jpg?itok=rtAKa6jQ)](https://www.cato.org/commentary/protectionism-steroids) 

Commentary 

### [Protectionism on Steroids](/commentary/protectionism-steroids) 

By [Colin Grabow](https://www.cato.org/people/colin-grabow) 

The case for dumping the Jones Act into the ashcan of history is a no-brainer.