JavaScript Document beforescriptexecute Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Deprecated
Non-standard
Document event

What You’ll Learn

The Document beforescriptexecute event once fired before a static <script> started running in Firefox. Cancelling it could stop execution. Learn why dynamic scripts were excluded, how it differed from afterscriptexecute, and which portable approaches to use instead—with five examples and try-it labs.

01

Kind

Document event

02

Type

Event

03

Cancelable

Yes (legacy)

04

Status

Deprecated · Non-standard

05

Target scripts

Static only

06

Modern path

CSP / safe loading

Introduction

Early Gecko experiments added a pair of proprietary Document events around script execution: beforescriptexecute (before run) and afterscriptexecute (after run). The “before” event was interesting because cancelling it could block the script.

On Document, it answered: is this static script about to start? That idea never became a web standard. Other browsers never shipped it, MDN warns not to rely on it, and modern Firefox stopped exposing useful web-facing support.

⚠️
Deprecated & non-standard

Learn this event for legacy Firefox code and interviews. For new apps, control scripts with CSP, trusted sources, modules, and careful DOM insertion—not Gecko-only events.

Understanding beforescriptexecute

A Document event listened on document in supporting Gecko. Per MDN, it fired when a static <script> was about to start executing—not when you insert a script later with appendChild() or similar.

  • Fires when a static script is about to be executed (legacy Firefox).
  • Does not fire for scripts added dynamically (for example appendChild()).
  • CancelablepreventDefault() could stop execution in old Gecko.
  • Generic Event — no special payload; event.target is the script element.
  • Siblingafterscriptexecute ran later and was not cancelable.
  • RelatedDocument.currentScript identifies the script currently running.
  • Status — Deprecated and Non-standard on MDN; not part of any specification.

🔎 Static vs Dynamic Scripts

This is the detail beginners miss. MDN’s Document page is explicit:

How the script appearsWould beforescriptexecute fire? (legacy Gecko)
Written in the HTML as <script>...</script> or <script src="...">Yes — static script about to start
Created in JS and inserted with appendChild() / insertBefore()No — dynamic scripts skipped

That limitation alone made it a poor “block all scripts” tool. Portable CSP and careful loading work for both static and dynamic scripts.

📝 Syntax

Use the event name with addEventListener, or set the handler property (legacy Firefox only):

JavaScript
addEventListener("beforescriptexecute", (event) => { });

onbeforescriptexecute = (event) => { };

Event type

A generic Event.

Cancelable

In legacy Gecko, cancelling the event prevented the script from executing. Call event.preventDefault() inside the handler. Modern browsers typically never fire this event at all.

Typical listener (MDN style)

JavaScript
function starting(e) {
  console.log(`Starting script with ID: ${e.target.id}`);
}

document.addEventListener("beforescriptexecute", starting);
// or
document.onbeforescriptexecute = starting;

⚖️ beforescriptexecute vs afterscriptexecute vs CSP

APIWhen it firesPortable?
beforescriptexecuteStatic script about to run (could cancel)No — legacy Gecko only
afterscriptexecuteStatic script just finished runningNo — legacy Gecko only
Content Security PolicyBrowser enforces which scripts may runYes — prefer this
script load / errorExternal script finished or failedYes — after-run hooks
document.currentScriptPoints at the script currently executingYes — standard property

🚀 What to Use Instead

There is no portable DOM event that cancels arbitrary scripts the way legacy beforescriptexecute did. Use layered, standard approaches:

  • CSP — declare which script sources (and inline policies) are allowed.
  • Do not inject untrusted scripts — fix the source, not the symptom.
  • ES modules — explicit imports instead of ad-hoc script tags.
  • MutationObserver — some legacy blockers changed a new script’s type before it ran (fragile; CSP is better).
JavaScript
Content-Security-Policy: script-src 'self'

That header (or a matching <meta> policy, where appropriate) is the modern, cross-browser way to control which scripts may execute—static or dynamic.

⚡ Quick Reference

GoalCode / note
Listen (legacy)document.addEventListener("beforescriptexecute", fn)
Handler propertydocument.onbeforescriptexecute = fn
Cancel (legacy)event.preventDefault()
Static scriptsOnly those (legacy Gecko)
Dynamic scriptsDo not fire (MDN)
Event typeGeneric Event
Feature-detect"onbeforescriptexecute" in document (weak; still prefer alternatives)
Modern replaceCSP + trusted script loading
MDN statusDeprecated · Non-standard

🔍 At a Glance

Four facts to remember about Document beforescriptexecute.

Event type
Event

Generic

Cancelable
yes*

*legacy Gecko

Scripts
static

Not dynamic

New code?
avoid

Use CSP

Examples Gallery

Examples follow MDN Document: beforescriptexecute event and show safe feature detection plus modern replacements. In most current browsers the proprietary event will never fire—the labs still teach the patterns clearly.

📚 Getting Started

Register handlers the MDN ways (legacy Gecko).

Example 1 — addEventListener("beforescriptexecute")

MDN style: listen on document and log the starting script’s id (where supported).

JavaScript
function starting(e) {
  console.log(`Starting script with ID: ${e.target.id}`);
}

document.addEventListener("beforescriptexecute", starting);

// In legacy Firefox, a static <script id="demo"> could fire this before it ran.
// In modern browsers it typically never fires.
Try It Yourself

How It Works

You register the same way as any other DOM event. Support is the hard part: without legacy Gecko behavior, the handler sits idle. When it did fire, event.target was the <script> element about to run.

Example 2 — onbeforescriptexecute Property

MDN’s alternate style using the event handler property on document.

JavaScript
document.onbeforescriptexecute = (event) => {
  console.log("Script about to run (onbeforescriptexecute)");
  console.log("target id:", event.target && event.target.id);
};

// Assigning again replaces the previous handler.
// Prefer addEventListener when you need multiple listeners.
Try It Yourself

How It Works

Same event, different registration API. One property means one handler—easy to overwrite by accident.

📈 Cancel, Limits & Replace

Legacy cancel path, static-only MDN rule, and modern controls.

Example 3 — Cancel with preventDefault()

In old Gecko this could block a static script. Today the event usually never fires.

JavaScript
document.addEventListener("beforescriptexecute", (event) => {
  console.log("Blocking script execution (legacy only)");
  event.preventDefault();
});

// Historical: cancel stopped a static script from running.
// Modern browsers: listener is usually a no-op (event never fires).
console.log("Cancel listener ready (event may never fire)");
Try It Yourself

How It Works

This was the unique selling point of beforescriptexecute versus afterscriptexecute. Without Gecko support, preventDefault() here does nothing useful—use CSP instead.

Example 4 — Static vs Dynamic (MDN Rule)

Dynamic appendChild() scripts would not trigger beforescriptexecute even in old Firefox.

JavaScript
document.addEventListener("beforescriptexecute", (e) => {
  console.log("beforescriptexecute for:", e.target && e.target.id);
});

// Dynamic insert — MDN: beforescriptexecute does NOT fire for this path
const dynamic = document.createElement("script");
dynamic.id = "dynamic-demo";
dynamic.textContent = "console.log('dynamic script ran');";
document.body.appendChild(dynamic);

console.log("Dynamic script appended");
console.log("MDN: beforescriptexecute skips dynamically added scripts");
console.log("Prefer CSP / trusted loading instead");
Try It Yourself

How It Works

The injected script still runs when appended. The proprietary Document event simply was not designed to intercept dynamic inserts—another reason CSP is a better teaching target for beginners.

Example 5 — Modern Thinking (CSP + Observer Demo)

Prefer CSP in production. This lab shows a fragile teaching demo some legacy blockers used: change an injected script’s type so it will not execute as JS.

JavaScript
const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
      if (node.nodeName === "SCRIPT" && node.dataset?.demo === "block") {
        node.type = "text/plain";
        console.log("Neutralized demo script");
      }
    }
  }
});

observer.observe(document.documentElement, { childList: true, subtree: true });

const s = document.createElement("script");
s.dataset.demo = "block";
s.textContent = "window.__shouldStayUndefined = true;";
document.body.appendChild(s);

console.log("__shouldStayUndefined:", typeof window.__shouldStayUndefined);
console.log("(Prefer CSP in production; this is a teaching demo only.)");
Try It Yourself

How It Works

Changing type to something other than a JS MIME type prevents execution for that demo script. Race conditions and incomplete coverage make this a poor security foundation—CSP belongs in the HTTP response (or carefully designed meta policies).

🚀 Common Use Cases

  • Understanding legacy Firefox / Gecko code that tried to cancel static scripts.
  • Migrating old extensions or pages off proprietary script-execute events.
  • Interview / history knowledge of early HTML script lifecycle proposals.
  • Teaching why static-vs-dynamic limits and standards matter for DOM events.
  • Choosing CSP, trusted loading, currentScript, or ES modules for real production work.

🔧 How It Works

1

Static script is ready

A <script> already in the markup is about to run.

Prepare
2

beforescriptexecute (legacy)

Old Gecko dispatched a Document Event; dynamic inserts skipped.

Notify
3

Optional cancel

preventDefault() could stop that script in supporting Gecko.

Gate
4

Prefer CSP today

Use Content Security Policy and trusted script loading in new code.

📝 Notes

  • MDN: Deprecated and Non-standard — avoid in production.
  • Applies to static scripts only; dynamic appendChild() scripts do not fire it.
  • Was cancelable in legacy Gecko; sibling afterscriptexecute was not.
  • Proprietary to Gecko; never a cross-browser API; not part of any specification.
  • Related learning: afterscriptexecute, currentScript, scripts, JavaScript hub.

Very Limited / Legacy Browser Support

beforescriptexecute is a deprecated, non-standard Gecko Document event. Logos use the shared browser-image-sprite.png sprite from this project. Other engines never implemented it; modern Firefox no longer dispatches it to web content. Prefer CSP and trusted script loading.

Deprecated · Non-standard

Document beforescriptexecute

Do not build features on this event. Use it only to understand or migrate legacy Firefox code.

Legacy Not for new apps
Google Chrome Never implemented
Unavailable
Mozilla Firefox Legacy only · removed / disabled in modern versions
Avoid
Apple Safari Never implemented
Unavailable
Microsoft Edge Never implemented (Chromium)
Unavailable
Opera Never implemented (Chromium)
Unavailable
Internet Explorer No beforescriptexecute support
Unavailable
beforescriptexecute Deprecated

Bottom line: Feature-detect if you must touch legacy Gecko code. For new work, use CSP and trusted script loading. Remember: even historically, dynamically appended scripts did not fire this Document event.

Conclusion

Document beforescriptexecute once told Firefox pages that a static script was about to run—and could cancel it. Today it is a deprecated, non-standard footnote: useful for reading old code, not for shipping new products.

Continue with DOMContentLoaded, currentScript, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Prefer Content Security Policy for script control
  • Load only trusted scripts; use ES modules when possible
  • Feature-detect before touching legacy Gecko-only APIs
  • Remember the static-only MDN rule when reading old code
  • Plan migration off proprietary script-execute events

❌ Don’t

  • Build new features on beforescriptexecute
  • Assume Chrome, Safari, or Edge ever supported it
  • Expect it to fire for appendChild()-inserted scripts
  • Treat preventDefault() here as a portable security tool
  • Treat non-standard Gecko events as future-proof

Key Takeaways

Knowledge Unlocked

Five things to remember about Document beforescriptexecute

Legacy Gecko “static script about to run” gate — prefer CSP now.

5
Core concepts
⚠️ 02

Deprecated

avoid new use

Status
🚫 03

Non-standard

Gecko only

Compat
🚫 04

Cancelable*

*legacy only

API
🚀 05

Replace

use CSP

Modern

❓ Frequently Asked Questions

It is a proprietary Gecko (Firefox) Document event that fired when a static <script> element was about to start executing. MDN marks it Deprecated and Non-standard. It was never a finished web standard.
No. Per MDN, it does not fire when a script element is added dynamically (for example with appendChild()). It only applied to static scripts already in the document markup in supporting legacy Firefox.
Yes, in legacy Gecko. Calling preventDefault() on beforescriptexecute could stop that static script from running. The sibling afterscriptexecute was not cancelable — it only notified after the script had already run.
No. Prefer Content Security Policy (CSP), avoid injecting untrusted scripts, ES modules with known imports, or careful DOM insertion. Do not rely on this Gecko-only cancel hook.
Historically only Firefox (Gecko). Other major browsers never shipped it. Modern Firefox stopped dispatching it to web content and later removed the implementation.
In supporting legacy Firefox: document.addEventListener("beforescriptexecute", handler) or document.onbeforescriptexecute = handler. Always feature-detect; do not assume the event exists.
Did you know?

Mozilla later unshipped beforescriptexecute and afterscriptexecute from web content because they were non-standard and unused by other browsers. Script blockers that once relied on them moved to portable techniques such as CSP or changing a script’s type via MutationObserver.

Next: Document DOMContentLoaded

Learn the standard event that fires when the HTML is fully parsed and ready.

DOMContentLoaded →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful