How to force the browser to download remote resource

Monday, April 5, 2021
2 min read

In a recent project, I needed to offer the ability to download files. Until recently I wasn't aware of the property. I'll explain how to use the download property and why this wouldn't work for my situation.

First though, here is a link to the repository and demo:

Using the HTML5 download property

By default, anchor elements will navigate to the href element. You can add the download property which will prompt the browser to download the file:

<a download href="">
  Download image

However, images and also Firefox only allows users to download files of the same origin. As the files for my project would be served from a different origin I would need a way to force the download.

Using fetch to download

My solution was to use fetch to get the remote resource:

const file = await fetch(*URL_TO_REMOTE_RESOURCE*);

const blob = await file.blob();
const url = URL.createObjectURL(blob);

Once the resource is downloaded, create an anchor element with the download and trigger the click event:

const downloadLink = document.createElement("a");

downloadLink.href = linkSource; = [download name];;

Here's the complete code:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>dlw download as data demo</title>
    <link rel="stylesheet" href="./build/tailwind.css" />
  <body class="bg-gray-900 h-full">
    <main class="min-h-screen flex flex-col justify-center py-12 sm:px-6 lg:px-8">
      <div class="max-w-3xl mx-auto flex flex-col items-center space-y-2">
        <div class="aspect-w-3 aspect-h-2 w-96">
            class="object-fill shadow-lg rounded-lg"
            alt="Star shot in Cathedral Valley State Park, Nevada"
          class="inline-flex items-center mt-4 px-6 py-3 border border-transparent shadow-sm text-base font-medium rounded-md text-white bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500"
            class="ml-2 w-6 h-6"
            viewBox="0 0 20 20"
              d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"

    <script defer type="text/javascript">
      const a = document.querySelector('a[data-remote]')

      a.addEventListener('click', async (e) => {

        const file = await fetch(;

        const blob = await file.blob();

        const blobUrl = URL.createObjectURL(blob);

        const downloadLink = document.createElement("a");
        downloadLink.href = blobUrl; = 'download-example.jpg';;

Find me on