Object URLs Need a Lifecycle: Creating and Revoking Blob URLs

In Brief
Create a Blob URL with URL.createObjectURL() when a browser consumer needs a temporary address for a Blob or File. Keep that URL, reuse it where appropriate, and call URL.revokeObjectURL() after every consumer has finished with it. For an interactive preview, revoke the old URL when the file is replaced or the preview is removed, not immediately after assigning it.
The File API makes it possible to preview a file selected by a visitor without uploading it first. We can turn the File into an object URL and give that URL to an image, video, or link just as we would use an address from the server.
There is a small but important difference. An object URL is created by the page, and the browser keeps its association with the underlying Blob until the URL is released or the document is unloaded. A page which repeatedly creates new previews without releasing the old ones can therefore retain data it no longer uses.
An Object URL Refers to Local Data
A File selected through a file input is a kind of Blob. It contains the file's bytes and details such as its media type, but an img element expects a URL in its src attribute.
URL.createObjectURL() bridges that gap:
<label for="photo">Choose a photograph</label><input id="photo" type="file" accept="image/*"><img id="preview" alt="Preview of the selected photograph">var photoInput = document.getElementById('photo');var preview = document.getElementById('preview');var objectURLAPI = window.URL || window.webkitURL;if (objectURLAPI && photoInput.files && photoInput.addEventListener) { photoInput.addEventListener('change', function () { var file = photoInput.files[0]; if (file) { preview.src = objectURLAPI.createObjectURL(file); } }, false);}The generated address uses the blob: scheme. It does not upload the photograph or give it a normal public web address. It creates a browser‑managed URL entry which refers to that particular object within the document's origin.
The April 2015 File API working draft defines both the creation method and a Blob URL store which holds these associations. That store is the reason the API has an explicit release method.
Release the Previous Preview
The first example works, but each change creates another object URL. Selecting ten large photographs can leave ten URL entries alive even though only the final preview is visible.
We can keep the current URL and revoke it before replacing the preview:
var photoInput = document.getElementById('photo');var preview = document.getElementById('preview');var objectURLAPI = window.URL || window.webkitURL;var currentPreviewURL = null;function releasePreview() { if (currentPreviewURL) { preview.removeAttribute('src'); objectURLAPI.revokeObjectURL(currentPreviewURL); currentPreviewURL = null; }}if (objectURLAPI && photoInput.files && photoInput.addEventListener) { photoInput.addEventListener('change', function () { releasePreview(); if (!photoInput.files.length) { return; } currentPreviewURL = objectURLAPI.createObjectURL( photoInput.files[0] ); preview.src = currentPreviewURL; }, false);}Removing src before revoking the URL makes the preview's end explicit. If the visitor clears the input, selects another file, or removes the preview, the current URL is no longer needed.
Browsers are required to discard a document's remaining Blob URL entries when that document is unloaded, so an explicit unload handler is unnecessary. Explicit cleanup matters more whilst a document remains open for a long time and lets the visitor replace the same resource repeatedly.
Do Not Revoke the URL Immediately
Cleanup can also happen too soon. This is unreliable:
var previewURL = objectURLAPI.createObjectURL(file);preview.src = previewURL;objectURLAPI.revokeObjectURL(previewURL);Assigning src starts the image's use of the URL, but it does not mean every browser has already finished fetching and decoding the data. Revoking the mapping immediately can leave the consumer with an address which no longer resolves.
For a one‑off operation, an image's load event can provide a later cleanup point. Even then, consider what the visitor can still do with the image. Revoking after it first displays may prevent a subsequent action which needs the original URL, such as opening the image separately or saving it from a context menu.
For an interactive preview, the least surprising boundary is normally replacement or removal. Keep the URL whilst the preview remains available, then revoke it when the preview ceases to be usable.
One URL Can Serve More than One Consumer
Calling createObjectURL() twice for the same Blob can create two URL entries. If an image and a link need to refer to the same data for the same period, store one URL and give that string to both of them. Revoke it only after both consumers are finished.
This is especially important for generated downloads. A Blob containing a report can be given to a link through an object URL, but the URL must remain valid when the visitor actually follows it. The HTML download attribute can improve that interaction in browsers which support it, although support is not consistent enough in 2015 to make it the only route offered for an essential download.
Feature‑Detect the API
Unprefixed window.URL and object URLs are available in current versions of the major browsers, including Internet Explorer 10 and later. Older browsers, including Internet Explorer 9, do not provide this route. Some older WebKit implementations expose the methods through window.webkitURL, which is why the examples retain that fallback.
Checking for the API avoids presenting a broken preview. A production interface should also check support for the file input and provide its ordinary upload route when local previewing is unavailable. The preview is an enhancement; choosing the file should not depend upon it.
Object URLs are straightforward once they are treated as resources rather than disposable strings. Create one at the point a consumer needs it, retain its value for as long as that consumer remains active, and revoke it at the corresponding end of that lifecycle.
Postscript
Aug 2026: This article forms part of an archive restored from a previous version of my website. Its original publication date is accurate. During the restoration, I reviewed and updated it where appropriate for formatting, imagery, broken links, code correctness, and current internal references, whilst preserving the original technical context and intent. URL.createObjectURL() and URL.revokeObjectURL() remain the standard browser methods, and explicit revocation is still important in long‑lived pages. Modern application frameworks provide component lifecycles in which to perform that cleanup, but the browser‑level rule is unchanged. Submitting Forms with JavaScript and FormData covers the separate task of sending selected files to a server.