{"id":11164,"library":"jsdom","title":"JSDOM: JavaScript DOM Implementation for Node.js","description":"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.","status":"active","version":"29.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/jsdom/jsdom","tags":["javascript","dom","html","whatwg","w3c"],"install":[{"cmd":"npm install jsdom","lang":"bash","label":"npm"},{"cmd":"yarn add jsdom","lang":"bash","label":"yarn"},{"cmd":"pnpm add jsdom","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Optional peer dependency for rendering canvas elements in the JSDOM environment.","package":"canvas","optional":true}],"imports":[{"note":"While CommonJS `require` is still supported, ESM imports are the standard for modern Node.js development. For CommonJS, use `const { JSDOM } = require('jsdom');`","wrong":"const { JSDOM } = require('jsdom');","symbol":"JSDOM","correct":"import { JSDOM } from 'jsdom';"},{"note":"Used for custom handling of console messages within the JSDOM window environment. For CommonJS, use `const { VirtualConsole } = require('jsdom');`","wrong":"const VirtualConsole = require('jsdom').VirtualConsole;","symbol":"VirtualConsole","correct":"import { VirtualConsole } from 'jsdom';"},{"note":"For custom resource loading behavior (e.g., intercepting HTTP requests). The API for this class was significantly overhauled in v28.0.0. For CommonJS, use `const { ResourceLoader } = require('jsdom');`","wrong":"const ResourceLoader = require('jsdom').ResourceLoader;","symbol":"ResourceLoader","correct":"import { ResourceLoader } from 'jsdom';"}],"quickstart":{"code":"import { JSDOM } from 'jsdom';\n\n// Basic usage: create a DOM from an HTML string\nconst dom = new JSDOM(`<!DOCTYPE html>\n  <html>\n    <head><title>My Page</title></head>\n    <body>\n      <p id=\"greeting\">Hello, JSDOM!</p>\n      <button onclick=\"document.querySelector('#greeting').textContent = 'Button Clicked!';\">Click Me</button>\n    </body>\n  </html>`, {\n  url: \"https://example.org/\",\n  referrer: \"https://example.com/\",\n  contentType: \"text/html\",\n  includeNodeLocations: true // Useful for debugging script errors\n});\n\nconst { window } = dom;\nconst { document } = window;\n\n// Access and manipulate the DOM\nconsole.log(document.title); // My Page\nconst greetingParagraph = document.getElementById(\"greeting\");\nconsole.log(greetingParagraph?.textContent); // Hello, JSDOM!\n\n// Simulate a click event, executing inline script\nconst button = document.querySelector('button');\nbutton?.click();\nconsole.log(greetingParagraph?.textContent); // Button Clicked!\n\n// Clean up the window object to prevent memory leaks\ndom.window.close();\n","lang":"typescript","description":"Demonstrates creating a JSDOM instance, accessing its window and document, manipulating elements, simulating user interaction, and proper cleanup."},"warnings":[{"fix":"Upgrade your Node.js environment to a supported version (e.g., `nvm install 22` or `nvm use 22`).","message":"jsdom v29.0.0 and later require Node.js v22.13.0+, v20.19.0+, or v24.0.0+.","severity":"breaking","affected_versions":">=29.0.0"},{"fix":"Review CSS parsing and `getComputedStyle()` usage. If custom CSS processing was tied to the old dependencies, update it to reflect the new internal implementation or use `css-tree` directly if advanced AST manipulation is needed.","message":"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.","severity":"breaking","affected_versions":">=29.0.0"},{"fix":"Consult the jsdom README or documentation for v28.0.0+ regarding the new `ResourceLoader` API and update your custom resource loading logic accordingly.","message":"The resource loading customization API was overhauled in v28.0.0. Existing custom `ResourceLoader` implementations will likely break.","severity":"breaking","affected_versions":">=28.0.0"},{"fix":"Be aware of potential increased WebSocket connection usage. Monitor upstream `undici` bug reports for a fix or upgrade to a jsdom version that incorporates a resolution if available.","message":"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.","severity":"gotcha","affected_versions":">=28.0.0 <29.0.0"},{"fix":"Only enable `includeNodeLocations: true` when necessary for debugging or source mapping. Keep it `false` (default) for performance-critical scenarios. Do not use with `contentType: 'application/xml'`.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Handle `QuotaExceededError` exceptions when interacting with `localStorage` or `sessionStorage`. Increase `storageQuota` in the `JSDOM` constructor options if more storage is legitimately required, e.g., `{ storageQuota: 20000000 }`.","message":"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`.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Upgrade 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.","cause":"Attempting to run jsdom v29.0.0 or newer with an unsupported Node.js version.","error":"Error: Your current Node.js version (vXX.Y.Z) is not supported by jsdom. Please upgrade to Node.js v22.13.0 or higher."},{"fix":"Increase 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.","cause":"An application running within the JSDOM environment attempted to store more data in `localStorage` or `sessionStorage` than the `storageQuota` allows.","error":"DOMException: QuotaExceededError: The quota has been exceeded."},{"fix":"Review 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.","cause":"Using a custom `ResourceLoader` class or configuration with `jsdom` v28.0.0 or newer that adheres to an older API specification.","error":"TypeError: The \"init\" argument must be an object of type ResourceLoaderInit"}],"ecosystem":"npm"}