A JavaScript implementation of many web standards
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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
});