The JSDOM class is the main entry point for creating DOM instances. It provides a constructor and several factory methods for creating instances from different sources.
Creates a jsdom instance from an HTML string or binary data.
/**
* Creates a jsdom instance
* @param input - HTML string or binary data (Buffer, ArrayBuffer, TypedArray)
* @param options - Configuration options
*/
constructor(input?: string | Buffer | ArrayBuffer | TypedArray, options?: JSDOMOptions);Usage Examples:
const { JSDOM } = require("jsdom");
// Basic usage with HTML string
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
// With options
const dom = new JSDOM(`<!DOCTYPE html><body></body>`, {
url: "https://example.org/",
referrer: "https://example.com/",
contentType: "text/html",
includeNodeLocations: true,
storageQuota: 10000000
});
// With binary data (auto-detects encoding)
const buffer = Buffer.from('<!DOCTYPE html><p>Hello</p>');
const dom = new JSDOM(buffer);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;
}Example with Multiple Options:
const { JSDOM, VirtualConsole, ResourceLoader } = require("jsdom");
const virtualConsole = new VirtualConsole();
virtualConsole.on("error", (err) => console.error("Page error:", err));
const resourceLoader = new ResourceLoader({
userAgent: "MyApp/1.0"
});
const dom = new JSDOM(`<!DOCTYPE html><html><body></body></html>`, {
url: "https://example.org/",
referrer: "https://google.com/",
contentType: "text/html",
includeNodeLocations: true,
storageQuota: 10000000,
runScripts: "dangerously",
resources: resourceLoader,
pretendToBeVisual: true,
virtualConsole: virtualConsole,
beforeParse(window) {
window.myCustomAPI = () => console.log("Custom API called");
}
});/**
* The Window object (global proxy)
* Provides access to the full DOM and web APIs
*/
readonly window: Window;
/**
* The VirtualConsole instance for this jsdom
*/
readonly virtualConsole: VirtualConsole;
/**
* The CookieJar instance for this jsdom
*/
readonly cookieJar: CookieJar;Usage Example:
const dom = new JSDOM(`<!DOCTYPE html><p>Hello</p>`);
// Access window
const { document } = dom.window;
console.log(document.querySelector("p").textContent); // "Hello"
// Access virtual console
dom.virtualConsole.on("error", err => console.error(err));
// Access cookie jar (compatible with tough-cookie)
dom.cookieJar.setCookieSync("key=value", "https://example.org/");Returns the HTML serialization of the document, including the doctype.
/**
* Serializes the document to an HTML string
* @returns HTML string including doctype
*/
serialize(): string;Usage Example:
const dom = new JSDOM(`<!DOCTYPE html>hello`);
const html = dom.serialize();
// Returns: "<!DOCTYPE html><html><head></head><body>hello</body></html>"
// Contrast with:
const outerHTML = dom.window.document.documentElement.outerHTML;
// Returns: "<html><head></head><body>hello</body></html>" (no doctype)Returns the source code location information for a DOM node. Requires includeNodeLocations: true option.
/**
* Gets the source code location of a node
* @param node - The DOM node to locate
* @returns Location information from the HTML parser, null for implicitly created nodes (like <html>, <body>),
* or undefined for dynamically created nodes
* @throws Error if includeNodeLocations was not set to true
*/
nodeLocation(node: Node): LocationInfo | null | undefined;
interface LocationInfo {
startOffset: number;
endOffset: number;
startLine: number;
startCol: number;
endLine: number;
endCol: number;
startTag?: {
startOffset: number;
endOffset: number;
startLine: number;
startCol: number;
endLine: number;
endCol: number;
attrs?: Record<string, { startOffset: number; endOffset: number; startLine: number; startCol: number; endLine: number; endCol: number; }>;
};
endTag?: {
startOffset: number;
endOffset: number;
startLine: number;
startCol: number;
endLine: number;
endCol: number;
};
attrs?: Record<string, { startOffset: number; endOffset: number; startLine: number; startCol: number; endLine: number; endCol: number; }>;
}Usage Example:
const dom = new JSDOM(
`<p>Hello
<img src="foo.jpg">
</p>`,
{ includeNodeLocations: true }
);
const pEl = dom.window.document.querySelector("p");
const imgEl = dom.window.document.querySelector("img");
const textNode = pEl.firstChild;
console.log(dom.nodeLocation(pEl));
// { startOffset: 0, endOffset: 39, startTag: {...}, endTag: {...} }
console.log(dom.nodeLocation(textNode));
// { startOffset: 3, endOffset: 13 }
console.log(dom.nodeLocation(imgEl));
// { startOffset: 13, endOffset: 32 }
// Implicitly created elements return null
const bodyEl = dom.window.document.body;
console.log(dom.nodeLocation(bodyEl)); // nullReturns the internal VM context for advanced script execution using Node.js vm module.
/**
* Gets the internal VM context for use with Node.js vm module
* @returns The contextified global object
* @throws TypeError if runScripts was not set
*/
getInternalVMContext(): vm.Context;Usage Example:
const { Script } = require("vm");
const { JSDOM } = require("jsdom");
const dom = new JSDOM(``, { runScripts: "outside-only" });
// Pre-compile a script
const script = new Script(`
if (!this.ran) {
this.ran = 0;
}
++this.ran;
`);
const vmContext = dom.getInternalVMContext();
// Run the pre-compiled script multiple times
script.runInContext(vmContext);
script.runInContext(vmContext);
script.runInContext(vmContext);
console.assert(dom.window.ran === 3);Reconfigures the jsdom's URL or window.top after creation. Does not perform navigation or reload content.
/**
* Reconfigures settings that are normally immutable
* @param settings - Settings to update
*/
reconfigure(settings: ReconfigureSettings): void;
interface ReconfigureSettings {
/**
* Changes window.top (which is normally unforgeable)
*/
windowTop?: Window;
/**
* Changes the document URL
* Affects window.location, document.URL, document.documentURI,
* relative URL resolution, and same-origin checks
* Does not navigate or reload content
*/
url?: string;
}Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM();
console.log(dom.window.location.href); // "about:blank"
// Change the URL
dom.reconfigure({ url: "https://example.com/" });
console.log(dom.window.location.href); // "https://example.com/"
console.log(dom.window.document.URL); // "https://example.com/"
// The DOM content remains unchanged
// No navigation occurs, just URL updateCreates a DocumentFragment from an HTML string without creating a full JSDOM instance. Useful for simple DOM manipulation without the overhead of a complete browser environment.
/**
* Creates a DocumentFragment from an HTML string
* Uses a shared template owner document for efficiency
* All fragments share the same owner document
* @param html - HTML string to parse
* @returns DocumentFragment containing parsed nodes
*/
static fragment(html: string): DocumentFragment;Usage Example:
const { JSDOM } = require("jsdom");
const frag = JSDOM.fragment(`<p>Hello</p><p><strong>Hi!</strong></p>`);
console.log(frag.childNodes.length); // 2
console.log(frag.querySelector("strong").textContent); // "Hi!"
// Can manipulate the fragment
frag.querySelector("p").textContent = "Updated";
// Note: The fragment's ownerDocument has no browsing context
// - ownerDocument.defaultView is null
// - Resources won't load
// - No associated URL
// Serialization of single-element fragments
const singleFrag = JSDOM.fragment(`<p>Hello</p>`);
console.log(singleFrag.firstChild.outerHTML); // "<p>Hello</p>"Promise-returning factory method that creates a jsdom by fetching content from a URL.
/**
* Creates a JSDOM instance by fetching from a URL
* @param url - URL to fetch
* @param options - Configuration options (similar to constructor)
* @returns Promise that resolves to JSDOM instance
* @throws If URL is invalid or request fails
*/
static fromURL(url: string, options?: FromURLOptions): Promise<JSDOM>;
interface FromURLOptions extends Omit<JSDOMOptions, "url" | "contentType"> {
// url and contentType are determined from the HTTP response
// All other JSDOMOptions are supported
/**
* Used as HTTP Referer request header
*/
referrer?: string;
}Usage Example:
const { JSDOM } = require("jsdom");
// Basic usage
JSDOM.fromURL("https://example.com/").then(dom => {
console.log(dom.serialize());
console.log(dom.window.document.title);
});
// With options
JSDOM.fromURL("https://example.com/", {
referrer: "https://google.com/",
resources: "usable",
runScripts: "dangerously"
}).then(dom => {
// The dom's URL is set from the final URL (after redirects)
console.log(dom.window.location.href);
// Content-Type header determines the document's content type
console.log(dom.window.document.contentType);
});
// Cookies are handled automatically
const { CookieJar } = require("jsdom");
const cookieJar = new CookieJar();
JSDOM.fromURL("https://example.com/", { cookieJar }).then(dom => {
// Cookies from Set-Cookie headers are stored in the jar
// Cookies in the jar are sent with the request
});
// Using async/await
async function fetchPage() {
const dom = await JSDOM.fromURL("https://example.com/");
return dom.window.document.querySelector("h1").textContent;
}Important Notes:
url or contentType options (determined from response)referrer option becomes the HTTP Referer request headerresources option affects the initial request (e.g., for proxy configuration)Promise-returning factory method that creates a jsdom from a local file.
/**
* Creates a JSDOM instance by reading from a file
* @param filename - Path to file (relative to current working directory)
* @param options - Configuration options
* @returns Promise that resolves to JSDOM instance
*/
static fromFile(filename: string, options?: JSDOMOptions): Promise<JSDOM>;Usage Example:
const { JSDOM } = require("jsdom");
// Basic usage
JSDOM.fromFile("./test.html").then(dom => {
console.log(dom.serialize());
});
// With options
JSDOM.fromFile("./test.html", {
url: "https://example.org/",
resources: "usable",
runScripts: "dangerously"
}).then(dom => {
console.log(dom.window.document.title);
});
// Using async/await
async function processFile() {
const dom = await JSDOM.fromFile("./page.html");
return dom.window.document.querySelectorAll("p").length;
}Default Behaviors:
url defaults to a file URL (e.g., file:///path/to/test.html) instead of "about:blank"contentType defaults to "application/xhtml+xml" for .xht, .xhtml, or .xml extensionscontentType defaults to "text/html" for all other extensionsExample with File Extensions:
// HTML file - parsed as text/html
await JSDOM.fromFile("./page.html");
// XHTML file - parsed as application/xhtml+xml
await JSDOM.fromFile("./page.xhtml");
// Override content type
await JSDOM.fromFile("./data.xml", {
contentType: "text/html" // Parse XML file as HTML
});