jackwener/OpenCLI · error · AuthRequiredError

x.com

Error message

x.com

What it means

AuthRequiredError with site 'x.com' is thrown when the browser session has no ct0 cookie, which x.com sets on login. The likes endpoint requires authenticated GraphQL requests, so the CLI checks cookies via page.getCookies({ url: 'https://x.com' }) before doing anything and fails fast with the site name and reason 'Not logged into x.com (no ct0 cookie)'.

Source

Thrown at clis/twitter/likes.js:231

        }
        if (outputFile && !fetchAll) {
            throw new ArgumentError('--output-file requires --all');
        }
        if (resumeFile && !fetchAll) {
            throw new ArgumentError('--resume-file requires --all');
        }
        if (outputFile && !resumeFile) {
            throw new ArgumentError('--output-file requires --resume-file so partial archives remain resumable');
        }
        const rawUsername = String(kwargs.username ?? '').trim();
        let username = normalizeTwitterScreenName(rawUsername);
        if (rawUsername && !username) {
            throw new ArgumentError('twitter likes username must be a valid Twitter/X handle', 'Example: opencli twitter likes @jack --limit 20');
        }
        const cookies = await page.getCookies({ url: 'https://x.com' });
        const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
        if (!ct0)
            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
        // If no username provided, detect the logged-in user.
        // Bridge wraps primitive page.evaluate returns as { session, data:<value> };
        // unwrap so the href string is usable downstream.
        if (!username) {
            // Force a navigation to the home surface so the AppTabBar sidebar
            // is rendered; the framework pre-nav lands on bare x.com which
            // does not always expose AppTabBar_Profile_Link.
            await page.goto('https://x.com/home');
            await page.wait({ selector: '[data-testid="primaryColumn"]' });
            const href = unwrapBrowserResult(await page.evaluate(`() => {
        const link = document.querySelector('a[data-testid="AppTabBar_Profile_Link"]');
        return link ? link.getAttribute('href') : null;
      }`));
            if (!href || typeof href !== 'string')
                throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');
            username = normalizeTwitterScreenName(href);
            if (!username)
                throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into x.com in the browser session the CLI uses, then re-run the command.
  2. Point the CLI at the browser profile where you are already logged in (persistent user-data-dir).
  3. Verify the cookie exists: page.getCookies({ url: 'https://x.com' }) should include { name: 'ct0' }; re-login if missing.

Example fix

// before: throwaway headless profile, never logged in
const page = await browser.newPage();
// after: use a persistent profile where x.com login persists
const context = await browser.newContext({ userDataDir: '/home/me/pw-profile' });
await page.goto('https://x.com/login'); // complete login once
await cli({ username: '@jack', ... });
Defensive patterns

Strategy: try-catch

Validate before calling

const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some((c) => c.name === 'ct0')) {
  throw new Error('Not logged into x.com — log in before running likes');
}

Type guard

function hasCt0(cookies) {
  return Array.isArray(cookies) && cookies.some((c) => c.name === 'ct0' && c.value);
}

Try / catch

try {
  await cli({ username });
} catch (err) {
  if (err instanceof AuthRequiredError && err.site === 'x.com') {
    await interactiveLogin('https://x.com/login'); // then retry once
  }
}

Prevention

When it happens

Trigger: Running the likes command with a browser profile/page that was never logged into x.com, or after the session was cleared/expired, so getCookies finds no cookie named 'ct0'.

Common situations: Fresh automation browser profile with no login; cookies cleared by a cleanup job; x.com logged the session out due to inactivity or password change; pointing at the wrong profile directory.

Related errors


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