jackwener/OpenCLI · error · CommandExecutionError

Instagram private route could not derive X-Instagram-AJAX fr

Error message

Instagram private route could not derive X-Instagram-AJAX from instagram runtime

What it means

The private API route must send the X-Instagram-AJAX header (the rolling request-version value). It comes from the instagram runtime instagramAjax field or captured context; when both are empty this error is thrown before any request is made.

Source

Thrown at clis/instagram/_shared/private-publish.js:116

                page.evaluate(buildReadInstagramRuntimeInfoJs()),
                typeof page.readNetworkCapture === 'function'
                    ? page.readNetworkCapture()
                    : Promise.resolve([]),
            ]);
            const captureEntries = (Array.isArray(entries) ? entries : []);
            const capturedContext = derivePrivateApiContextFromCapture(captureEntries)
                ?? derivePartialPrivateApiContextFromCapture(captureEntries);
            const csrfToken = runtime?.csrfToken || getCookieValue(cookies, 'csrftoken') || capturedContext.csrfToken || '';
            const igAppId = runtime?.appId || capturedContext.igAppId || '';
            const instagramAjax = runtime?.instagramAjax || capturedContext.instagramAjax || '';
            if (!csrfToken) {
                throw new CommandExecutionError('Instagram private route could not derive CSRF token from browser session');
            }
            if (!igAppId) {
                throw new CommandExecutionError('Instagram private route could not derive X-IG-App-ID from instagram runtime');
            }
            if (!instagramAjax) {
                throw new CommandExecutionError('Instagram private route could not derive X-Instagram-AJAX from instagram runtime');
            }
            const asbdId = capturedContext.asbdId || '';
            const igWwwClaim = capturedContext.igWwwClaim || '';
            const webSessionId = capturedContext.webSessionId || '';
            return {
                apiContext: {
                    asbdId,
                    csrfToken,
                    igAppId,
                    igWwwClaim,
                    instagramAjax,
                    webSessionId,
                },
                jazoest: deriveInstagramJazoest(csrfToken),
            };
        }
        catch (error) {
            lastError = error;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Let the CLI capture headers by loading an instagram.com page in the automation browser first
  2. Provide instagramAjax explicitly in the instagram runtime config
  3. Re-login / hard reload to refresh session-captured values
  4. Use the UI route instead, which does not require manually derived headers

Example fix

// before
runtime = { csrfToken, appId: '936619743392459' };
// after
runtime = { csrfToken, appId: '936619743392459', instagramAjax: '1029384756%3A%3A...' };
Defensive patterns

Strategy: validation

Validate before calling

if (!runtime.instagramAjax) {
  await page.goto('https://www.instagram.com/'); // triggers header capture
}

Type guard

function hasInstagramAjax(rt) {
  return typeof rt?.instagramAjax === 'string' && rt.instagramAjax.length > 0;
}

Try / catch

try {
  await publishPrivate(cfg);
} catch (e) {
  if (/could not derive X-Instagram-AJAX/.test(e.message)) {
    await page.goto('https://www.instagram.com/'); // recapture then retry
  } else throw e;
}

Prevention

When it happens

Trigger: resolveInstagramPrivatePublishConfig finds csrfToken and appId but no instagramAjax value in runtime or capture entries.

Common situations: Runtime config built manually without instagramAjax, private call issued before the browser session captured any instagram.com request headers.

Related errors


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