Over 900 arrested in South Africa during anti-immigrant protests

Anti-immigrant protesters march on the day of an unofficial deadline set by anti-immigrant groups for all undocumented migrants to leave, in Durban, South Africa, June 30, 2026. PHOTO | REUTERS

Johannesburg. South African police have arrested more than 900 people during nationwide anti-immigrant protests that were largely peaceful but turned violent in some areas, authorities said.

Police said 108 of the 120 protests held across the country passed without incident, while 12 required intervention as isolated cases of violence and looting were reported.

Deputy National Police Commissioner Tebello Mosikili said the arrests were linked to a range of offences, including immigration violations, public violence, harbouring undocumented migrants and robbery.

In Johannesburg’s Alexandra township, one person was shot dead during looting at informal shops known as spaza shops, which are often owned by foreign nationals.

Police also confirmed that reinforcements were deployed in five of South Africa’s nine provinces, while soldiers were sent to parts of Johannesburg, including Hillbrow, where two people were injured in a shooting.

In Durban, police opened an inquest after a foreign national reportedly died after falling from the eighth floor of a building on the eve of the protests. Authorities said he is believed to have jumped in fear during the unrest.

The demonstrations were organised to coincide with a deadline issued by an anti-immigrant movement calling for undocumented migrants to leave the country.

The protests come amid months of rising tensions, during which foreign nationals have faced attacks, including looting of businesses and destruction of property in several areas.

(function () { "use strict"; var thisScript = document.currentScript; var CONFIG = { apiBase: "https://market.mcl.co.tz", brand: "Market", live: "LIVE", labels: { stocks: "Stocks", forex: "Forex", buy: "Buy", sell: "Sell", unavailable: "Market data is currently unavailable.", updated: "Updated", }, majorCurrencies: ["USD", "EUR", "GBP", "KES", "UGX", "ZAR", "JPY", "CNY", "INR", "AED", "CAD", "CHF", "SAR"], refreshMs: 5 * 60 * 1000, pxPerSecond: 55, accent: "#0a66c2", accentRgb: "10, 102, 194", }; // ---------------- STYLE ---------------- var CSS = ` .mcl-ticker{--accent:${CONFIG.accent};--accent-rgb:${CONFIG.accentRgb}; --bg-a:#0b1f3a;--bg-b:#123059;--txt:#fff;--txt-dim:rgba(255,255,255,.62); --up:#2fd07f;--down:#ff5d5d;--flat:#9fb3c8;--h:48px; position:relative;height:var(--h);width:100%;overflow:hidden;display:flex;align-items:stretch; color:var(--txt);background:linear-gradient(90deg,var(--bg-a),var(--bg-b)); border-top:2px solid var(--accent);box-shadow:0 2px 10px rgba(0,0,0,.18); font-size:13.5px;user-select:none; font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial;} .mcl-ticker *{box-sizing:border-box;} .mcl-brand{flex:0 0 auto;display:flex;align-items:center;gap:9px;padding:0 16px; background:rgba(0,0,0,.2);white-space:nowrap;} .mcl-brand-name{font-weight:800;font-size:12px;text-transform:uppercase;} .mcl-live{display:flex;align-items:center;gap:6px;font-size:10px;font-weight:700;color:var(--accent);} .mcl-dot{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:pulse 1.6s infinite;} @keyframes pulse{0%{box-shadow:0 0 0 0 rgba(var(--accent-rgb),.6);}70%{box-shadow:0 0 0 7px rgba(var(--accent-rgb),0);}100%{box-shadow:0 0 0 0 rgba(var(--accent-rgb),0);}} .mcl-viewport{flex:1;overflow:hidden;position:relative;} .mcl-track{position:absolute;display:inline-flex;white-space:nowrap;align-items:center;height:100%;} @keyframes scroll{from{transform:translateX(0);}to{transform:translateX(-50%);}} .mcl-item{display:inline-flex;gap:7px;padding:0 14px;border-right:1px solid rgba(255,255,255,.08);} .mcl-sym{font-weight:700;} .mcl-val{color:var(--txt-dim);} .mcl-chg.up{color:var(--up);} .mcl-chg.down{color:var(--down);} .mcl-chg.flat{color:var(--flat);} .mcl-pill{margin:0 10px;padding:3px 10px;border-radius:999px;background:var(--accent);font-size:10px;font-weight:800;} .mcl-status{padding:0 16px;color:var(--txt-dim);} `; function injectStyle() { if (document.getElementById("mcl-style")) return; var s = document.createElement("style"); s.id = "mcl-style"; s.textContent = CSS; document.head.appendChild(s); } // ---------------- MOUNT ---------------- function getMount() { return document.querySelector(".ticker-data"); } // ---------------- HELPERS ---------------- function toNum(v) { var n = parseFloat(String(v || "").replace(/,/g, "")); return isFinite(n) ? n : null; } function fmt(v) { var n = parseFloat(v); if (!isFinite(n)) return v; return n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } function arrow(d) { if (!d) return "▬"; return d > 0 ? "▲" : "▼"; } function cls(d) { if (!d) return "flat"; return d > 0 ? "up" : "down"; } // ---------------- DATA ---------------- async function fetchFiles(cat) { var r = await fetch(CONFIG.apiBase + "/api/files?category=" + cat); return r.ok ? r.json() : []; } async function load(track) { try { var [stocksFile, forexFile] = await Promise.all([ fetchFiles("hisa"), fetchFiles("fedha"), ]); track.innerHTML = '
Loading...
'; // simplified render (kept minimal for integration) var html = ""; html += 'STOCKS'; html += 'NMB2,450.00▲ 1.2%'; html += 'FOREX'; html += 'USDBuy 2,600 · Sell 2,640▼ 0.4%'; track.innerHTML = html + html; var speed = 50; var dur = Math.max(20, track.scrollWidth / speed); track.style.animation = "scroll " + dur + "s linear infinite"; } catch (e) { track.innerHTML = '
Market data unavailable
'; } } // ---------------- INIT ---------------- function init() { injectStyle(); var mount = getMount(); if (!mount) return; mount.innerHTML = '
' + '
' + '' + CONFIG.brand + '' + 'LIVE' + '
' + '
' + '
Loading...
' + '
' + '
'; var track = mount.querySelector(".mcl-track"); load(track); setInterval(function () { load(track); }, CONFIG.refreshMs); } console.log(CONFIG); if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();