--- name: happy-dom description: Use happy-dom ^20.0.0 as a headless DOM/browser implementation in standalone Bun or Node scripts, with v20 security defaults and lifecycle cleanup in mind. --- Verified against happy-dom@20.14.0 on 2026-09-07. 5 of 5 examples executed. # happy-dom ## Scope `happy-dom` provides a headless DOM implementation and a programmatic browser API. The examples below are standalone scripts: each can be run as `bun example.ts` with only `happy-dom` installed. ## `Window`: create and manipulate a DOM Import `Window` from `happy-dom`. Pass a URL when code under test depends on the document location. Access the DOM through `window.document`. ```ts pmcp-example import { strict as assert } from 'node:assert'; import { Window } from 'happy-dom'; const window = new Window({ url: 'https://localhost:8080' }); const document = window.document; document.body.innerHTML = '
'; const container = document.querySelector('.container'); assert.ok(container); const button = document.createElement('button'); container.appendChild(button); assert.equal(document.body.innerHTML, ''); assert.equal(window.location.href, 'https://localhost:8080/'); await window.happyDOM.abort(); window.close(); ``` Use `window.happyDOM.abort()` when pending Happy DOM work should be stopped, and call `window.close()` when the window is no longer needed. ## JavaScript evaluation is disabled by default in v20 Do not assume that scripts embedded in markup execute. Since v20, JavaScript evaluation is disabled by default for security reasons. Enable it explicitly with `settings: { enableJavaScriptEvaluation: true }` only when the evaluated code is trusted. A VM context is not an isolation boundary; untrusted JavaScript can pose an RCE risk. ```ts pmcp-example import { strict as assert } from 'node:assert'; import { Window } from 'happy-dom'; const window = new Window({ settings: { enableJavaScriptEvaluation: true } }); window.document.write(` `); assert.equal(window.document.body.getAttribute('data-evaluated'), 'yes'); await window.happyDOM.abort(); window.close(); ``` A common outdated pattern is to rely on HTML scripts executing without this setting. In v20 that default is intentionally off. ## `Browser` and pages Import `Browser` and, when configuring error handling, `BrowserErrorCaptureEnum`. Create a page with `browser.newPage()`, navigate with `page.goto()`, use `page.mainFrame.document`, and wait with `page.waitUntilComplete()`. The documented browser flow navigates to a URL and therefore requires the browser's page-loading environment. The standalone example below only exercises the constructible, offline portion of the API and does not make a network request. ```ts pmcp-example import { strict as assert } from 'node:assert'; import { Browser, BrowserErrorCaptureEnum } from 'happy-dom'; const browser = new Browser({ settings: { errorCapture: BrowserErrorCaptureEnum.processLevel } }); const page = browser.newPage(); assert.ok(page); assert.ok(page.mainFrame); assert.ok(page.mainFrame.document); await page.waitUntilComplete(); await browser.close(); ``` For a loaded page, the documented sequence is: ```ts const browser = new Browser({ settings: { errorCapture: BrowserErrorCaptureEnum.processLevel } }); const page = browser.newPage(); await page.goto('https://example.test/'); page.mainFrame.document.querySelector('a')?.click(); await page.waitUntilComplete(); await browser.close(); ``` Always close the browser when finished. The browser/page API is not the same shape as the older examples that only construct a `Window`. ## `GlobalWindow` `GlobalWindow` extends `Window` but evaluates document scripts in the global scope rather than in a Node.js VM context. This changes global state, so use it only when that behavior is required. Enable JavaScript evaluation explicitly in v20. ```ts pmcp-example import { strict as assert } from 'node:assert'; import { GlobalWindow } from 'happy-dom'; const key = '__happyDomSkillExampleValue'; const window = new GlobalWindow({ settings: { enableJavaScriptEvaluation: true } }); window.document.write(` `); assert.equal((globalThis as Record