DownloadURL is a Chrome-specific, non-standard data transfer type that lets users drag files from web pages directly to their desktop or file manager.

Demo 1: Most basic demo

Try it yourself

Drag the button below to your desktop!
Note: Only works in Chrome/Chromium-based browsers

After dragging the button to your desktop, you should see a file named hello.txt with the content “Hello, world!”.

How it works (source code)
  • The button has the draggable="true" attribute, making it draggable.

  • An ondragstart event handler sets the DownloadURL data transfer item with the format: MIME:filename:URL using the following code:

    <button
      class="btn cursor-grab"
      onclick="alert('Drag me; don\'t click me!')"
      draggable="true"
      ondragstart="
        event.dataTransfer.setData('DownloadURL', [
          'text/plain',
          'hello.txt',
          'data:text/plain,' + encodeURIComponent('Hello, world!')
        ].join(':'))
      "
    >
      hello.txt
    </button>

Demo 2: Drag out a colored square

Try it yourself

Pick a color and drag the canvas to your desktop!
Note: Only works in Chrome/Chromium-based browsers

  1. Drag the square below to your desktop: You should get a file named “color-3498db.png”.
How it works (source code)
  • The canvas has a data-canvas-drag-filename attribute that specifies the filename to use when dragging out the image.

  • A dragstart event listener sets the DownloadURL data transfer item with the format: MIME:filename:URL using the following code:

    function onDragStart(e) {
      if (!e.dataTransfer) return
    
      const canvas = e.target.closest('canvas')
      if (!canvas) return
    
      const filename = canvas.dataset.canvasDragFilename
      if (!filename) return
    
      const dataUrl = canvas.toDataURL()
      e.dataTransfer.clearData()
      e.dataTransfer.setData(
        'DownloadURL',
        ['image/png', filename, dataUrl].join(':')
      )
    }

Usage

In your dragstart event handler, set the DownloadURL data transfer item to a string with the following format:

MIME:filename:URL
  • MIME: The MIME type of the file (e.g., text/plain, image/png)
  • filename: The suggested filename for the download
  • URL: A fetchable URL where the file content can be retrieved
    • It can be a regular URL (however, if it’s cross-origin, it may fail)
    • It can also be a data URL (e.g., data:text/plain,Hello%2C%20world!)
    • It can also be a blob URL (generated with URL.createObjectURL)

Here's an example of setting the DownloadURL data transfer item in a dragstart event handler:

element.addEventListener('dragstart', (event) => {
  const mimeType = 'text/plain'
  const filename = 'hello.txt'
  const url = 'data:text/plain,Hello%2C%20world!'
  const downloadUrl = [mimeType, filename, url].join(':')
  event.dataTransfer.setData('DownloadURL', downloadUrl)
})

History

The DownloadURL API was likely developed for Gmail's drag-and-drop attachment feature (announced in 2010) and was discovered and documented by Ryan Seddon. Despite being widely used, it remains undocumented in official web specifications.

Bookmarks