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

resources.mddocs/

0

# Resources

1

2

jsdom provides two classes for managing external resources and HTTP cookies: ResourceLoader for fetching resources (scripts, stylesheets, images) and CookieJar for cookie storage. Both can be customized for advanced use cases.

3

4

## Capabilities

5

6

### ResourceLoader Class

7

8

Handles loading of external resources including scripts, stylesheets, images, and iframes. Supports HTTP/HTTPS, file, and data URLs.

9

10

#### Constructor

11

12

```javascript { .api }

13

/**

14

* Create a resource loader for fetching external resources

15

* @param options - Configuration options

16

* @param options.strictSSL - Require valid SSL certificates (default: true)

17

* @param options.proxy - HTTP proxy URL

18

* @param options.userAgent - Custom User-Agent header

19

*/

20

class ResourceLoader {

21

constructor(options?: {

22

strictSSL?: boolean;

23

proxy?: string;

24

userAgent?: string;

25

});

26

}

27

```

28

29

**Options:**

30

31

- **`strictSSL`** (default: `true`): Require valid SSL certificates for HTTPS requests

32

- **`proxy`** (optional): HTTP proxy address (e.g., `"http://127.0.0.1:9001"`)

33

- **`userAgent`** (optional): Custom User-Agent header. Default: `` `Mozilla/5.0 (${process.platform}) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/${version}` ``

34

35

**Usage Examples:**

36

37

```javascript

38

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

39

40

// Default resource loader

41

const loader1 = new ResourceLoader();

42

43

// Custom configuration

44

const loader2 = new ResourceLoader({

45

userAgent: "My Custom Bot/1.0",

46

strictSSL: false, // Allow self-signed certificates

47

proxy: "http://127.0.0.1:9001"

48

});

49

50

const dom = new JSDOM(`<script src="https://example.com/script.js"></script>`, {

51

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

52

resources: loader2,

53

runScripts: "dangerously"

54

});

55

```

56

57

#### fetch()

58

59

```javascript { .api }

60

/**

61

* Fetch a resource from a URL

62

* @param urlString - URL to fetch

63

* @param options - Request options

64

* @param options.accept - Accept header value

65

* @param options.cookieJar - Cookie jar for request

66

* @param options.referrer - Referrer URL

67

* @param options.element - Element requesting the resource

68

* @returns Promise for Buffer with additional properties

69

*/

70

fetch(

71

urlString: string,

72

options?: {

73

accept?: string;

74

cookieJar?: CookieJar;

75

referrer?: string;

76

element?: Element;

77

}

78

): Promise<Buffer> & {

79

abort(): void;

80

response?: Response;

81

href?: string;

82

getHeader(name: string): string | undefined;

83

}

84

```

85

86

Fetches a resource from a URL. Returns a Promise for a Buffer with additional methods and properties.

87

88

**Parameters:**

89

90

- **`urlString`**: URL to fetch

91

- **`options.accept`** (optional): Accept header value

92

- **`options.cookieJar`** (optional): CookieJar for cookie handling

93

- **`options.referrer`** (optional): Referrer URL for Referer header

94

- **`options.element`** (optional): DOM element requesting the resource (for logging)

95

96

**Returns:** Promise for Buffer with:

97

98

- **`abort()`**: Method to cancel the request

99

- **`response`**: HTTP response object (set when response received)

100

- **`href`**: Final URL after redirects (set when complete)

101

- **`getHeader(name)`**: Get request header value

102

103

**Supported URL Schemes:**

104

105

- **`http://` and `https://`**: HTTP requests with automatic redirect following

106

- **`file://`**: Local file reading

107

- **`data://`**: Data URL parsing

108

109

**HTTP Behavior:**

110

111

- Follows redirects automatically

112

- Returns 2xx status codes as success

113

- Rejects for non-2xx status codes

114

- Default headers:

115

- `User-Agent`: From constructor option

116

- `Accept-Language`: `"en"`

117

- `Accept-Encoding`: `"gzip"`

118

- `Accept`: From options or `"*/*"`

119

- `Referer`: From options (if provided)

120

121

**Usage Examples:**

122

123

```javascript

124

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

125

126

const loader = new ResourceLoader();

127

128

// Simple fetch

129

loader.fetch("https://example.com/data.json").then(buffer => {

130

const json = JSON.parse(buffer.toString());

131

console.log(json);

132

}).catch(error => {

133

console.error("Fetch failed:", error.message);

134

});

135

136

// With options

137

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

138

const cookieJar = new CookieJar();

139

140

const promise = loader.fetch("https://example.com/api/data", {

141

accept: "application/json",

142

cookieJar: cookieJar,

143

referrer: "https://example.com/page"

144

});

145

146

promise.then(buffer => {

147

console.log("Final URL:", promise.href);

148

console.log("Status:", promise.response.statusCode);

149

console.log("Data:", buffer.toString());

150

});

151

152

// Cancel request

153

const cancelablePromise = loader.fetch("https://example.com/large-file.zip");

154

155

setTimeout(() => {

156

cancelablePromise.abort(); // Cancel after 1 second

157

}, 1000);

158

159

cancelablePromise.catch(error => {

160

if (error.isAbortError) {

161

console.log("Request cancelled");

162

}

163

});

164

165

// File URL

166

loader.fetch("file:///path/to/local/file.html").then(buffer => {

167

console.log(buffer.toString());

168

});

169

170

// Data URL

171

loader.fetch("data:text/plain,Hello%20World").then(buffer => {

172

console.log(buffer.toString()); // "Hello World"

173

});

174

```

175

176

#### Subclassing ResourceLoader

177

178

Create custom resource loaders by extending the ResourceLoader class and overriding the `fetch()` method.

179

180

**Usage Examples:**

181

182

```javascript

183

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

184

185

// Custom resource loader with overrides

186

class CustomResourceLoader extends ResourceLoader {

187

fetch(url, options) {

188

// Intercept specific URLs

189

if (url === "https://example.com/special-script.js") {

190

return Promise.resolve(Buffer.from("window.special = true;"));

191

}

192

193

// Mock API endpoints

194

if (url.startsWith("https://api.example.com/")) {

195

const mockData = { status: "ok", data: [] };

196

return Promise.resolve(Buffer.from(JSON.stringify(mockData)));

197

}

198

199

// Block certain domains

200

if (url.includes("blocked-domain.com")) {

201

return Promise.reject(new Error("Domain blocked"));

202

}

203

204

// Log all requests

205

console.log("Fetching:", url);

206

if (options.element) {

207

console.log(" Requested by:", options.element.localName);

208

}

209

210

// Delegate to parent for other URLs

211

return super.fetch(url, options);

212

}

213

}

214

215

const customLoader = new CustomResourceLoader();

216

217

const dom = new JSDOM(`

218

<script src="https://example.com/special-script.js"></script>

219

<script src="https://api.example.com/data"></script>

220

<img src="https://example.com/image.png">

221

`, {

222

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

223

resources: customLoader,

224

runScripts: "dangerously"

225

});

226

```

227

228

### CookieJar Class

229

230

Manages HTTP cookies with browser-like behavior. Extends `tough-cookie.CookieJar` with loose mode enabled by default.

231

232

#### Constructor

233

234

```javascript { .api }

235

/**

236

* Create a cookie jar for HTTP cookie storage

237

* Extends tough-cookie.CookieJar with looseMode: true by default

238

* @param store - Cookie store backend (optional)

239

* @param options - Options passed to tough-cookie

240

*/

241

class CookieJar extends ToughCookieJar {

242

constructor(store?: CookieStore, options?: object);

243

}

244

```

245

246

**Parameters:**

247

248

- **`store`** (optional): Cookie store backend from tough-cookie

249

- **`options`** (optional): Options passed to tough-cookie (jsdom sets `looseMode: true` by default for better browser compatibility)

250

251

**Usage Examples:**

252

253

```javascript

254

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

255

256

// Default cookie jar

257

const jar1 = new CookieJar();

258

259

// With custom store

260

const { MemoryCookieStore } = require("tough-cookie");

261

const jar2 = new CookieJar(new MemoryCookieStore());

262

263

// Use with jsdom

264

const jar3 = new CookieJar();

265

const dom = new JSDOM(``, {

266

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

267

cookieJar: jar3

268

});

269

270

// Set cookie via document.cookie

271

dom.window.document.cookie = "session=abc123; path=/";

272

273

// Access cookies

274

const cookies = jar3.getCookiesSync("https://example.com/");

275

console.log(cookies);

276

```

277

278

#### Cookie Methods

279

280

CookieJar inherits all methods from tough-cookie. Most commonly used:

281

282

```javascript { .api }

283

/**

284

* Set a cookie synchronously

285

* @param cookieOrString - Cookie object or cookie string

286

* @param currentUrl - URL for cookie context

287

* @param options - Cookie options

288

* @returns Cookie object

289

*/

290

setCookieSync(

291

cookieOrString: string | Cookie,

292

currentUrl: string,

293

options?: object

294

): Cookie

295

296

/**

297

* Get cookies synchronously

298

* @param currentUrl - URL for cookie context

299

* @param options - Cookie options

300

* @returns Array of Cookie objects

301

*/

302

getCookiesSync(

303

currentUrl: string,

304

options?: object

305

): Cookie[]

306

307

/**

308

* Set a cookie asynchronously

309

* @param cookieOrString - Cookie object or cookie string

310

* @param currentUrl - URL for cookie context

311

* @param options - Cookie options

312

* @param callback - Callback function

313

*/

314

setCookie(

315

cookieOrString: string | Cookie,

316

currentUrl: string,

317

options?: object,

318

callback?: (error: Error | null, cookie: Cookie) => void

319

): void

320

321

/**

322

* Get cookies asynchronously

323

* @param currentUrl - URL for cookie context

324

* @param options - Cookie options

325

* @param callback - Callback function

326

*/

327

getCookies(

328

currentUrl: string,

329

options?: object,

330

callback?: (error: Error | null, cookies: Cookie[]) => void

331

): void

332

333

/**

334

* Get cookies as string for Cookie header

335

* @param currentUrl - URL for cookie context

336

* @param options - Cookie options

337

* @param callback - Callback function

338

*/

339

getCookieString(

340

currentUrl: string,

341

options?: object,

342

callback?: (error: Error | null, cookieString: string) => void

343

): void

344

345

/**

346

* Get cookies as string synchronously

347

* @param currentUrl - URL for cookie context

348

* @param options - Cookie options

349

* @returns Cookie string for Cookie header

350

*/

351

getCookieStringSync(

352

currentUrl: string,

353

options?: object

354

): string

355

```

356

357

**Usage Examples:**

358

359

```javascript

360

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

361

362

const jar = new CookieJar();

363

364

// Set cookies

365

jar.setCookieSync("session=abc123; Path=/; HttpOnly", "https://example.com/");

366

jar.setCookieSync("user=john; Path=/; Max-Age=3600", "https://example.com/");

367

368

// Get cookies

369

const cookies = jar.getCookiesSync("https://example.com/");

370

console.log(cookies); // Array of Cookie objects

371

372

// Get cookie string (for HTTP Cookie header)

373

const cookieString = jar.getCookieStringSync("https://example.com/");

374

console.log(cookieString); // "session=abc123; user=john"

375

376

// Async operations

377

jar.setCookie("token=xyz789", "https://example.com/", (error, cookie) => {

378

if (error) {

379

console.error("Failed to set cookie:", error);

380

} else {

381

console.log("Cookie set:", cookie.toString());

382

}

383

});

384

385

jar.getCookies("https://example.com/", (error, cookies) => {

386

if (!error) {

387

console.log("Cookies:", cookies);

388

}

389

});

390

```

391

392

#### Cookie Behavior

393

394

**Accessibility:**

395

396

- Cookies on same domain as document URL accessible via `document.cookie`

397

- HTTP-only cookies **not** accessible via `document.cookie`

398

- All cookies in jar affect subresource fetching (including HTTP-only)

399

400

**Sharing:**

401

402

- Cookie jars can be shared across multiple jsdom instances

403

- Useful for maintaining session across page navigations

404

405

**Integration:**

406

407

- Used automatically by `JSDOM.fromURL()` for HTTP requests

408

- Cookies from `Set-Cookie` headers stored in jar

409

- Cookies sent in `Cookie` header for requests

410

411

**Usage Examples:**

412

413

```javascript

414

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

415

416

// Shared cookie jar across instances

417

const sharedJar = new CookieJar();

418

419

const dom1 = new JSDOM(``, {

420

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

421

cookieJar: sharedJar

422

});

423

424

// Set cookie in first instance

425

dom1.window.document.cookie = "shared=value";

426

427

const dom2 = new JSDOM(``, {

428

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

429

cookieJar: sharedJar

430

});

431

432

// Cookie available in second instance

433

console.log(dom2.window.document.cookie); // "shared=value"

434

435

// HTTP-only cookies (not accessible via document.cookie)

436

sharedJar.setCookieSync(

437

"session=secret; Path=/; HttpOnly",

438

"https://example.com/"

439

);

440

441

console.log(dom1.window.document.cookie); // "shared=value" (no session cookie)

442

443

// But HTTP-only cookie sent in HTTP requests

444

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

445

cookieJar: sharedJar

446

}).then(dom => {

447

// Request included both shared and session cookies

448

});

449

```

450

451

### toughCookie Module Export

452

453

jsdom re-exports the `tough-cookie` module for direct access to cookie utilities.

454

455

```javascript { .api }

456

/**

457

* Re-export of tough-cookie module for cookie utilities

458

*/

459

const toughCookie: ToughCookieModule

460

```

461

462

**Provides access to:**

463

464

- `Cookie` class

465

- `CookieJar` class

466

- `Store` classes

467

- Parsing and serialization utilities

468

469

**Usage Examples:**

470

471

```javascript

472

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

473

474

// Use Cookie class

475

const cookie = new toughCookie.Cookie({

476

key: "session",

477

value: "abc123",

478

domain: "example.com",

479

path: "/",

480

httpOnly: true,

481

maxAge: 3600

482

});

483

484

console.log(cookie.toString());

485

// "session=abc123; Domain=example.com; Path=/; HttpOnly; Max-Age=3600"

486

487

// Parse cookie string

488

const parsed = toughCookie.Cookie.parse("user=john; Path=/; Secure");

489

console.log(parsed.key); // "user"

490

console.log(parsed.value); // "john"

491

console.log(parsed.secure); // true

492

```

493

494

## Common Usage Patterns

495

496

### Custom Resource Caching

497

498

```javascript

499

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

500

501

class CachingResourceLoader extends ResourceLoader {

502

constructor(options) {

503

super(options);

504

this.cache = new Map();

505

}

506

507

fetch(url, options) {

508

// Check cache

509

if (this.cache.has(url)) {

510

console.log("Cache hit:", url);

511

return Promise.resolve(this.cache.get(url));

512

}

513

514

// Fetch and cache

515

return super.fetch(url, options).then(buffer => {

516

this.cache.set(url, buffer);

517

console.log("Cached:", url);

518

return buffer;

519

});

520

}

521

}

522

523

const loader = new CachingResourceLoader();

524

const dom = new JSDOM(`

525

<script src="https://example.com/lib.js"></script>

526

`, {

527

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

528

resources: loader,

529

runScripts: "dangerously"

530

});

531

```

532

533

### Session Management

534

535

```javascript

536

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

537

538

async function navigateWithSession(urls) {

539

const sessionJar = new CookieJar();

540

541

for (const url of urls) {

542

const dom = await JSDOM.fromURL(url, {

543

cookieJar: sessionJar,

544

resources: "usable",

545

runScripts: "dangerously"

546

});

547

548

console.log("Page:", dom.window.document.title);

549

console.log("Cookies:", sessionJar.getCookieStringSync(url));

550

551

// Session maintained across requests

552

}

553

}

554

555

navigateWithSession([

556

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

557

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

558

"https://example.com/profile"

559

]);

560

```

561

562

### Mock API Responses

563

564

```javascript

565

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

566

567

class MockAPILoader extends ResourceLoader {

568

constructor(mocks, options) {

569

super(options);

570

this.mocks = mocks;

571

}

572

573

fetch(url, options) {

574

// Check if URL should be mocked

575

for (const [pattern, response] of Object.entries(this.mocks)) {

576

if (url.includes(pattern)) {

577

console.log("Mocked:", url);

578

return Promise.resolve(Buffer.from(JSON.stringify(response)));

579

}

580

}

581

582

// Real fetch for non-mocked URLs

583

return super.fetch(url, options);

584

}

585

}

586

587

const loader = new MockAPILoader({

588

"/api/users": { users: [{ id: 1, name: "Alice" }] },

589

"/api/posts": { posts: [{ id: 1, title: "Test Post" }] }

590

});

591

592

const dom = new JSDOM(`

593

<script>

594

fetch("/api/users")

595

.then(r => r.json())

596

.then(data => console.log(data));

597

</script>

598

`, {

599

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

600

resources: loader,

601

runScripts: "dangerously"

602

});

603

```

604

605

## Types

606

607

```javascript { .api }

608

interface ResourceLoaderOptions {

609

strictSSL?: boolean;

610

proxy?: string;

611

userAgent?: string;

612

}

613

614

interface FetchOptions {

615

accept?: string;

616

cookieJar?: CookieJar;

617

referrer?: string;

618

element?: Element;

619

}

620

621

interface FetchPromise extends Promise<Buffer> {

622

abort(): void;

623

response?: Response;

624

href?: string;

625

getHeader(name: string): string | undefined;

626

}

627

628

interface Cookie {

629

key: string;

630

value: string;

631

domain?: string;

632

path?: string;

633

secure?: boolean;

634

httpOnly?: boolean;

635

expires?: Date;

636

maxAge?: number;

637

sameSite?: "strict" | "lax" | "none";

638

}

639

```

640