URL.createObjectURL(blob) returns a short blob: URL for a Blob, File or MediaSource in memory, usable in <img src>, <a download>, <video src> or new Worker(). Unlike a data URL nothing is copied or encoded, but the data stays alive until URL.revokeObjectURL() or the document unloads.
<body style="display: flex; gap: 16px; align-items: center; font: 14px system-ui, sans-serif">
<img id="badge" width="90" height="90" alt="Generated badge">
<div><a download="scores.csv">Download scores.csv</a><pre id="log"></pre></div>
<script type="module">
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 90">
<circle cx="45" cy="45" r="44" fill="#1565c0"/>
<text x="45" y="55" font-size="28" text-anchor="middle" fill="#fff">A+</text></svg>`;
const img = document.querySelector('#badge');
img.src = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
img.addEventListener('load', () => URL.revokeObjectURL(img.src), { once: true }); // free it
const csv = new Blob(['name,score\nAna,92\nBo,87\n'], { type: 'text/csv' });
const link = document.querySelector('a');
link.href = URL.createObjectURL(csv); // revoke when no longer offered
document.querySelector('#log').textContent = `${link.href}\n${csv.size} bytes, ${csv.type}`;
</script>
The URL holds the page's origin (file:// in this demo) and a random UUID, and works only in the creating document or worker; service workers cannot create them. For user files, pass the File from <input type="file"> directly (FileReader and Blob).