jackwener/OpenCLI · error · CommandExecutionError

LinkedIn redirected away from the search page (${result.erro

Error message

LinkedIn redirected away from the search page (${result.error}). Likely Commercial Use Limit reached - the limit resets on the 1st of next month.

What it means

If the extraction script reports result.error but the page does not look like the auth wall, the library concludes LinkedIn redirected away from the people-search results — which in practice means the account's Commercial Use Limit (CUL) for search was reached or the account is otherwise gated. It throws CommandExecutionError advising the user that CUL resets on the 1st of the next month.

Source

Thrown at clis/linkedin/people-search.js:228

        }
        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 in the browser.');
        }

        let result;
        try {
            result = unwrapEvaluateResult(await page.evaluate(extractionScript()));
        } catch (error) {
            throw new CommandExecutionError(`LinkedIn people search extraction failed: ${error?.message || error}`);
        }
        if (result?.error) {
            if (looksLinkedInAuthWall(`${result.url || ''} ${result.error || ''}`)) {
                throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn people search requires an active signed-in browser session.');
            }
            // If LinkedIn redirected away from the search page that
            // usually means CUL was reached or the account is gated.
            throw new CommandExecutionError(`LinkedIn redirected away from the search page (${result.error}). Likely Commercial Use Limit reached - the limit resets on the 1st of next month.`);
        }
        if (!result || typeof result !== 'object') {
            throw new CommandExecutionError('LinkedIn people search returned malformed extraction payload');
        }
        const candidateCount = parseNonNegativeCount(result.candidate_count, 'candidate_count');
        parseNonNegativeCount(result.person_entries_count, 'person_entries_count');
        const resolvedCount = parseNonNegativeCount(result.resolved_count, 'resolved_count');
        const rows = normalizePeopleRows(result.rows);
        if (rows.length === 0 && (candidateCount > 0 || resolvedCount > 0)) {
            throw new CommandExecutionError('LinkedIn people search found profile candidates but could not parse stable result rows');
        }
        if (rows.length === 0) {
            throw new EmptyResultError(`No people found on the rendered page for "${keywords}". The search may have returned zero results, or the DOM markup may have changed.`);
        }
        return rows.slice(0, limit).map((p, i) => ({ rank: i + 1, ...p }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Wait until the 1st of next month for CUL to reset, then retry
  2. Reduce search volume / spread queries across the month (respect the --limit flag)
  3. Use an account tier that includes commercial search (Premium/Sales Navigator/Recruiter)
  4. Check the account in a browser: if linkedin.com shows an upgrade/limit banner, that confirms CUL
  5. Distinguish from auth issues — if a login wall appears instead, fix auth first (see 2345/2347)

Example fix

// before: hard loop burning remaining CUL
for (const kw of keywords) await cli('linkedin people-search', { keywords: kw });
// after: stop on CUL error
try { await cli('linkedin people-search', { keywords: kw }); }
catch (e) { if (String(e.message).includes('Commercial Use Limit')) break; throw e; }
Defensive patterns

Strategy: fallback

Validate before calling

// track monthly search usage yourself and stop before LinkedIn's CUL
const used = await getMonthlySearchCount();
if (used >= CUL_BUDGET) throw new Error('Local CUL budget reached; skip searches until next month');

Type guard

null

Try / catch

try { await cli('linkedin people-search', args); }
catch (e) { if (/Commercial Use Limit/.test(e.message)) { return fallbackDataSource(args); } throw e; }

Prevention

When it happens

Trigger: result.error set, looksLinkedInAuthWall returns false, and the final URL is not the search page — LinkedIn bounced the search to a generic feed/upgrade page after the monthly CUL quota of searches was exhausted or the account lacks commercial search features.

Common situations: Free/basic accounts after exhausting monthly people-search credits; accounts without Sales Navigator/Recruiter commercial features searching too often; end-of-month quota exhaustion; LinkedIn A/B-gating the account.

Related errors


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