JSDOM: JavaScript DOM Implementation for Node.js
jsdom is a pure-JavaScript implementation of many web standards, including the WHATWG DOM and HTML specifications, designed for use within Node.js. Its primary goal is to emulate a sufficient subset of a web browser environment, making it highly useful for server-side testing, web scraping, and automation of web applications without a full browser GUI. The current stable version is 29.0.2. Releases seem to follow a relatively frequent cadence, with minor and patch versions appearing regularly to address bugs, improve performance, and add features, while major versions introduce breaking changes and significant overhauls, such as the recent CSSOM rewrite in v29.0.0 and resource loading changes in v28.0.0. Key differentiators include its pure-JS nature, making it lightweight compared to headless browser solutions, and its direct exposure of the DOM API, enabling direct manipulation and inspection of rendered HTML.
Common errors
-
Error: Your current Node.js version (vXX.Y.Z) is not supported by jsdom. Please upgrade to Node.js v22.13.0 or higher.
cause Attempting to run jsdom v29.0.0 or newer with an unsupported Node.js version.fixUpgrade your Node.js runtime to `^20.19.0`, `^22.13.0`, or `^24.0.0` or a newer compatible version as specified in the package's `engines` field. -
DOMException: QuotaExceededError: The quota has been exceeded.
cause An application running within the JSDOM environment attempted to store more data in `localStorage` or `sessionStorage` than the `storageQuota` allows.fixIncrease the `storageQuota` in the JSDOM constructor options, for example: `new JSDOM(html, { storageQuota: 10 * 1024 * 1024 })` for 10MB, or reduce the amount of data being stored. -
TypeError: The "init" argument must be an object of type ResourceLoaderInit
cause Using a custom `ResourceLoader` class or configuration with `jsdom` v28.0.0 or newer that adheres to an older API specification.fixReview the jsdom documentation for v28.0.0+ regarding `ResourceLoader` customization. The API was overhauled; your `ResourceLoader` implementation needs to be updated to match the new `ResourceLoaderInit` interface.
Warnings
- breaking jsdom v29.0.0 and later require Node.js v22.13.0+, v20.19.0+, or v24.0.0+.
- breaking The CSSOM implementation was completely overhauled in v29.0.0, replacing `@acemir/cssom` and `cssstyle` with internal implementations. This may change parsing behavior for complex CSS or break direct interactions with previous internal CSS objects.
- breaking The resource loading customization API was overhauled in v28.0.0. Existing custom `ResourceLoader` implementations will likely break.
- gotcha A regression in v28.0.0 means `WebSocket`s are no longer correctly throttled to one connection per origin due to an upstream Node.js `undici` bug.
- gotcha Enabling `includeNodeLocations: true` in the JSDOM constructor options preserves HTML parser location info, which is useful for debugging but incurs a performance overhead. It is also incompatible with XML content types.
- gotcha The `storageQuota` option limits `localStorage` and `sessionStorage` size. Exceeding the default 5MB (5,000,000 code units) per origin will throw a `DOMException` of type `QuotaExceededError`.
Install
-
npm install jsdom -
yarn add jsdom -
pnpm add jsdom
Imports
- JSDOM
const { JSDOM } = require('jsdom');import { JSDOM } from 'jsdom'; - VirtualConsole
const VirtualConsole = require('jsdom').VirtualConsole;import { VirtualConsole } from 'jsdom'; - ResourceLoader
const ResourceLoader = require('jsdom').ResourceLoader;import { ResourceLoader } from 'jsdom';
Quickstart
import { JSDOM } from 'jsdom';
// Basic usage: create a DOM from an HTML string
const dom = new JSDOM(`<!DOCTYPE html>
<html>
<head><title>My Page</title></head>
<body>
<p id="greeting">Hello, JSDOM!</p>
<button onclick="document.querySelector('#greeting').textContent = 'Button Clicked!';">Click Me</button>
</body>
</html>`, {
url: "https://example.org/",
referrer: "https://example.com/",
contentType: "text/html",
includeNodeLocations: true // Useful for debugging script errors
});
const { window } = dom;
const { document } = window;
// Access and manipulate the DOM
console.log(document.title); // My Page
const greetingParagraph = document.getElementById("greeting");
console.log(greetingParagraph?.textContent); // Hello, JSDOM!
// Simulate a click event, executing inline script
const button = document.querySelector('button');
button?.click();
console.log(greetingParagraph?.textContent); // Button Clicked!
// Clean up the window object to prevent memory leaks
dom.window.close();