jackwener/OpenCLI · error · AuthRequiredError

LinkedIn JSESSIONID cookie not found. Please sign in to Link

Error message

LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.

What it means

Thrown in clis/linkedin/salesnav-search.js:147 after navigating to Sales Navigator home and reading cookies for https://www.linkedin.com: no cookie named JSESSIONID was present. JSESSIONID is required to derive the csrf-token header for LinkedIn REST API calls. Its absence means the browser is not signed in to LinkedIn (or the session cookie was not scoped to the www domain), so the search cannot authenticate. The error is raised as AuthRequiredError, signaling the user must log in.

Source

Thrown at clis/linkedin/salesnav-search.js:147

  strategy: Strategy.UI,
  browser: true,
  args: [
    { name: 'keywords', type: 'string', required: true, positional: true, help: 'People search keywords, e.g. "quality manager food manufacturing"' },
    { name: 'limit', type: 'number', default: 25, help: 'Maximum leads to return (1-500, fetched 25 per request)' },
  ],
  columns: ['rank', 'name', 'title', 'company', 'location', 'degree', 'profile_url', 'lead_url', 'recipient_urn'],
  func: async (page, args) => {
    if (!page) throw new CommandExecutionError('Browser session required for linkedin salesnav-search');
    const keywords = requireStringArg(args, 'keywords', '--keywords');
    const limit = parseLimit(args.limit);

    await page.goto(SALES_HOME);
    await page.wait(6);

    const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });
    const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;
    if (!jsession) {
      throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.');
    }
    const csrf = jsession.replace(/^\"|\"$/g, '');

    const leads = [];
    const seen = new Set();
    for (let start = 0; leads.length < limit && start < 2000; start += PAGE_SIZE) {
      const result = unwrapEvaluateResult(await page.evaluate(fetchLeadSearchScript(leadSearchUrl(keywords, start), csrf)));
      const json = requireLeadSearchResult(result);
      const pageLeads = parseLeads(json);
      if (pageLeads.length === 0) break;
      for (const lead of pageLeads) {
        const key = lead.profile_url || lead.name.toLowerCase();
        if (seen.has(key)) continue;
        seen.add(key);
        leads.push(lead);
      }
      await page.wait(1);
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Sign in to LinkedIn in the automation browser (run the platform's login flow) and retry the command.
  2. Verify the session by loading https://www.linkedin.com/feed/ and confirming you are not redirected to the login page.
  3. Check cookies manually for a www.linkedin.com JSESSIONID (document.cookie or devtools) to rule out domain-scoping mismatches.
  4. If the profile persists cookies but the session keeps dropping, re-authenticate and avoid sharing the profile across concurrent automation runs.

Example fix

// before (assume cookie exists)
const csrf = jsession.replace(/^"|"$/g, '');
// after (check login state before reading cookies)
await page.goto('https://www.linkedin.com/feed/');
if (/login/.test(page.url())) { await interactiveLogin(page); }
const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });
const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;
if (!jsession) throw new AuthRequiredError('www.linkedin.com', 'sign in first');
Defensive patterns

Strategy: validation

Validate before calling

// Verify login state before the API flow:
await page.goto('https://www.linkedin.com/feed/');
if (/\/login|checkpoint/.test(page.url())) {
  throw new AuthRequiredError('www.linkedin.com', 'Sign in to LinkedIn before running salesnav-search');
}
const hasJsession = (await page.getCookies({ url: 'https://www.linkedin.com' }))
  .some((c) => c.name === 'JSESSIONID' && c.value);
if (!hasJsession) throw new AuthRequiredError('www.linkedin.com', 'JSESSIONID missing; log in again');

Type guard

function hasLinkedInSession(cookies) {
  return Array.isArray(cookies) && cookies.some(
    (c) => c.name === 'JSESSIONID' && typeof c.value === 'string' && c.value.length > 0
  );
}

Try / catch

try {
  const leads = await run('linkedin salesnav-search', [keywords]);
} catch (err) {
  if (err instanceof AuthRequiredError) {
    await interactiveLogin(page); // open login flow, wait for user/2FA
    return run('linkedin salesnav-search', [keywords]);
  }
  throw err;
}

Prevention

When it happens

Trigger: page.getCookies() returns no JSESSIONID because the browser profile is logged out; cookies are scoped to a different domain/subdomain than https://www.linkedin.com; navigating to /sales/ redirected to a login page; cookie expiry or a LinkedIn logout wiping the session.

Common situations: Fresh automation browser profile with no saved LinkedIn login; session expired after LinkedIn's security logout; running from a region/IP that forces re-authentication; using a profile where cookies are stored under linkedin.com without www and the lookup URL filter misses them.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/7bed2e0e78c5f147. Report an issue: GitHub.