Safe subset of web API for DOM manipulation but avoids tracking

For progressive enhancement, web devs should avoid using JavaScript for crucial behavior. However, for accessibility, JavaScript is often necessary to manage focus, set aria-* states, or manipulating the DOM to show/hide modals, tooltips, and accordion sections.

This means that JavaScript is crucial, even for the most vanilla pages, let alone pages that rely on frameworks. Even Web Components rely on JavaScript.

JavaScript is considered a weak link in progressive enhancement because of a few reasons: External JS files not loading (for whatever reason) and users disabling it (0.2% globally but varying by browser–TOR–and location–East Asia, What percentage of browsers with javascript disabled? - Deliberate Digital). Users that disable JavaScript often do so to avoid tracking. They pay the price by getting an often unusable web experience.

To combat this, I propose a new script type: <script type="safe">.

This new type of script can only be declared inline, disallowing linking external scripts. This would fix the “external JS didn’t load” issue because if you got the HTML, you got the inline script.

Secondly, and more importantly, this subset would not have the ability to make network calls or access location, navigator, history, or other sources of identifying data. It would not be able to do things like or form.submit() but it could do el.focus() and DOM manipulations. If JavaScript were disabled, it wouldn’t be able to insert a new image element or any tag that would make a network call. (I guess the img tag would be added to the DOM but just show a broken image.)

It would provide enough power to enable Web Components but not enough to enable tracking.


JavaScript is often necessary to manage focus, set aria-* states, or manipulating the DOM to show/hide modals, tooltips, and accordion sections.

Deeply wrong assumption in HTML architecture change discussion. Here we can (and should) discuss the root cause and 'right" ways of solving the problem. Given list of challenges exposes the lack of declarative behavior definition for given cases. Those have to be addressed on per-use-case basis.

Special kind of JS would not solve the problems, it just would mask it.

I agree that this showcases a lack of declarative behavior definitions. I think mature ux patterns should graduate from imperative scripting to declarative markup, but with things like Web Components allowing devs to introduce novel UI/UX, it may take years for those patterns to graduate if at all. In the meantime, these websites are broken and often unusable for users on poor connections or who’ve turned off JavaScript for security.

There is a precedent for having a restricted JavaScript API: web workers. They have no access to the DOM and also cannot use some synchronous APIs. This would be almost the opposite. The isolated/safe script would be able to manipulate the DOM but not much else. It wouldn’t be able to use fetch() or make network calls. It wouldn’t be able to write to cookies or local storage. It wouldn’t have access to browser context like the history or location.

I think such a restricted API could be created with the forthcoming Realms mechanism.

Creating such a safe web API subset seems incredibly difficult. I wouldn’t bet on it that it’s possible. The web platform is in such wide use that there will always be websites that will figure out ways to misuse even the “safest” APIs for nefarious purposes, if they’re forced to.

That being said, I would love if browsers stopped treating JavaScript as a simple binary (either on or off) and instead assigned different levels of privileges for self-hosted vs. third-party scripts.

It is not easy, but definitely not that difficult. While I personally do not support such proposal, creation the walled garden is doable which has been done several times in the past.

Could you elaborate?

I certainly like the idea of encouraging developers to refrain from having their pages make numerous HTTP requests, which can degrade the experience of users with patchy connections, with pages being partially loaded and stuck in that state.

I can’t imagine though the level of restrictiveness you propose being compatible with the ways people generally want to use web-sites (typically featuring transactional processing) ergo limited uptake, which is germane I think, assuming that in addition to safe script type, you mean the browser to offer a ‘Run safe JavaScript’ option.

Google Caja, embed-page and few others made a full and partial insulation of browser APIs to run the microapplication in jailed environment but still with embedded DOM.

I like the idea of browsers allowing different levels/types of JavaScript. Disallowing 3rd party is would be difficult because the websites could get around disallowing loading JS from other origins by self-hosting the scripts, and they could get around blocking network requests (tracking pings) to other origins by proxying the requests. Given the option, I’m sure more users would opt out of the ability for invasive tracking, by which I mean using the full web API to gather identifying context and sending it to multiple tracking services without user initiation.

The idea behind this proposal is to disallow all programmatic network access (like fetch) and all identifying contextual information (like document.cookie and document. location. (User-initiated network requests, like submitting a form by clicking a button, would still work.) This would prevent the isolated script (which would be allowed to run when other scripts aren’t) from pinging tracking servers or adding hidden inputs to a form containing identifying information gathered client-side.

This could mostly be achieved by denying the use of most web APIs. There are a few methods available in the DOM API that would need to be removed, namely canvas.toDataURL(),, and form.submit(). The DOM API, Intersection Observer, Resize Observer, and Screen Orientation API would provide most of what’s needed for simple UI Web Components and other basic UI and accessibility work.

Like how lazy load images fetch eagerly when JavaScript is turned off (to protect against leaking user behavior like how far they’ve scrolled), there would need to be some way to handle loading images with this script. Otherwise bad actors could add small images as tracking beacons detailing user behavior.

By denying contextual information and access to cookies and sources of entropy (like canvas.toDataURL()) these scripts would be unable to fingerprint the browser or add tracking information to the page.

Not directly relevant to proposal, but addresses same concern of security via scope insulation and inline scripting.

For Declarative Web Application(DWA) I am imagining the business logic defined declaratively( no js ) and in a manner when there is no cross-scope and global scope overlap between transformation pipelines and scoped elements. That pattern can be propagated into JS and most likely would be available for consumption of DWA patterns from usual JS.