or run

npx @tessl/cli init
Log in

Version

Files

docs

api

cookie-management.mdjsdom-constructor.mdresource-loading.mdvirtual-console.mdwindow-dom-apis.md
index.md
tile.json

jsdom-constructor.mddocs/api/

JSDOM Constructor and Methods

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.

Constructor

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);

Constructor Options

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");
  }
});

Instance Properties

/**
 * 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/");

serialize()

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)

nodeLocation()

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)); // null

getInternalVMContext()

Returns 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);

reconfigure()

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 update

Static: fragment()

Creates 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>"

Static: fromURL()

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:

  • Follows redirects automatically
  • Cannot specify url or contentType options (determined from response)
  • referrer option becomes the HTTP Referer request header
  • resources option affects the initial request (e.g., for proxy configuration)
  • Cookies from Set-Cookie headers are stored in the cookie jar
  • Cookies in the jar are sent as Cookie request headers

Static: fromFile()

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 extensions
  • contentType defaults to "text/html" for all other extensions
  • Binary encoding is sniffed from file contents (BOMs, meta charset tags)

Example 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
});