0
# JSDOM Class
1
2
The JSDOM class is the main interface for creating and managing jsdom instances. It provides methods for document serialization, node location tracking, VM context access, and runtime reconfiguration.
3
4
## Capabilities
5
6
### Constructor
7
8
Creates a new jsdom instance from HTML string or binary data.
9
10
```javascript { .api }
11
/**
12
* Create a new jsdom instance
13
* @param input - HTML content as string or binary data for encoding sniffing
14
* @param options - Configuration options
15
*/
16
constructor(input?: string | Buffer | ArrayBuffer | TypedArray, options?: JSDOMOptions)
17
```
18
19
**Parameters:**
20
21
- **`input`** (optional): HTML content to parse
22
- `string`: HTML string (most common)
23
- `Buffer`: Node.js Buffer for encoding sniffing
24
- `ArrayBuffer`: Standard JavaScript binary data
25
- `TypedArray`: Uint8Array, DataView, etc.
26
- Default: `""` (empty document)
27
28
- **`options`** (optional): Configuration object (see [Configuration](./configuration.md))
29
30
**Usage Examples:**
31
32
```javascript
33
const { JSDOM } = require("jsdom");
34
35
// From HTML string
36
const dom = new JSDOM(`<!DOCTYPE html><p>Hello</p>`);
37
38
// Empty document
39
const emptyDom = new JSDOM();
40
41
// From binary data (encoding sniffing)
42
const buffer = Buffer.from(htmlBytes);
43
const domFromBuffer = new JSDOM(buffer);
44
45
// With options
46
const configuredDom = new JSDOM(`<!DOCTYPE html><p>Hello</p>`, {
47
url: "https://example.com/",
48
referrer: "https://google.com/",
49
contentType: "text/html",
50
runScripts: "dangerously"
51
});
52
```
53
54
### Instance Properties
55
56
Properties available on JSDOM instances.
57
58
#### window
59
60
```javascript { .api }
61
/**
62
* The Window object containing the DOM and browser APIs
63
*/
64
readonly window: Window
65
```
66
67
Returns the global window object (actually the global proxy for proper JavaScript behavior). This provides access to `document`, `navigator`, and all browser APIs.
68
69
**Usage Examples:**
70
71
```javascript
72
const dom = new JSDOM(`<p>Hello</p>`);
73
74
// Access window
75
const { window } = dom;
76
77
// Use window APIs
78
console.log(window.document.querySelector("p").textContent); // "Hello"
79
console.log(window.location.href); // "about:blank"
80
81
// Or destructure what you need
82
const { document } = dom.window;
83
```
84
85
#### virtualConsole
86
87
```javascript { .api }
88
/**
89
* The VirtualConsole instance for this jsdom
90
*/
91
readonly virtualConsole: VirtualConsole
92
```
93
94
Returns the VirtualConsole used by this jsdom. This is either the one you provided in options or the default one created automatically.
95
96
**Usage Examples:**
97
98
```javascript
99
const { JSDOM } = require("jsdom");
100
101
const dom = new JSDOM(`<!DOCTYPE html>`);
102
103
// Access the virtual console
104
dom.virtualConsole.on("log", (message) => {
105
console.log("Page logged:", message);
106
});
107
```
108
109
#### cookieJar
110
111
```javascript { .api }
112
/**
113
* The CookieJar instance for this jsdom
114
*/
115
readonly cookieJar: CookieJar
116
```
117
118
Returns the CookieJar used by this jsdom for cookie storage. This is either the one you provided in options or the default one created automatically.
119
120
**Usage Examples:**
121
122
```javascript
123
const { JSDOM } = require("jsdom");
124
125
const dom = new JSDOM(`<!DOCTYPE html>`, {
126
url: "https://example.com/"
127
});
128
129
// Access the cookie jar
130
const cookies = dom.cookieJar.getCookiesSync("https://example.com/");
131
console.log(cookies);
132
```
133
134
### Instance Methods
135
136
Methods available on JSDOM instances.
137
138
#### serialize()
139
140
```javascript { .api }
141
/**
142
* Serialize the document to an HTML string including DOCTYPE
143
* @returns Complete HTML string with DOCTYPE
144
*/
145
serialize(): string
146
```
147
148
Returns the HTML serialization of the entire document, including the DOCTYPE declaration.
149
150
**Usage Examples:**
151
152
```javascript
153
const { JSDOM } = require("jsdom");
154
155
const dom = new JSDOM(`<!DOCTYPE html>hello`);
156
console.log(dom.serialize());
157
// "<!DOCTYPE html><html><head></head><body>hello</body></html>"
158
159
// After modifying the DOM
160
const dom2 = new JSDOM(`<p>test</p>`);
161
dom2.window.document.querySelector("p").textContent = "modified";
162
console.log(dom2.serialize());
163
// "<html><head></head><body><p>modified</p></body></html>"
164
```
165
166
**Note:** This differs from `document.documentElement.outerHTML` which doesn't include the DOCTYPE.
167
168
#### nodeLocation()
169
170
```javascript { .api }
171
/**
172
* Get the source code location of a DOM node
173
* @param node - DOM node to get location for
174
* @returns Location info with line, column, and offset information, or undefined for dynamically created nodes
175
* @throws Error if includeNodeLocations option was not set to true
176
*/
177
nodeLocation(node: Node): LocationInfo | undefined
178
```
179
180
Returns the parse5 location info for where a node appears in the original HTML source. Only works if `includeNodeLocations: true` was set during construction.
181
182
**Returns:**
183
184
- `LocationInfo` object for nodes from original source
185
- `undefined` for nodes created via `innerHTML`, `outerHTML`, or `createContextualFragment()`
186
187
**Throws:**
188
189
- `Error` if `includeNodeLocations` was not set to `true`
190
191
**Usage Examples:**
192
193
```javascript
194
const { JSDOM } = require("jsdom");
195
196
const dom = new JSDOM(`<p>Hello
197
<img src="foo.jpg">
198
</p>`, { includeNodeLocations: true });
199
200
const document = dom.window.document;
201
const pEl = document.querySelector("p");
202
const imgEl = document.querySelector("img");
203
204
console.log(dom.nodeLocation(pEl));
205
// { startOffset: 0, endOffset: 39, startLine: 1, endLine: 2,
206
// startCol: 1, endCol: 7, startTag: {...}, endTag: {...} }
207
208
console.log(dom.nodeLocation(imgEl));
209
// { startOffset: 13, endOffset: 32, ... }
210
211
// Dynamically created nodes return undefined
212
pEl.innerHTML = `<div>new</div>`;
213
const divEl = document.querySelector("div");
214
console.log(dom.nodeLocation(divEl)); // undefined
215
```
216
217
**LocationInfo Structure:**
218
219
```javascript
220
{
221
startOffset: number, // Character offset in source
222
endOffset: number,
223
startLine: number, // 1-indexed line number
224
endLine: number,
225
startCol: number, // 1-indexed column number
226
endCol: number,
227
startTag: { // For elements only
228
startOffset: number,
229
endOffset: number,
230
startLine: number,
231
endLine: number,
232
startCol: number,
233
endCol: number,
234
attrs: { // Attribute locations
235
attrName: { startOffset, endOffset, startLine, endLine, startCol, endCol }
236
}
237
},
238
endTag: { ... }, // For elements with closing tags
239
attrs: { ... } // Same as startTag.attrs
240
}
241
```
242
243
#### getInternalVMContext()
244
245
```javascript { .api }
246
/**
247
* Get the Node.js VM context for advanced script execution
248
* @returns Contextified global object for use with Node.js vm module
249
* @throws TypeError if runScripts option was not set
250
*/
251
getInternalVMContext(): object
252
```
253
254
Returns the internal VM context for use with Node.js's `vm` module. Enables advanced use cases like pre-compiling scripts and running them multiple times.
255
256
**Throws:**
257
258
- `TypeError` if `runScripts` option was not set to `"dangerously"` or `"outside-only"`
259
260
**Usage Examples:**
261
262
```javascript
263
const { Script } = require("vm");
264
const { JSDOM } = require("jsdom");
265
266
const dom = new JSDOM(``, { runScripts: "outside-only" });
267
268
// Pre-compile a script
269
const script = new Script(`
270
if (!this.ran) {
271
this.ran = 0;
272
}
273
++this.ran;
274
`);
275
276
// Run it multiple times
277
const vmContext = dom.getInternalVMContext();
278
script.runInContext(vmContext);
279
script.runInContext(vmContext);
280
script.runInContext(vmContext);
281
282
console.log(dom.window.ran); // 3
283
284
// With timeout
285
const infiniteScript = new Script(`while(true) {}`);
286
try {
287
infiniteScript.runInContext(vmContext, { timeout: 50 });
288
} catch (e) {
289
console.error("Script timed out");
290
}
291
```
292
293
#### reconfigure()
294
295
```javascript { .api }
296
/**
297
* Reconfigure the jsdom after creation
298
* @param settings - Settings to change
299
* @param settings.windowTop - Override window.top (normally unforgeable)
300
* @param settings.url - Change the document URL
301
* @throws TypeError if url is invalid
302
*/
303
reconfigure(settings: { windowTop?: any, url?: string }): void
304
```
305
306
Modifies jsdom configuration after creation. Allows changing the normally-unforgeable `window.top` property and updating the document URL.
307
308
**Parameters:**
309
310
- **`settings.windowTop`** (optional): Override `window.top`. Useful for testing scenarios with iframes.
311
- **`settings.url`** (optional): Change the document URL. Must be a valid absolute URL. Updates `window.location`, `document.URL`, `document.documentURI`, base URL resolution, and same-origin checks. Does **not** navigate or fetch new content.
312
313
**Throws:**
314
315
- `TypeError` if `url` is not a valid absolute URL
316
317
**Usage Examples:**
318
319
```javascript
320
const { JSDOM } = require("jsdom");
321
322
const dom = new JSDOM(`<img src="foo.jpg">`, {
323
url: "http://example.com/"
324
});
325
326
console.log(dom.window.location.href); // "http://example.com/"
327
console.log(dom.window.document.querySelector("img").src);
328
// "http://example.com/foo.jpg"
329
330
// Change URL
331
dom.reconfigure({ url: "http://localhost/bar/index.html" });
332
333
console.log(dom.window.location.href); // "http://localhost/bar/index.html"
334
console.log(dom.window.document.querySelector("img").src);
335
// "http://localhost/bar/foo.jpg" (relative URL re-resolved)
336
337
// Override window.top
338
const fakeTop = { is: "top" };
339
dom.reconfigure({ windowTop: fakeTop });
340
console.log(dom.window.top); // { is: "top" }
341
342
// Can set to undefined
343
dom.reconfigure({ windowTop: undefined });
344
console.log(dom.window.top); // undefined
345
```
346
347
### Static Methods
348
349
Static methods on the JSDOM class for convenient instance creation.
350
351
#### JSDOM.fromURL()
352
353
```javascript { .api }
354
/**
355
* Create jsdom by fetching from a URL
356
* @param url - URL to fetch (HTTP/HTTPS)
357
* @param options - Configuration options (url and contentType not allowed)
358
* @returns Promise resolving to JSDOM instance
359
*/
360
static fromURL(url: string, options?: JSDOMOptions): Promise<JSDOM>
361
```
362
363
Factory method that fetches HTML from a URL and creates a jsdom instance. The URL is fetched via HTTP/HTTPS with automatic redirect following.
364
365
**Parameters:**
366
367
- **`url`**: HTTP or HTTPS URL to fetch
368
- **`options`** (optional): Same as constructor options with restrictions:
369
- Cannot include `url` (determined from response URL)
370
- Cannot include `contentType` (determined from Content-Type header)
371
- `referrer` used as HTTP Referer header
372
- `resources` affects initial request (e.g., proxy configuration)
373
- `cookieJar` used for HTTP cookies (sent and received)
374
375
**Returns:** Promise resolving to JSDOM instance
376
377
**Behavior:**
378
379
- Follows HTTP redirects automatically
380
- URL fragment (#hash) preserved from original URL
381
- Content-Type header determines `contentType`
382
- Final URL (after redirects) used as document URL
383
- HTTP cookies handled via `cookieJar` option
384
385
**Usage Examples:**
386
387
```javascript
388
const { JSDOM } = require("jsdom");
389
390
// Simple fetch
391
JSDOM.fromURL("https://example.com/").then(dom => {
392
console.log(dom.serialize());
393
});
394
395
// With options
396
const { CookieJar } = require("jsdom");
397
const cookieJar = new CookieJar();
398
399
JSDOM.fromURL("https://example.com/page.html", {
400
referrer: "https://google.com/",
401
cookieJar: cookieJar,
402
resources: "usable",
403
runScripts: "dangerously"
404
}).then(dom => {
405
console.log(dom.window.document.title);
406
console.log("Cookies:", cookieJar.getCookiesSync("https://example.com/"));
407
});
408
409
// Error handling
410
JSDOM.fromURL("https://example.com/").catch(error => {
411
console.error("Failed to load:", error.message);
412
});
413
```
414
415
#### JSDOM.fromFile()
416
417
```javascript { .api }
418
/**
419
* Create jsdom by reading from a file
420
* @param filename - File path relative to current working directory
421
* @param options - Configuration options
422
* @returns Promise resolving to JSDOM instance
423
*/
424
static fromFile(filename: string, options?: JSDOMOptions): Promise<JSDOM>
425
```
426
427
Factory method that reads HTML from a file and creates a jsdom instance.
428
429
**Parameters:**
430
431
- **`filename`**: File path (relative to current working directory or absolute)
432
- **`options`** (optional): Same as constructor options with defaults:
433
- `url` defaults to `file://` URL for the file
434
- `contentType` defaults to `"application/xhtml+xml"` for `.xhtml`, `.xht`, `.xml` extensions
435
436
**Returns:** Promise resolving to JSDOM instance
437
438
**Usage Examples:**
439
440
```javascript
441
const { JSDOM } = require("jsdom");
442
443
// Read from file
444
JSDOM.fromFile("./test.html").then(dom => {
445
console.log(dom.serialize());
446
});
447
448
// With options
449
JSDOM.fromFile("./page.html", {
450
url: "https://example.com/", // Override default file:// URL
451
contentType: "text/html",
452
runScripts: "dangerously"
453
}).then(dom => {
454
console.log(dom.window.document.title);
455
});
456
457
// Using async/await
458
async function loadPage() {
459
const dom = await JSDOM.fromFile("./index.html");
460
return dom.window.document.querySelector("h1").textContent;
461
}
462
```
463
464
#### JSDOM.fragment()
465
466
```javascript { .api }
467
/**
468
* Create a DocumentFragment from HTML string (lightweight, no full document)
469
* @param string - HTML string to parse
470
* @returns DocumentFragment with parsed content
471
*/
472
static fragment(string?: string): DocumentFragment
473
```
474
475
Factory method for parsing HTML into a DocumentFragment without creating a full jsdom instance. This is lightweight and efficient for simple parsing needs.
476
477
**Parameters:**
478
479
- **`string`** (optional): HTML string to parse. Default: `""`
480
481
**Returns:** DocumentFragment instance
482
483
**Characteristics:**
484
485
- No full document or window object created
486
- Parses as if inside `<template>` element (allows any element type including `<td>`, `<tr>`, etc.)
487
- Resulting fragment has no browsing context (`ownerDocument.defaultView === null`)
488
- All invocations share the same template owner document (very efficient)
489
- No customization options available
490
491
**Usage Examples:**
492
493
```javascript
494
const { JSDOM } = require("jsdom");
495
496
// Parse HTML fragment
497
const frag = JSDOM.fragment(`<p>Hello</p><p><strong>Hi!</strong></p>`);
498
499
console.log(frag.childNodes.length); // 2
500
console.log(frag.querySelector("strong").textContent); // "Hi!"
501
502
// Parse table elements (requires template context)
503
const tableFrag = JSDOM.fragment(`<tr><td>Cell</td></tr>`);
504
console.log(tableFrag.firstChild.nodeName); // "TR"
505
506
// Serialize single element fragment
507
const singleFrag = JSDOM.fragment(`<p>Hello</p>`);
508
console.log(singleFrag.firstChild.outerHTML); // "<p>Hello</p>"
509
510
// Use with actual DOM
511
const frag2 = JSDOM.fragment(`<li>Item 1</li><li>Item 2</li>`);
512
const dom = new JSDOM(`<ul id="list"></ul>`);
513
dom.window.document.getElementById("list").appendChild(frag2);
514
console.log(dom.serialize());
515
// Contains: <ul id="list"><li>Item 1</li><li>Item 2</li></ul>
516
```
517
518
## Types
519
520
```javascript { .api }
521
interface JSDOMOptions {
522
url?: string;
523
referrer?: string;
524
contentType?: string;
525
includeNodeLocations?: boolean;
526
storageQuota?: number;
527
runScripts?: "dangerously" | "outside-only";
528
resources?: "usable" | ResourceLoader;
529
pretendToBeVisual?: boolean;
530
virtualConsole?: VirtualConsole;
531
cookieJar?: CookieJar;
532
beforeParse?: (window: Window) => void;
533
}
534
535
interface LocationInfo {
536
startOffset: number;
537
endOffset: number;
538
startLine: number;
539
endLine: number;
540
startCol: number;
541
endCol: number;
542
startTag?: TagLocationInfo;
543
endTag?: TagLocationInfo;
544
attrs?: Record<string, AttrLocationInfo>;
545
}
546
547
interface TagLocationInfo {
548
startOffset: number;
549
endOffset: number;
550
startLine: number;
551
endLine: number;
552
startCol: number;
553
endCol: number;
554
attrs?: Record<string, AttrLocationInfo>;
555
}
556
557
interface AttrLocationInfo {
558
startOffset: number;
559
endOffset: number;
560
startLine: number;
561
endLine: number;
562
startCol: number;
563
endCol: number;
564
}
565
```
566