or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mddom-apis.mdindex.mdjsdom-class.mdresources.mdtroubleshooting.mdvirtual-console.md
tile.json

configuration.mddocs/

0

# Configuration

1

2

jsdom provides comprehensive configuration options through the JSDOM constructor's `options` parameter. These options control document properties, script execution, resource loading, visual rendering simulation, and more.

3

4

## Capabilities

5

6

### Basic Document Options

7

8

Options that control document properties and metadata.

9

10

#### url

11

12

```javascript { .api }

13

/**

14

* Set the document URL

15

* @default "about:blank"

16

*/

17

url?: string

18

```

19

20

Sets `window.location`, `document.URL`, and `document.documentURI`. Affects relative URL resolution within the document and same-origin restrictions for subresources.

21

22

**Must be a valid absolute URL**. URLs are canonicalized according to the URL Standard.

23

24

**Usage Examples:**

25

26

```javascript

27

const { JSDOM } = require("jsdom");

28

29

const dom = new JSDOM(`<img src="logo.png">`, {

30

url: "https://example.com/page.html"

31

});

32

33

console.log(dom.window.location.href); // "https://example.com/page.html"

34

console.log(dom.window.document.URL); // "https://example.com/page.html"

35

console.log(dom.window.document.querySelector("img").src);

36

// "https://example.com/logo.png" (resolved relative to URL)

37

38

// URL canonicalization

39

const dom2 = new JSDOM(``, { url: "http:example.com" });

40

console.log(dom2.window.location.href); // "http://example.com/"

41

```

42

43

#### referrer

44

45

```javascript { .api }

46

/**

47

* Set the document referrer

48

* @default "" (empty string)

49

*/

50

referrer?: string

51

```

52

53

Sets `document.referrer`. Must be a valid absolute URL if provided. URLs are canonicalized before use.

54

55

**Usage Examples:**

56

57

```javascript

58

const { JSDOM } = require("jsdom");

59

60

const dom = new JSDOM(``, {

61

referrer: "https://google.com/"

62

});

63

64

console.log(dom.window.document.referrer); // "https://google.com/"

65

66

// Default is empty string

67

const dom2 = new JSDOM(``);

68

console.log(dom2.window.document.referrer); // ""

69

```

70

71

#### contentType

72

73

```javascript { .api }

74

/**

75

* Set the content type and parsing mode

76

* @default "text/html"

77

*/

78

contentType?: string

79

```

80

81

Affects `document.contentType` and determines how the document is parsed (HTML vs XML). Must be a valid HTML MIME type or XML MIME type.

82

83

Can include a `charset` parameter for encoding sniffing (though BOM takes precedence).

84

85

**Valid HTML MIME types:** `"text/html"`, `"application/xhtml+xml"`

86

87

**Valid XML MIME types:** `"application/xml"`, `"text/xml"`, `"image/svg+xml"`, etc.

88

89

**Usage Examples:**

90

91

```javascript

92

const { JSDOM } = require("jsdom");

93

94

// HTML parsing (default)

95

const htmlDom = new JSDOM(`<p>test</p>`, {

96

contentType: "text/html"

97

});

98

console.log(htmlDom.window.document.contentType); // "text/html"

99

100

// XML parsing

101

const xmlDom = new JSDOM(`<doc><item/></doc>`, {

102

contentType: "application/xhtml+xml"

103

});

104

console.log(xmlDom.window.document.contentType); // "application/xhtml+xml"

105

106

// With charset parameter

107

const dom = new JSDOM(buffer, {

108

contentType: "text/html; charset=utf-8"

109

});

110

console.log(dom.window.document.contentType); // "text/html" (parameter not shown)

111

112

// Invalid content type throws

113

try {

114

new JSDOM(``, { contentType: "application/json" });

115

} catch (e) {

116

console.error("Not a valid HTML or XML MIME type");

117

}

118

```

119

120

### Parsing Options

121

122

Options that affect how HTML is parsed and tracked.

123

124

#### includeNodeLocations

125

126

```javascript { .api }

127

/**

128

* Preserve source code location information

129

* @default false

130

*/

131

includeNodeLocations?: boolean

132

```

133

134

When `true`, preserves location info produced by the HTML parser, enabling the `nodeLocation()` method. Also ensures correct line numbers in exception stack traces for `<script>` elements.

135

136

**Cannot be used with XML content types** (XML parser doesn't support location info).

137

138

Disabled by default for performance.

139

140

**Usage Examples:**

141

142

```javascript

143

const { JSDOM } = require("jsdom");

144

145

const dom = new JSDOM(`<p>Hello</p>`, {

146

includeNodeLocations: true

147

});

148

149

const p = dom.window.document.querySelector("p");

150

const location = dom.nodeLocation(p);

151

console.log(location);

152

// { startOffset: 0, endOffset: 12, startLine: 1, ... }

153

154

// Without the option, nodeLocation() throws

155

const dom2 = new JSDOM(`<p>Hello</p>`);

156

try {

157

dom2.nodeLocation(dom2.window.document.querySelector("p"));

158

} catch (e) {

159

console.error("Location information was not saved");

160

}

161

162

// Cannot use with XML

163

try {

164

new JSDOM(`<doc/>`, {

165

contentType: "application/xml",

166

includeNodeLocations: true

167

});

168

} catch (e) {

169

console.error("Cannot set includeNodeLocations with XML");

170

}

171

```

172

173

### Script Execution Options

174

175

Options that control script execution behavior and security.

176

177

#### runScripts

178

179

```javascript { .api }

180

/**

181

* Control script execution mode

182

* @default undefined (no script execution)

183

*/

184

runScripts?: "dangerously" | "outside-only"

185

```

186

187

Controls whether and how JavaScript code executes within the jsdom.

188

189

**Values:**

190

191

- **`undefined` (default)**: Scripts don't execute. `<script>` tags are parsed but not run. Event handler attributes don't function. `window.eval` === Node.js `eval`.

192

193

- **`"dangerously"`**: Executes `<script>` tags and event handler attributes. **Security warning**: The sandbox is not foolproof - code can escape to Node.js environment if it tries hard enough. **Only use with trusted content**.

194

195

- **`"outside-only"`**: Provides fresh JavaScript globals (`window.Array`, `window.Promise`, `window.eval`, etc.) for external script execution, but doesn't run inline `<script>` tags or event handler attributes. Safe to enable. Use `window.eval()` or VM module to run code.

196

197

**Usage Examples:**

198

199

```javascript

200

const { JSDOM } = require("jsdom");

201

202

// Default: scripts don't run

203

const dom1 = new JSDOM(`

204

<div id="content"></div>

205

<script>

206

document.getElementById("content").innerHTML = "<p>Added</p>";

207

</script>

208

`);

209

console.log(dom1.window.document.getElementById("content").children.length); // 0

210

211

// "dangerously": scripts run (SECURITY WARNING!)

212

const dom2 = new JSDOM(`

213

<div id="content"></div>

214

<script>

215

document.getElementById("content").innerHTML = "<p>Added</p>";

216

</script>

217

`, { runScripts: "dangerously" });

218

console.log(dom2.window.document.getElementById("content").children.length); // 1

219

220

// "outside-only": run scripts from outside

221

const dom3 = new JSDOM(`

222

<div id="content"></div>

223

<script>

224

// This won't run

225

document.getElementById("content").innerHTML = "<p>From inside</p>";

226

</script>

227

`, { runScripts: "outside-only" });

228

229

// Script didn't run

230

console.log(dom3.window.document.getElementById("content").children.length); // 0

231

232

// But we can run code from outside

233

dom3.window.eval(`

234

document.getElementById("content").innerHTML = "<p>From outside</p>";

235

`);

236

console.log(dom3.window.document.getElementById("content").children.length); // 1

237

238

// Event handler attributes require "dangerously"

239

const dom4 = new JSDOM(`<button onclick="console.log('clicked')">Click</button>`, {

240

runScripts: "dangerously"

241

});

242

// onclick will work

243

244

// But event handler properties work regardless

245

const dom5 = new JSDOM(`<button>Click</button>`);

246

const button = dom5.window.document.querySelector("button");

247

button.onclick = () => console.log("clicked"); // This works

248

```

249

250

### Resource Loading Options

251

252

Options that control loading of external resources.

253

254

#### resources

255

256

```javascript { .api }

257

/**

258

* Configure resource loading

259

* @default undefined (no resources loaded)

260

*/

261

resources?: "usable" | ResourceLoader

262

```

263

264

Controls whether and how jsdom loads subresources (scripts, stylesheets, images, iframes).

265

266

**Values:**

267

268

- **`undefined` (default)**: No subresources loaded

269

270

- **`"usable"`**: Loads all usable resources:

271

- Frames and iframes via `<frame>` and `<iframe>`

272

- Stylesheets via `<link rel="stylesheet">`

273

- Scripts via `<script src="">` (only if `runScripts: "dangerously"`)

274

- Images via `<img>` (only if `canvas` npm package installed)

275

276

- **ResourceLoader instance**: Custom resource loader for advanced control

277

278

**Note:** Default `url` is `"about:blank"`, so relative URLs will fail to load. Set a proper `url` option when using resource loading.

279

280

**Usage Examples:**

281

282

```javascript

283

const { JSDOM, ResourceLoader } = require("jsdom");

284

285

// Load usable resources

286

const dom = new JSDOM(`

287

<!DOCTYPE html>

288

<html>

289

<head>

290

<link rel="stylesheet" href="styles.css">

291

<script src="app.js"></script>

292

</head>

293

<body><img src="logo.png"></body>

294

</html>

295

`, {

296

url: "https://example.com/",

297

resources: "usable",

298

runScripts: "dangerously" // Required for <script> loading

299

});

300

301

// Custom resource loader

302

class MyResourceLoader extends ResourceLoader {

303

fetch(url, options) {

304

if (url.endsWith(".css")) {

305

return Promise.resolve(Buffer.from("body { margin: 0; }"));

306

}

307

return super.fetch(url, options);

308

}

309

}

310

311

const dom2 = new JSDOM(`<link rel="stylesheet" href="custom.css">`, {

312

url: "https://example.com/",

313

resources: new MyResourceLoader()

314

});

315

316

// No resources loaded (default)

317

const dom3 = new JSDOM(`<script src="script.js"></script>`);

318

// script.js won't load

319

```

320

321

### Visual Rendering Options

322

323

Options that simulate visual browser behavior.

324

325

#### pretendToBeVisual

326

327

```javascript { .api }

328

/**

329

* Pretend to be a visual browser

330

* @default false

331

*/

332

pretendToBeVisual?: boolean

333

```

334

335

When `true`, jsdom pretends to render and display content. Does **not** actually implement layout or rendering.

336

337

**Effects:**

338

339

- Sets `document.hidden` to `false` (instead of `true`)

340

- Sets `document.visibilityState` to `"visible"` (instead of `"prerender"`)

341

- Enables `window.requestAnimationFrame()` and `window.cancelAnimationFrame()` methods

342

343

**Usage Examples:**

344

345

```javascript

346

const { JSDOM } = require("jsdom");

347

348

// Default: acts as headless

349

const dom1 = new JSDOM();

350

console.log(dom1.window.document.hidden); // true

351

console.log(dom1.window.document.visibilityState); // "prerender"

352

console.log(typeof dom1.window.requestAnimationFrame); // "undefined"

353

354

// Pretend to be visual

355

const dom2 = new JSDOM(``, { pretendToBeVisual: true });

356

console.log(dom2.window.document.hidden); // false

357

console.log(dom2.window.document.visibilityState); // "visible"

358

console.log(typeof dom2.window.requestAnimationFrame); // "function"

359

360

// Use requestAnimationFrame

361

dom2.window.requestAnimationFrame(timestamp => {

362

console.log("Animation frame:", timestamp);

363

});

364

```

365

366

### Storage Options

367

368

Options that control Web Storage behavior.

369

370

#### storageQuota

371

372

```javascript { .api }

373

/**

374

* Maximum storage size for localStorage and sessionStorage

375

* @default 5000000 (5 million code units per origin)

376

*/

377

storageQuota?: number

378

```

379

380

Maximum size in code units for the separate storage areas used by `localStorage` and `sessionStorage`. Attempting to store data exceeding this limit throws a `DOMException`.

381

382

Default is 5,000,000 code units per origin, as inspired by the HTML specification.

383

384

**Usage Examples:**

385

386

```javascript

387

const { JSDOM } = require("jsdom");

388

389

// Default quota

390

const dom1 = new JSDOM(``, { url: "https://example.com/" });

391

dom1.window.localStorage.setItem("key", "value"); // Works

392

393

// Small quota

394

const dom2 = new JSDOM(``, {

395

url: "https://example.com/",

396

storageQuota: 100

397

});

398

399

try {

400

// Try to store more than 100 code units

401

const largeData = "x".repeat(101);

402

dom2.window.localStorage.setItem("key", largeData);

403

} catch (e) {

404

console.error("QuotaExceededError:", e.name);

405

}

406

```

407

408

### Console and Cookie Options

409

410

Options for console output capture and cookie management.

411

412

#### virtualConsole

413

414

```javascript { .api }

415

/**

416

* Virtual console for capturing output

417

* @default new VirtualConsole().forwardTo(console)

418

*/

419

virtualConsole?: VirtualConsole

420

```

421

422

Provides a VirtualConsole instance for capturing console output from within jsdom. Default forwards all output to Node.js console.

423

424

See [Virtual Console](./virtual-console.md) for detailed documentation.

425

426

**Usage Examples:**

427

428

```javascript

429

const { JSDOM, VirtualConsole } = require("jsdom");

430

431

// Custom virtual console

432

const virtualConsole = new VirtualConsole();

433

virtualConsole.on("log", (message) => {

434

console.log("Page logged:", message);

435

});

436

virtualConsole.on("error", (message) => {

437

console.error("Page error:", message);

438

});

439

440

const dom = new JSDOM(`

441

<script>console.log("Hello from page");</script>

442

`, {

443

runScripts: "dangerously",

444

virtualConsole: virtualConsole

445

});

446

// Logs: "Page logged: Hello from page"

447

```

448

449

#### cookieJar

450

451

```javascript { .api }

452

/**

453

* Cookie jar for HTTP cookie storage

454

* @default new CookieJar()

455

*/

456

cookieJar?: CookieJar

457

```

458

459

Provides a CookieJar instance for cookie storage. Useful for sharing cookies across multiple jsdom instances or priming cookies before creation.

460

461

See [Resources](./resources.md) for detailed documentation.

462

463

**Usage Examples:**

464

465

```javascript

466

const { JSDOM, CookieJar } = require("jsdom");

467

468

// Shared cookie jar

469

const cookieJar = new CookieJar();

470

471

const dom1 = new JSDOM(``, {

472

url: "https://example.com/",

473

cookieJar: cookieJar

474

});

475

476

// Set cookie via document.cookie

477

dom1.window.document.cookie = "session=abc123";

478

479

// Cookie available in another jsdom with same jar

480

const dom2 = new JSDOM(``, {

481

url: "https://example.com/",

482

cookieJar: cookieJar

483

});

484

485

console.log(dom2.window.document.cookie); // "session=abc123"

486

487

// Pre-populate cookies

488

const prePopulatedJar = new CookieJar();

489

prePopulatedJar.setCookieSync("token=xyz789", "https://example.com/");

490

491

const dom3 = new JSDOM(``, {

492

url: "https://example.com/",

493

cookieJar: prePopulatedJar

494

});

495

496

console.log(dom3.window.document.cookie); // "token=xyz789"

497

```

498

499

### Advanced Options

500

501

Options for advanced use cases.

502

503

#### beforeParse

504

505

```javascript { .api }

506

/**

507

* Callback invoked before HTML parsing

508

* @default no-op function

509

*/

510

beforeParse?: (window: Window) => void

511

```

512

513

Callback function invoked after `Window` and `Document` objects are created, but before any HTML is parsed. Useful for modifying the environment, adding shims, or injecting globals before the page loads.

514

515

**Parameters:**

516

517

- `window`: The Window object (global proxy)

518

519

**Usage Examples:**

520

521

```javascript

522

const { JSDOM } = require("jsdom");

523

524

const dom = new JSDOM(`<p>Hello</p>`, {

525

beforeParse(window) {

526

// Window and document exist, but no nodes parsed yet

527

console.log(window.document.childNodes.length); // 0

528

529

// Add custom API

530

window.myCustomAPI = () => {

531

return "Custom functionality";

532

};

533

534

// Add shim for missing API

535

if (!window.someAPI) {

536

window.someAPI = () => {

537

console.log("Shimmed API");

538

};

539

}

540

541

// Modify navigator

542

window.navigator.userAgent = "Custom User Agent";

543

}

544

});

545

546

// Custom API is available

547

console.log(dom.window.myCustomAPI()); // "Custom functionality"

548

549

// HTML has been parsed

550

console.log(dom.window.document.querySelector("p").textContent); // "Hello"

551

```

552

553

## Complete Options Interface

554

555

```javascript { .api }

556

/**

557

* Configuration options for JSDOM constructor

558

*/

559

interface JSDOMOptions {

560

/** Document URL (default: "about:blank") */

561

url?: string;

562

563

/** Document referrer (default: "") */

564

referrer?: string;

565

566

/** Content type for parsing (default: "text/html") */

567

contentType?: string;

568

569

/** Enable node location tracking for source mapping (default: false) */

570

includeNodeLocations?: boolean;

571

572

/** Storage quota for localStorage/sessionStorage in code units (default: 5000000) */

573

storageQuota?: number;

574

575

/** Script execution mode (default: undefined) */

576

runScripts?: "dangerously" | "outside-only";

577

578

/** Resource loading configuration (default: undefined) */

579

resources?: "usable" | ResourceLoader;

580

581

/** Pretend to be a visual browser (default: false) */

582

pretendToBeVisual?: boolean;

583

584

/** Virtual console for output capture (default: new VirtualConsole().forwardTo(console)) */

585

virtualConsole?: VirtualConsole;

586

587

/** Cookie jar for cookie storage (default: new CookieJar()) */

588

cookieJar?: CookieJar;

589

590

/** Callback before HTML parsing (default: no-op) */

591

beforeParse?: (window: Window) => void;

592

}

593

```

594

595

## Common Configuration Patterns

596

597

### Testing Environment

598

599

```javascript

600

const { JSDOM } = require("jsdom");

601

602

const dom = new JSDOM(`<!DOCTYPE html><body></body>`, {

603

url: "https://example.org/",

604

referrer: "https://google.com/",

605

contentType: "text/html",

606

runScripts: "dangerously",

607

resources: "usable",

608

pretendToBeVisual: true

609

});

610

611

// Make available globally for tests

612

global.window = dom.window;

613

global.document = dom.window.document;

614

global.navigator = dom.window.navigator;

615

```

616

617

### Web Scraping

618

619

```javascript

620

const { JSDOM } = require("jsdom");

621

622

JSDOM.fromURL("https://example.com/", {

623

resources: "usable",

624

runScripts: "dangerously"

625

}).then(dom => {

626

const title = dom.window.document.title;

627

const content = dom.window.document.querySelector(".content").textContent;

628

console.log({ title, content });

629

});

630

```

631

632

### Safe Script Execution

633

634

```javascript

635

const { JSDOM } = require("jsdom");

636

637

const dom = new JSDOM(`<!DOCTYPE html><body></body>`, {

638

url: "https://example.org/",

639

runScripts: "outside-only"

640

});

641

642

// Run code safely from outside

643

dom.window.eval(`

644

document.body.innerHTML = '<h1>Safe execution</h1>';

645

`);

646

```

647

648

### Debug Mode

649

650

```javascript

651

const { JSDOM, VirtualConsole } = require("jsdom");

652

653

const virtualConsole = new VirtualConsole();

654

virtualConsole.on("log", msg => console.log("[Page]", msg));

655

virtualConsole.on("error", msg => console.error("[Page Error]", msg));

656

virtualConsole.on("jsdomError", e => console.error("[jsdom Error]", e));

657

658

const dom = new JSDOM(`<!DOCTYPE html><script>console.log("Hi!");</script>`, {

659

runScripts: "dangerously",

660

virtualConsole: virtualConsole,

661

includeNodeLocations: true,

662

resources: "usable"

663

});

664

```

665