Skip to main content

Ephemeral vs. Session mode

By default, each fetch() call runs in ephemeral mode. This is a good fit for one-off requests. For multi-step flows (like login sequences), use sessions to persist state.
ScenarioRecommendedWhy
One-off request, no cookie carryoverEphemeral (default)Request context is isolated per call
Multi-step login or reuse cookiesSessionShared session context
Parallel jobs that must stay isolatedEphemeral or per-job sessionAvoid cross-talk between tasks

Creating a session

import { createSession } from 'wreq-js';

const session = await createSession({ browser: 'chrome_142' });

// All requests share the same cookie jar
await session.fetch('https://example.com/login', {
  method: 'POST',
  body: new URLSearchParams({ user: 'name', pass: 'secret' }),
});

// Cookies from login are automatically included
const dashboard = await session.fetch('https://example.com/dashboard');
console.log(await dashboard.text());

// Always close when done
await session.close();

Auto-disposing sessions

Use withSession() to automatically close the session when done:
import { withSession } from 'wreq-js';

await withSession(async (session) => {
  await session.fetch('https://example.com/login', {
    method: 'POST',
    body: 'credentials',
  });
  
  const data = await session.fetch('https://example.com/data');
  console.log(await data.json());
}); // Session is automatically closed here

Session options

Sessions accept browser, os, proxy, timeout, insecure, and defaultHeaders:
const session = await createSession({
  browser: 'chrome_142',
  os: 'windows',
  proxy: 'http://proxy.example.com:8080',
  insecure: false,
});

Per-request overrides

Within a session, browser, os, and proxy are fixed at creation time unless you pass an explicit transport for that request. You can still override per-request values like timeout, headers, redirect, and body:
const session = await createSession({
  browser: 'chrome_142',
  timeout: 30_000,
});

// Override timeout for a single request
await session.fetch('https://example.com', {
  timeout: 5_000,
  headers: {
    'accept': 'text/html,application/xhtml+xml',
  },
});
Sessions automatically handle cookies across requests, but you can also read and write cookies directly.

Reading cookies

Use getCookies(url) to inspect which cookies would be sent to a URL:
await session.fetch('https://example.com/login', {
  method: 'POST',
  body: new URLSearchParams({ user: 'name', pass: 'secret' }),
});

const cookies = session.getCookies('https://example.com');
console.log(cookies);
// { "session_id": "abc123", "csrf": "xyz" }

Setting cookies manually

Use setCookie(name, value, url) to inject a cookie into the session jar:
session.setCookie('auth_token', 'my-token', 'https://example.com');

// Subsequent requests to example.com will include the cookie
const resp = await session.fetch('https://example.com/api');

Clearing cookies

Use clearCookies() to remove all cookies from the session:
await session.clearCookies();

Session isolation

Each session maintains its own:
  1. Cookie jar: cookies are not shared between sessions
  2. Session identifier and defaults
If you want separate cookie jars but shared transport settings (for example, multiple sessions through the same proxy), use a shared Transport per request.
// These sessions are completely isolated
const session1 = await createSession({ browser: 'chrome_142' });
const session2 = await createSession({ browser: 'firefox_139' });

// Cookies set in session1 do not affect session2
await session1.fetch('https://example.com/set-cookie');
await session2.fetch('https://example.com/check-cookie'); // No cookie present

Best practices

Always close sessions

Call session.close() or use withSession() to prevent resource leaks.

One session per flow

Use a dedicated session for each logical user flow or task.

Parallel isolation

For parallel scraping, create separate sessions to avoid cookie cross-contamination.

Reuse for workflow consistency

Sessions keep one context for multi-step flows.