Which Safari version first introduced fetch duplex support, and can we detect it programmatically before concurrent uploads?
0 reputation · 27 Aug 2026, 07:00 UTC
0 reputation · 27 Aug 2026, 07:00 UTC
Determine how to programmatically detect whether Safari’s Fetch API will support request streaming (duplex: 'half') when issuing multiple concurrent uploads, rather than relying on ad‑hoc try/catch behavior.
Safari currently throws or falls back when a ReadableStream body is used with duplex: 'half'. No documented navigator property or feature flag exposes this capability, and the only detection method is a try/catch around the fetch call. The support is version‑sensitive, and edge cases may cause false positives or negatives.
duplex: 'half' in the Fetch API?fetch(url, {method:'POST', body:..., duplex:'half'}) reliably indicate support, or are there known edge cases that cause false positives or negatives?The first Safari release that accepted duplex: 'half' with a ReadableStream body was Safari 16.1 (released in 2023). Prior to 16.1, the call throws a TypeError immediately, preventing concurrent uploads.
duplex: 'half'.navigator property, feature flag, or API that exposes this capability.async function supportsDuplexHalf() {
// Create a minimal ReadableStream that yields nothing
const stream = new ReadableStream({ start(controller) { controller.close(); } });
try {
await fetch('https://example.com/placeholder', {
method: 'POST',
body: stream,
duplex: 'half',
});
return true; // No exception => Safari 16.1+ (or other browsers that support it)
} catch (e) {
// Safari 16.0 or earlier will throw a TypeError
return false;
}
}
supportsDuplexHalf().then(isSupported => {
console.log('duplex: half supported:', isSupported);
});
duplex: 'half' with a ReadableStream; it does not guarantee success under all network conditions.Use the supportsDuplexHalf helper before initiating any concurrent uploads. If it returns false, fall back to a non‑streaming upload strategy (e.g., FormData or Blob).
If you’re unsure about the Safari version your users are on, consider logging navigator.userAgent during the detection step. That extra data can help troubleshoot unexpected failures.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.