jackwener/OpenCLI · critical · AuthRequiredError

Not logged in (SAPISID cookie missing)

Error message

Not logged in (SAPISID cookie missing)

What it means

AuthRequiredError thrown before the unlike command runs because no SAPISID cookie exists for www.youtube.com. The SAPISID cookie is only set when the browser profile is signed into a YouTube/Google account, and it is required to build the SAPISIDHASH authorization header for YouTube's internal APIs. The library throws this instead of letting the API call fail later so the caller can prompt for login.

Source

Thrown at clis/youtube/unlike.js:25

cli({
    site: 'youtube',
    name: 'unlike',
    access: 'write',
    description: 'Remove like from a YouTube video',
    domain: 'www.youtube.com',
    strategy: Strategy.COOKIE,
    args: [
        { name: 'url', required: true, positional: true, help: 'YouTube video URL or video ID' },
    ],
    columns: ['status', 'message'],
    func: async (page, kwargs) => {
        const videoId = parseVideoId(String(kwargs.url));
        await prepareYoutubeApiPage(page);
        // Read SAPISID directly from the cookie store via CDP — zero document.cookie round-trip
        const sapisid = await readYoutubeSapisid(page);
        if (!sapisid)
            throw new AuthRequiredError('www.youtube.com', 'Not logged in (SAPISID cookie missing)');
        const result = await page.evaluate(`
      (async () => {
        ${SAPISID_HASH_FN}

        const cfg = window.ytcfg?.data_ || {};
        const apiKey = cfg.INNERTUBE_API_KEY;
        const context = cfg.INNERTUBE_CONTEXT;
        if (!apiKey || !context) return { error: 'config', message: 'YouTube config not found' };

        const authHash = await getSapisidHash(${JSON.stringify(sapisid)}, 'https://www.youtube.com');
        if (!authHash) return { error: 'auth', message: 'Not logged in (SAPISID cookie missing)' };

        const resp = await fetch('/youtubei/v1/like/removelike?key=' + apiKey + '&prettyPrint=false', {
          method: 'POST',
          credentials: 'include',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': authHash,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into www.youtube.com in the browser profile used by the automation (interactively or by loading a persistent profile with valid Google cookies).
  2. Re-run readYoutubeSapisid / verify the SAPISID cookie exists for www.youtube.com before invoking the command.
  3. Point the tool at a persistent user-data-dir profile that retains YouTube session cookies instead of a fresh ephemeral context.
  4. Re-authenticate if Google expired the session, then retry the unlike command.
Defensive patterns

Strategy: try-catch

Validate before calling

const sapisid = await readYoutubeSapisid(page);
if (!sapisid) throw new Error('YouTube login required: SAPISID cookie missing');

Try / catch

try {
  await unlike({ url });
} catch (e) {
  if (e.name === 'AuthRequiredError') {
    await loginToYoutube(browserProfile);
    return unlike({ url });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the youtube unlike command while the automation browser profile is not logged into YouTube, or the profile's cookies were cleared/expired so readYoutubeSapisid(page) returns a falsy value.

Common situations: Running headless automation with a fresh (never-logged-in) browser profile; Google signed the user out; cookie store wiped between runs; using a profile for a different Google account without YouTube session; incognito context with no persistent cookies.

Related errors


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