Force iOS Safari (and other browsers) to download media file
💡 How to Force File Downloads in Safari Using JavaScript (JS-Only Solution)
Safari has a mind of its own when it comes to downloading media files. Even if your server correctly sets Content-Disposition: attachment
and Content-Type: application/octet-stream
, Safari might still display files like PDFs, MP4s, or images instead of downloading them.
If you’re a frontend developer looking for a JS-only workaround that actually works, this post is for you.
🧠 Why Safari Ignores Content-Disposition
Safari uses its own internal logic to decide whether to show or download a file. If it recognizes the MIME type (like video/mp4
, application/pdf
, image/jpeg
), it often overrides your server headers and opens the file inline.
That’s frustrating — especially when all you want is a reliable download button.
✅ The Reliable JavaScript Solution
By using the Fetch API to grab the file as a Blob, and then simulating a click on a dynamically created <a>
element with a download
attribute, you can bypass Safari’s preview behavior entirely.
🧪 Code Example
<button id="download-btn">Download File</button>
<script>
function forceDownload(url, filename) {
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.blob();
})
.then(blob => {
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = blobUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(blobUrl);
})
.catch(error => {
console.error("Download failed:", error);
alert("Download failed.");
});
}
document.getElementById("download-btn").addEventListener("click", () => {
// Adjust the URL and filename as needed
forceDownload("/download/video.mp4", "my_video.mp4");
});
</script>
⬅️ Read previous Read next ➡️