Atlantic

Global Storms
Loading active storms worldwide…
'; return; } var itemsHtml = storms.map(function(s){ return ( '' + '' + '' + escapeHtml(s.name) + '' + '' + escapeHtml(s.location) + '' + '' + s.windMph + ' mph' + '' + escapeHtml(s.catAbbr) + '' + '' ); }).join(''); // Duplicate the sequence so the scrolling loop is seamless at -50% translateX. viewport.innerHTML = '
' + itemsHtml + itemsHtml + '
'; } function renderError(){ viewport.innerHTML = '
Live storm ticker unavailable right now — check ' + 'nhc.noaa.gov or ' + 'gdacs.org directly.
'; } function load(){ fetch(FEED_URL, { cache: 'no-store' }) .then(function(r){ if (!r.ok) throw new Error('bad status'); return r.json(); }) .then(function(data){ var features = (data && data.features) || []; var storms = features .filter(function(f){ var p = f.properties || {}; return p.eventtype === 'TC' && String(p.iscurrent) === 'true'; }) .map(function(f){ var p = f.properties; var lon = f.geometry && f.geometry.coordinates ? f.geometry.coordinates[0] : 0; var lat = f.geometry && f.geometry.coordinates ? f.geometry.coordinates[1] : 0; var kmh = p.severitydata && p.severitydata.severity ? p.severitydata.severity : 0; var mph = Math.round(kmh * 0.621371); var cat = categoryFor(mph); var location = p.country && p.country.trim() ? p.country.trim() : basinFromCoords(lon, lat); return { id: p.eventid, name: cleanName(p.eventname), location: location, windMph: mph, color: cat.color, catAbbr: cat.abbr, catLabel: cat.label, reportUrl: (p.url && p.url.report) || 'https://www.gdacs.org/' }; }) .sort(function(a, b){ return b.windMph - a.windMph; }); render(storms); updatedEl.textContent = 'Updated ' + fmtAgo(new Date()); }) .catch(function(){ renderError(); updatedEl.textContent = ''; }); } load(); setInterval(load, REFRESH_MS); })();

Atlantic Hurricane News brings you the latest tropical storm updates, hurricane forecasts and development outlooks across the Atlantic basin.

Orbis Weather — Atlantic Basin
Orbis Weather · Tropical Center

🌀 Atlantic Basin

Live hurricane tracking, tropical activity, satellite imagery, weather, sea temperatures, waves and buoy observations across the Atlantic, Caribbean and Gulf.

LIVE DATA · --:-- UTC
Active tropical cyclones
NHCOfficial outlook source
GOES-19Atlantic satellite
8NOAA buoys monitored

⚠️ Atlantic Tropics Right Now

NHC 7-Day Outlook
Checking live Atlantic tropical cyclone activity…
Areas to watch
Highest 2-day formation chance
Highest 7-day formation chance

🌀 Atlantic Basin Storm Tracker

Live tropical cyclones · click a storm for track/cone

🌀 Atlantic Basin Storm Tracker

Live tropical cyclones across the Atlantic, Caribbean and Gulf. Drag to pan, Ctrl/⌘+scroll to zoom, and click a storm to show its track and cone.

Use Ctrl + scroll (⌘ + scroll on Mac) to zoom the map
Connecting…
Intensity
Tropical Depression
Tropical Storm
Category 1
Category 2
Major Cat 3
Category 4
Category 5
No active tropical cyclones in the Atlantic Basin right now.
Live storm data unavailable right now — check the National Hurricane Center directly.
Loading live storm map…

🛰️ NOAA/NHC Hurricane Tracker

Official forecast tracks & cones
Official NOAA/NHC forecast information, opened to an Atlantic-focused view. The cone represents the probable path of the storm center, not the full extent of hazardous weather.

🛰️ GOES-19 Tropical Atlantic Satellite

GeoColor · refreshing
GOES-East GeoColor imagery from NOAA/NESDIS/STAR. Daytime imagery approximates natural color; nighttime imagery uses multispectral infrared.

🌦️ Atlantic Live Weather Map

Windy · ECMWF
Use the layer controls inside the map to switch among rain, wind, temperature, clouds and other weather layers.

🌊 Atlantic Coast Sea Temperatures

NOAA CO-OPS · loading

🌊 Atlantic Waves & Swell

Windy · ECMWF
Basin-wide waves and swell view. Use the map menu to switch wave height, swell and wind layers. Some model tiles can briefly show unavailable data during model updates.

⚓ NOAA Buoy Conditions

NDBC · loading
Significant wave height combines swell and wind waves. Always use official NWS/NHC marine forecasts for safety decisions.
'; return; } list.innerHTML=unique.map(function(r,i){ var probs=[]; if (r.p2 !== null) probs.push("2-day: "+r.p2+"%"); if (r.p7 !== null) probs.push("7-day: "+r.p7+"%"); return '
Area '+(i+1)+(r.name && r.name!=="Disturbance" ? " · "+r.name : "")+''+ '
'+probs.join(" · ")+'
'+ (r.desc ? '
'+r.desc.slice(0,240)+'
' : '')+'
'; }).join(""); } async function refreshNHCOutlook() { var checked = new Date(); document.getElementById("owOutlookChecked").textContent = "NHC 7-Day Outlook · checked " + checked.toUTCString().split(" ")[4] + " UTC"; // Bust cache on the official outlook image. var outlookImg = document.getElementById("owNHCOutlookImg"); outlookImg.removeAttribute("src"); outlookImg.src = "https://www.nhc.noaa.gov/xgtwo/two_atl_7d0.png?cb=" + Date.now(); try { var url="https://www.nhc.noaa.gov/xgtwo/xgtwo_atl.json?_="+Date.now(); var res=await fetch(url,{cache:"no-store"}); if (!res.ok) throw new Error("NHC HTTP "+res.status); var json=await res.json(); var rows=[]; collectCandidates(json,rows,new WeakSet()); renderNHCOutlook(rows); } catch(e) { // Some WordPress/browser setups block the NHC JSON endpoint with CORS. // Try the official text outlook as a second source. If it explicitly says // no formation is expected, we can safely show 0 / 0% / 0%. try { var textUrl="https://www.nhc.noaa.gov/text/refresh/MIATWOAT+shtml/?_="+Date.now(); var txtRes=await fetch(textUrl,{cache:"no-store"}); if (!txtRes.ok) throw new Error("NHC text HTTP "+txtRes.status); var txt=await txtRes.text(); var quiet=/tropical cyclone formation is not expected during the next 7 days/i.test(txt) || /no new tropical cyclones are expected during the next seven days/i.test(txt); if (quiet) { var dCard=document.getElementById("owDisturbances").parentElement; var p2Card=document.getElementById("owHigh2").parentElement; var p7Card=document.getElementById("owHigh7").parentElement; dCard.style.display=""; p2Card.style.display=""; p7Card.style.display=""; dCard.style.gridColumn=""; document.getElementById("owDisturbances").textContent="0"; document.getElementById("owHigh2").textContent="0%"; document.getElementById("owHigh7").textContent="0%"; document.getElementById("owWatchList").innerHTML= '
No development areas
NHC indicates tropical cyclone formation is not expected during the next 7 days.
'; } else { throw new Error("Text outlook does not explicitly indicate quiet conditions"); } } catch(e2) { // If the machine-readable NHC feeds are blocked by the browser, avoid // showing three oversized "See map" cards. Collapse the probability // area into a simple quiet-basin status while keeping the official // NHC 7-day graphic directly below as the authoritative source. document.getElementById("owDisturbances").textContent="0"; document.getElementById("owHigh2").textContent="—"; document.getElementById("owHigh7").textContent="—"; document.getElementById("owDisturbances").parentElement.querySelector("span").textContent="Areas to watch"; document.getElementById("owHigh2").parentElement.style.display="none"; document.getElementById("owHigh7").parentElement.style.display="none"; document.getElementById("owDisturbances").parentElement.style.gridColumn="1 / -1"; document.getElementById("owDisturbances").parentElement.innerHTML= 'No DisturbancesAtlantic Basin Quiet · See the official NHC 7-day outlook below'; document.getElementById("owWatchList").innerHTML=""; } } } refreshNHCOutlook(); setInterval(refreshNHCOutlook, 30*60*1000); // Sea temperatures var seaStations=[ ['8418150','Portland','ME',43.6564,-70.2483],['8452660','Newport','RI',41.5045,-71.3262], ['8518750','The Battery (NYC)','NY',40.7006,-74.0142],['8534720','Atlantic City','NJ',39.3561,-74.4183], ['8557380','Lewes','DE',38.7828,-75.1193],['8638610','Sewells Point','VA',36.9428,-76.3286], ['8658120','Wilmington','NC',34.2267,-77.9533],['8670870','Fort Pulaski','GA',32.0347,-80.9030], ['8721604','Port Canaveral','FL',28.4158,-80.5931],['8723214','Virginia Key','FL',25.7314,-80.1618], ['8724580','Key West','FL',24.5557,-81.8079] ]; function f2c(f){return (f-32)*5/9} function tcolor(f){if(f<55)return'#104281';if(f<60)return'#184f95';if(f<65)return'#2a78d6';if(f<70)return'#9ec5f4';if(f<75)return'#ddd8cb';if(f<80)return'#eda9a8';if(f<85)return'#e34948';return'#b23332'} async function seaRefresh(){ var results=await Promise.all(seaStations.map(async s=>{ try{ var u='https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?product=water_temperature&application=OrbisWeather&station='+s[0]+'&date=latest&units=english&time_zone=lst_ldt&format=json'; var b=await (await fetch(u)).json(); var v=b.data&&b.data[0]?parseFloat(b.data[0].v):NaN; return [s,v,b.data&&b.data[0]?b.data[0].t:'']; }catch(e){return[s,NaN,'']} })); var ok=0; document.getElementById('owSeaCards').innerHTML=results.map(x=>{ var s=x[0],v=x[1]; if(!isNaN(v))ok++; var col=isNaN(v)?'#b8c0c5':tcolor(v); return '
'+s[1]+''+s[2]+'
'+(isNaN(v)?'—':v.toFixed(1)+'°F')+'
'+(isNaN(v)?'No live reading':f2c(v).toFixed(1)+'°C · '+x[2])+'
'; }).join(''); document.getElementById('owSeaMeta').textContent=ok+' / '+seaStations.length+' stations reporting'; } seaRefresh(); setInterval(seaRefresh,5*60*1000); // NDBC buoys var buoys=[['44027','Mount Desert Rock','ME'],['44025','Long Island','NY'],['44009','Delaware Bay','DE'],['44014','Virginia Beach','VA'],['41013','Frying Pan Shoals','NC'],['41004','Edisto','SC'],['41008','Grays Reef','GA'],['41009','Canaveral','FL']]; function compass(d){var a=['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW'];return a[Math.round(d/22.5)%16]} async function buoyRefresh(){ try{ var txt=await (await fetch('https://www.ndbc.noaa.gov/data/latest_obs/latest_obs.txt')).text(), by={}; txt.split('\n').forEach(line=>{ if(!line||line[0]==='#')return; var c=line.trim().split(/\s+/); if(c.length<19)return; by[c[0]]={wdir:c[8]==='MM'?null:+c[8],wspd:c[9]==='MM'?null:+c[9],wvht:c[11]==='MM'?null:+c[11],dpd:c[12]==='MM'?null:+c[12],mwd:c[14]==='MM'?null:+c[14],time:c[3]+'-'+c[4]+'-'+c[5]+' '+c[6]+':'+c[7]+' UTC'}; }); var ok=0; document.getElementById('owBuoyCards').innerHTML=buoys.map(s=>{ var o=by[s[0]], ft=o&&o.wvht!=null?o.wvht*3.28084:NaN; if(!isNaN(ft))ok++; var detail=''; if(o&&o.dpd!=null)detail+=o.dpd.toFixed(0)+'s period'+(o.mwd!=null?' · '+compass(o.mwd):''); if(o&&o.wspd!=null)detail+=(detail?' · ':'')+'Wind '+(o.wspd*1.94384).toFixed(0)+' kt'+(o.wdir!=null?' '+compass(o.wdir):''); return '
'+s[1]+''+s[2]+'
'+(isNaN(ft)?'—':ft.toFixed(1)+' ft')+'
'+(detail||'No live wave reading')+(o&&o.time?'
'+o.time:'')+'
'; }).join(''); document.getElementById('owBuoyMeta').textContent=ok+' / '+buoys.length+' buoys reporting wave height'; document.getElementById('owBuoyCount').textContent=buoys.length; document.getElementById('owBuoyCount').parentElement.querySelector('span').textContent= ok ? (ok+' of '+buoys.length+' buoys reporting') : (buoys.length+' NOAA buoys monitored'); }catch(e){document.getElementById('owBuoyMeta').textContent='NDBC feed temporarily unavailable'; document.getElementById('owBuoyCount').textContent=buoys.length; document.getElementById('owBuoyCount').parentElement.querySelector('span').textContent=buoys.length+' NOAA buoys monitored';} } buoyRefresh(); setInterval(buoyRefresh,10*60*1000); })();
' + '
' + '
' + s.name + "
"; el.addEventListener("click", (e) => { e.stopPropagation(); toggleTrack(s); }); markersEl.appendChild(el); }); positionMarkers(); } function positionMarkers() { const els = markersEl.querySelectorAll(".marker"); els.forEach((el) => { const s = storms.find((st) => String(st.id) === el.dataset.id); if (!s) return; const [x, y] = project(s.lon, s.lat); el.style.left = x + "px"; el.style.top = y + "px"; }); } // Click a storm to show its forecast track/cone; click it again (or // click empty map space) to hide it. Only one storm's track is shown // at a time. function toggleTrack(s) { if (selectedId === s.id) { clearTrack(); return; } selectedId = s.id; markersEl.querySelectorAll(".marker").forEach((m) => m.classList.toggle("selected", m.dataset.id === String(s.id))); fetchCone(s); scheduleRedraw(); } function clearTrack() { selectedId = null; markersEl.querySelectorAll(".marker").forEach((m) => m.classList.remove("selected")); scheduleRedraw(); } appEl.addEventListener("click", clearTrack); // --------------------------------------------------------------------- // Pan / zoom // --------------------------------------------------------------------- // mousemove/wheel/touchmove can fire far faster than the screen can // repaint, and drawMap() walks every coastline point on every call. // Calling it directly from those handlers is what was making the page // feel like it locked up while dragging or scrolling — coalesce any // number of events per frame into a single redraw via rAF instead. let redrawScheduled = false; function scheduleRedraw() { if (redrawScheduled) return; redrawScheduled = true; requestAnimationFrame(() => { redrawScheduled = false; drawMap(); positionMarkers(); }); } let isDragging = false, dragStart = null, transformStart = null, dragMoved = false; mapCanvas.addEventListener("mousedown", (e) => { isDragging = true; dragMoved = false; appEl.classList.add("grabbing"); dragStart = { x: e.clientX, y: e.clientY }; transformStart = { ...transform }; }); window.addEventListener("mousemove", (e) => { if (!isDragging) return; if (Math.abs(e.clientX - dragStart.x) > 3 || Math.abs(e.clientY - dragStart.y) > 3) dragMoved = true; transform.x = transformStart.x + (e.clientX - dragStart.x); transform.y = transformStart.y + (e.clientY - dragStart.y); scheduleRedraw(); }); window.addEventListener("mouseup", () => { isDragging = false; appEl.classList.remove("grabbing"); }); // A plain scroll over the map must NOT be captured — otherwise a visitor // can never scroll the page past this widget, which is the actual bug // reported. Zooming requires holding Ctrl (or Cmd on Mac), matching how // Google Maps/Leaflet embeds behave inline in a page; a bare scroll just // shows a brief hint and is left alone so the page scrolls normally. let scrollHintTimer = null; function flashScrollHint() { scrollHintEl.classList.add("visible"); clearTimeout(scrollHintTimer); scrollHintTimer = setTimeout(() => scrollHintEl.classList.remove("visible"), 900); } mapCanvas.addEventListener("wheel", (e) => { if (!(e.ctrlKey || e.metaKey)) { flashScrollHint(); return; // do NOT preventDefault — let the page scroll as normal } e.preventDefault(); const zoomFactor = Math.exp(-e.deltaY * 0.0015); const newK = Math.max(0.6, Math.min(8, transform.k * zoomFactor)); const mx = e.clientX, my = e.clientY; transform.x = mx - ((mx - transform.x) / transform.k) * newK; transform.y = my - ((my - transform.y) / transform.k) * newK; transform.k = newK; scheduleRedraw(); }, { passive: false }); let touchState = null; mapCanvas.addEventListener("touchstart", (e) => { if (e.touches.length === 1) { touchState = { mode: "pan", x: e.touches[0].clientX, y: e.touches[0].clientY, t0: { ...transform } }; } else if (e.touches.length === 2) { const [a, b] = e.touches; touchState = { mode: "pinch", dist: Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY), cx: (a.clientX + b.clientX) / 2, cy: (a.clientY + b.clientY) / 2, t0: { ...transform } }; } }, { passive: true }); mapCanvas.addEventListener("touchmove", (e) => { if (!touchState) return; if (touchState.mode === "pan" && e.touches.length === 1) { transform.x = touchState.t0.x + (e.touches[0].clientX - touchState.x); transform.y = touchState.t0.y + (e.touches[0].clientY - touchState.y); scheduleRedraw(); } else if (touchState.mode === "pinch" && e.touches.length === 2) { const [a, b] = e.touches; const dist = Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY); const k = Math.max(0.6, Math.min(8, touchState.t0.k * (dist / touchState.dist))); transform.x = touchState.cx - ((touchState.cx - touchState.t0.x) / touchState.t0.k) * k; transform.y = touchState.cy - ((touchState.cy - touchState.t0.y) / touchState.t0.k) * k; transform.k = k; scheduleRedraw(); } }, { passive: true }); mapCanvas.addEventListener("touchend", () => { touchState = null; }); resetBtn.addEventListener("click", () => { atlanticHomeView(); clearTrack(); }); window.addEventListener("resize", resize); // --------------------------------------------------------------------- // Boot // --------------------------------------------------------------------- resize(); function atlanticHomeView() { // Approximate viewport: 5°N–55°N, 100°W–5°W. const k = 2.55; const center = baseProject(-52.5, 30); transform = { x: cssWidth/2 - center[0]*k, y: cssHeight/2 - center[1]*k, k: k }; scheduleRedraw(); } atlanticHomeView(); const coastlinesReady = fetch("https://unpkg.com/world-atlas@2/countries-110m.json") .then((r) => r.json()) .then((topology) => { landPolygons = topologyToLandPolygons(topology); }) .catch(() => { landPolygons = []; }); const stormsReady = loadStorms(); Promise.all([coastlinesReady, stormsReady]).finally(() => { drawMap(); positionMarkers(); loadingEl.classList.add("hidden"); }); setInterval(loadStorms, REFRESH_MS); })();
ORBIS WEATHER

🌀 ATLANTIC • CARIBBEAN • GULF
LIVE SATELLITE LOOP

Animated GOES-East satellite imagery • Atlantic Basin
LIVE SATELLITE
Preparing loop...
NOAA • NESDIS • STAR • GOES-19
PLAYBACK
LOOP LENGTH
SATELLITE PRODUCT
CLEAN INFRARED
GOES-19 • GOES-East • Full Disk
Loading Atlantic satellite loop...
FRAME 1 / 24
SATELLITE GOES-19
COVERAGE Atlantic Full Disk
LOOP 4 Hours
FRAME Loading
PLAYBACK Fast

Follow Atlantic Hurricane News throughout hurricane season for updates on developing storms, tropical disturbances and potential threats to Florida and the Caribbean.

More Tropical Weather: Follow our Pacific and Western Pacific coverage for the latest tropical cyclone developments around the world.

Planning around the weather? Check our Marco Island & Naples Weather page for the latest local forecast.