Double-click an HTML file and the browser may open a URL such as file:///C:/tools/index.html. Serve that same file from a local web server and the URL may instead be http://localhost:8080/. Strictly speaking, file: is a URL scheme while localhost is a hostname, so this article compares opening a page with file:// against serving it from http://localhost. Because the HTML bytes are the same, it is natural to expect identical behavior.

In practice, JavaScript modules or fetches of neighboring files can fail under file:// and work under localhost. At the same time, being able to open a self-contained HTML file directly is useful in its own right. Browser Kitty tests these as separate execution environments. The key difference is not the HTML file itself, but the URL, origin model, and HTTP conditions the browser applies to it.

Four things to separate first

file://

Read the file directly

The browser opens the HTML directly from local storage without a web server. There is no HTTP response, and file URLs have special origin and storage behavior.

localhost

Receive it over HTTP from your own device

The browser makes an HTTP request to a local web server and receives the HTML as a response. In addition to normal origin behavior, the server can set HTTP response headers for Content-Type, range handling, CSP, and related web-delivery controls.

Secure Context

Secure context is a separate axis

Browsers treat localhost as trustworthy for development, and file URLs can also be potentially trustworthy. But being a secure context does not mean every API is available.

Local processing

Local processing is another separate axis

A file:// page can still contact external services when CORS and other conditions on the receiving side allow it, while a localhost app can process everything without external requests. Locality is determined by the real data path, not by the URL alone.

The same HTML can still run in a different browser environment

In short, the browser can apply different rules depending on how the document was reached, even when the HTML contents are identical. With file:// the browser opens a filesystem resource directly; with localhost it receives the document as an HTTP response from a web server.

That difference affects origins, CORS, HTTP headers, Web API requirements, and storage behavior. This is why changing only how the same file is opened can change the result.

How identical HTML can end up behaving differently
Same index.html file:// / localhost Origin & HTTP conditions CORS & API rules Different behavior

Identical HTML can face different browser rules when the URL scheme and delivery method change

file:// is direct file access; localhost is HTTP delivery

When opened with file:// there is no web server in between. HTML, JavaScript, images, and other resources are referenced as local files. With localhost the browser sends HTTP requests to a web server running on the same device and receives resources as HTTP responses.

Using localhost does not by itself mean uploading anything to a cloud service; localhost normally refers back to the same device. However, code in that page can still request external URLs, so localhost does not automatically mean there is no external communication.

Two ways to open the same HTML
Aspectfile://http://localhost
LoadingRead the file directlyReceive it over HTTP from a local web server
OriginUsually treated as an opaque originNormal origin based on scheme, host, and port
HTTP responseNoneAvailable
Response headersNo HTTP response, so there are no HTTP response headersCan return CSP, Content-Type, range-related settings, and more as HTTP response headers
Single HTMLWell suited to double-click useWell suited to testing web-delivery behavior

One major difference is the origin model

For ordinary web pages, an origin is broadly defined by the combination of scheme, hostname, and port. Resources delivered from the same http://localhost:8080 origin can therefore participate in normal same-origin rules.

File URLs are special. MDN notes that modern browsers usually treat files loaded with file:/// as opaque origins. An opaque origin is not considered equal to another origin, so another file in the same folder is not automatically treated as same-origin. The exact handling of file origins also has implementation-dependent aspects.

JavaScript modules and fetch often expose the difference

JavaScript modules are a clear example. Loading a module from another local file under file:// can hit CORS errors because of module security requirements. MDN explicitly recommends testing modules through a server rather than by opening the HTML as a local file.

The same issue can appear when fetch is used to read a neighboring JSON or text file. Merely placing two files in the same folder does not guarantee that JavaScript may read one from the other. With localhost, the server can deliver both resources from the same HTTP origin.

localhost has an HTTP response layer

Because localhost uses a web server, responses can carry headers such as Content-Type, Content-Length, Content-Range, Content-Security-Policy, Cross-Origin-Opener-Policy, and Cross-Origin-Embedder-Policy when needed. With file:// there is no HTTP response from a server in the first place.

Media playback makes this difference concrete. HTTP range requests let media players and other clients retrieve only the needed part of a large resource. Browser Kitty's local preview server handles range requests for demo videos. During development, seeking could cause the browser to abandon an older range connection, and the server originally raised an exception when it tried to keep writing to that closed connection. The local web server's behavior is therefore part of the localhost environment, not just a way to locate the HTML.

Secure context alone does not explain the difference

It is inaccurate to reduce the issue to 'file:// is insecure while localhost is secure.' Secure Context rules treat loopback locations such as localhost as potentially trustworthy for development, and the file scheme can also be considered potentially trustworthy.

So secure-context status alone cannot explain file:// versus localhost. Origins, URL schemes, CORS, API-specific restrictions, permissions, and user activation may all be separate conditions.

An API can still reject file:// even in a secure context

Service workers are a useful example. They are restricted to secure contexts, but register() has additional requirements: MDN documents a TypeError when the script URL or scope uses a scheme other than http: or https:. localhost can therefore support service workers as a local development secure context, while a file:// page cannot simply register a file: service-worker script.

Being in a secure context is only one part of an API's requirements. Whether a feature works under file:// depends on the conditions defined by that API as well.

localStorage also has special file:// behavior

On normal web pages, localStorage is partitioned by origin. A page opened at http://localhost:8080 can therefore be reasoned about in terms of that origin's storage area.

For documents loaded from file: URLs, MDN says localStorage behavior is undefined and may vary between browsers. Current implementations may appear to create separate storage areas per file URL, but that is not a behavior applications should rely on as a stable guarantee. This matters when a standalone HTML tool stores preferences or work state.

Why Browser Kitty tests file:// and localhost separately

Browser Kitty packages tools as single HTML files when practical. Embedding JavaScript, CSS, SVG, workers, Wasm, and other assets reduces the need to fetch or import neighboring files and makes direct file:// use more feasible. That helps distribution, but it also reduces exposure to local-file origin restrictions.

We still test through localhost during development. MIME types, range requests, and behavior that depends on HTTP response headers such as CSP, COOP, and COEP can only be exercised meaningfully through HTTP delivery. Success as a standalone file does not guarantee identical hosted behavior, and success on localhost does not guarantee identical double-click behavior.

When identical HTML behaves differently, inspect the address bar as well as the code. Is it file://, http://localhost, or a deployed https:// URL? On the web, that difference is part of the runtime environment.

Try it in Browser Kitty

Developer Toolbox

A local developer toolbox with 33 utilities for Base64, JSON, JWT, cron, regex, hashes, text, web formats, and more.

Open toolView tool details

Tips and limitations

  • 'Works from file://' and 'fully local processing' are different claims. A file:// page can still run code that contacts external URLs when CORS and other receiving-side conditions allow it.
  • localhost normally loops back to the same device, but it does not block external requests made by the page. Check those separately with tools such as the Network panel and CSP.
  • Bundling an app into one HTML file reduces cross-file loading problems, but it cannot bypass API requirements that specifically require http:, https:, or particular origin conditions.

Frequently asked questions

Does using localhost send my files to the internet?

Serving HTML from a web server on localhost normally uses loopback communication on the same device. However, JavaScript in the page can still contact external APIs or resources, and those requests must be evaluated separately.

Does file:// automatically mean fully local processing?

No. file:// tells you that the document itself was opened from a local file, but it does not guarantee that the page makes no external requests. Fully local processing depends on the actual runtime data and network paths.

If file:// can be a secure context, why can't it register a service worker?

Because secure-context status is only one requirement. ServiceWorkerContainer.register() also restricts the script and scope URL schemes to http: or https:. localhost can satisfy that as a trustworthy local HTTP origin.

Will every single-HTML app work under file://?

Not always. Bundling removes many cross-file fetch and import problems, but Web APIs can still impose origin, scheme, permission, user-activation, or other requirements.

Should I develop with file:// or localhost?

For software intended to run as a website, localhost is the normal development baseline. If you also distribute a standalone HTML file intended for direct opening, test the important workflows under file:// as a separate target.

References

The references below cover file URL origins, JavaScript modules, secure contexts, service workers, localStorage, and HTTP range requests. Browser Kitty-specific observations come from the local development server and standalone-HTML workflow used as of v168.