jsdom is a pure-JavaScript implementation of many web standards, notably the WHATWG DOM and HTML Standards, for use with Node.js. It emulates enough of a subset of a web browser to be useful for testing and scraping real-world web applications.
const { JSDOM } = require("jsdom");
// Create a jsdom instance
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
// Access the window object
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
// Use destructuring for convenience
const { document } = (new JSDOM(`<!DOCTYPE html><div id="main"></div>`)).window;
const mainDiv = document.getElementById("main");npm install jsdomconst { JSDOM } = require("jsdom");For ES modules:
import { JSDOM } from "jsdom";Additional exports:
const { JSDOM, VirtualConsole, CookieJar, ResourceLoader, toughCookie } = require("jsdom");jsdom is built around several key components:
class JSDOM {
constructor(input?: string | Buffer | ArrayBuffer | TypedArray, options?: JSDOMOptions);
readonly window: Window;
readonly virtualConsole: VirtualConsole;
readonly cookieJar: CookieJar;
serialize(): string;
nodeLocation(node: Node): LocationInfo | null | undefined;
getInternalVMContext(): vm.Context;
reconfigure(settings: ReconfigureSettings): void;
static fragment(html: string): DocumentFragment;
static fromURL(url: string, options?: FromURLOptions): Promise<JSDOM>;
static fromFile(filename: string, options?: JSDOMOptions): Promise<JSDOM>;
}Basic Usage:
// From HTML string
const dom = new JSDOM(`<!DOCTYPE html><p>Hello</p>`);
// From URL
const dom = await JSDOM.fromURL("https://example.com/");
// From file
const dom = await JSDOM.fromFile("./page.html");
// Create fragment (lightweight, no full browser environment)
const frag = JSDOM.fragment(`<p>Hello</p><p>World</p>`);See JSDOM Constructor and Methods for complete API details.
The Window object provides access to 180+ web standard interfaces:
// Access window from JSDOM instance
const window = dom.window;
// Window provides access to:
// - DOM APIs (Document, Element, Node, etc.)
// - HTML Elements (HTMLDivElement, HTMLInputElement, etc.)
// - Events (Event, MouseEvent, CustomEvent, etc.)
// - Storage (localStorage, sessionStorage)
// - Network (XMLHttpRequest, WebSocket, fetch Headers)
// - And 170+ more web standard interfacesUsage Example:
const { document, Element, Event, localStorage } = dom.window;
// DOM manipulation
const div = document.createElement("div");
div.textContent = "Hello";
document.body.appendChild(div);
// Events
div.addEventListener("click", (e) => console.log("Clicked"));
// Storage
localStorage.setItem("key", "value");See Window and DOM APIs for complete API reference.
Control how JavaScript executes within the jsdom environment:
interface JSDOMOptions {
/**
* Controls script execution
* - undefined: Scripts don't execute (default)
* - "outside-only": Enables window.eval() and fresh globals
* - "dangerously": Executes inline and external scripts (security risk!)
*/
runScripts?: "dangerously" | "outside-only";
}Usage:
// Default: No script execution
const dom1 = new JSDOM(`<script>console.log("won't run");</script>`);
// Outside-only: Use window.eval()
const dom2 = new JSDOM(``, { runScripts: "outside-only" });
dom2.window.eval('document.body.innerHTML = "<p>Hello</p>"');
// Dangerously: Inline scripts execute automatically
const dom3 = new JSDOM(`
<script>document.body.innerHTML = "<p>Hello</p>";</script>
`, { runScripts: "dangerously" });Load external scripts, stylesheets, images, and iframes:
interface JSDOMOptions {
resources?: "usable" | ResourceLoader;
}
class ResourceLoader {
constructor(options?: ResourceLoaderOptions);
fetch(url: string, options: FetchOptions): Promise<Buffer | null>;
}Usage:
// Enable resource loading
const dom = new JSDOM(`
<script src="https://example.com/script.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">
`, {
url: "https://example.org/",
resources: "usable",
runScripts: "dangerously"
});
// Custom resource loader
const loader = new ResourceLoader({
proxy: "http://127.0.0.1:9001",
userAgent: "MyApp/1.0"
});See Resource Loading for complete details.
Capture console output and jsdom errors:
class VirtualConsole {
constructor();
forwardTo(console: Console, options?: ForwardOptions): this;
on(event: ConsoleMethod, listener: (...args: any[]) => void): this;
on(event: "jsdomError", listener: (error: JSDOMError) => void): this;
}Usage:
const virtualConsole = new VirtualConsole();
virtualConsole.on("error", (err) => console.error("Page error:", err));
virtualConsole.on("jsdomError", (error) => {
console.error("jsdom error:", error.type, error.message);
});
const dom = new JSDOM(html, { virtualConsole });See Virtual Console for complete details.
HTTP cookie storage and management:
class CookieJar extends toughCookie.CookieJar {
constructor(store?: toughCookie.Store, options?: CookieJarOptions);
}Usage:
const cookieJar = new CookieJar();
cookieJar.setCookieSync("session=abc123", "https://example.org/");
const dom = new JSDOM(``, {
url: "https://example.org/",
cookieJar
});
// Access cookies from page
console.log(dom.window.document.cookie); // "session=abc123"See Cookie Management for complete details.
interface JSDOMOptions {
/**
* Sets window.location, document.URL, and document.documentURI
* Also affects relative URL resolution and same-origin checks
* @default "about:blank"
*/
url?: string;
/**
* Sets document.referrer
* @default "" (empty string)
*/
referrer?: string;
/**
* Document content type - affects parsing mode
* Must be an HTML MIME type or XML MIME type
* @default "text/html"
*/
contentType?: string;
/**
* Preserves location info for nodeLocation() method
* Also ensures correct line numbers in script stack traces
* Cannot be used with XML content type
* @default false
*/
includeNodeLocations?: boolean;
/**
* Maximum size in code units for localStorage and sessionStorage
* @default 5000000
*/
storageQuota?: number;
/**
* Controls script execution
* - undefined: Scripts don't execute (default)
* - "outside-only": Enables window.eval() and fresh globals
* - "dangerously": Executes inline and external scripts (security risk!)
* @default undefined
*/
runScripts?: "dangerously" | "outside-only";
/**
* Controls resource loading (scripts, stylesheets, images, iframes)
* - undefined: No resources loaded (default)
* - "usable": Loads usable resources
* - ResourceLoader instance: Custom resource loading
* @default undefined
*/
resources?: "usable" | ResourceLoader;
/**
* Pretends to be rendering/displaying content
* - Changes document.hidden to false
* - Changes document.visibilityState to "visible"
* - Enables requestAnimationFrame/cancelAnimationFrame
* @default false
*/
pretendToBeVisual?: boolean;
/**
* Custom virtual console for capturing output
* @default new VirtualConsole().forwardTo(console)
*/
virtualConsole?: VirtualConsole;
/**
* Cookie jar for HTTP cookie storage
* @default new CookieJar()
*/
cookieJar?: CookieJar;
/**
* Hook called before HTML parsing begins
* Useful for adding shims or modifying the environment
* @param window - The window object (not yet populated with DOM)
*/
beforeParse?: (window: Window) => void;
}New to jsdom? Start here:
Ready to dive deeper?
Complete API documentation for all components:
// Access to the tough-cookie module used by jsdom
import { toughCookie } from "jsdom";
// toughCookie is the complete tough-cookie module
// Provides advanced cookie utilities beyond CookieJar