{"record":{"id":"0af039527ed2b98d","repo":"jackwener/OpenCLI","slug":"http-res-status-make-sure-you-are-logged","errorCode":null,"errorMessage":"HTTP ' + res.status + ' - make sure you are logged in to Instagram","messagePattern":"HTTP ' \\+ res\\.status \\+ ' - make sure you are logged in to Instagram","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/instagram/explore.js","lineNumber":23,"sourceCode":"    access: 'read',\n    description: 'Instagram explore/discover trending posts',\n    domain: 'www.instagram.com',\n    args: [\n        { name: 'limit', type: 'int', default: 20, help: 'Number of posts' },\n    ],\n    columns: ['rank', 'user', 'caption', 'likes', 'comments', 'type'],\n    pipeline: [\n        { navigate: 'https://www.instagram.com' },\n        { evaluate: `(async () => {\n  const limit = \\${{ args.limit }};\n  const res = await fetch(\n    'https://www.instagram.com/api/v1/discover/web/explore_grid/',\n    {\n      credentials: 'include',\n      headers: { 'X-IG-App-ID': '936619743392459' }\n    }\n  );\n  if (!res.ok) throw new Error('HTTP ' + res.status + ' - make sure you are logged in to Instagram');\n  const data = await res.json();\n\n  // Instagram no longer populates the flat layout_content.medias[] path. Media\n  // objects are now nested across mixed layout shapes (one_by_two_item.clips.\n  // items[].media, fill_items[].media, etc.), so recursively walk each sectional\n  // item collecting every distinct node.media and dedupe by pk/id/code. See #2091.\n  const seen = new Set();\n  const medias = [];\n  const collect = (node, depth) => {\n    if (!node || typeof node !== 'object' || depth > 8) return;\n    if (Array.isArray(node)) {\n      for (const item of node) collect(item, depth + 1);\n      return;\n    }\n    const media = node.media;\n    if (media && typeof media === 'object' && !Array.isArray(media)) {\n      const key = media.pk ?? media.id ?? media.code;\n      if (key != null && !seen.has(key)) {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/explore.js#L5-L41","documentation":"The instagram explore command's in-page script calls Instagram's web explore_grid API with cookie credentials; if the response is not ok, it throws a plain Error 'HTTP <status> - make sure you are logged in to Instagram'. This surfaces the raw HTTP status of the explore API call and hints the most common cause: an unauthenticated session (401/403) or throttling (429).","triggerScenarios":"The fetch to https://www.instagram.com/api/v1/discover/web/explore_grid/ inside the page returns a non-2xx status — 401/403 when not logged in or missing X-IG-App-ID acceptance, 429 when rate limited, 5xx from Instagram.","commonSituations":"Running explore without ever logging into Instagram in the automation browser; expired session cookies; hitting explore too frequently from one IP/account; Instagram changing required headers (X-IG-App-ID or CSRF) and rejecting old requests.","solutions":["Log in to Instagram in the browser session, then re-run explore","Wait and retry if the status is 429 (rate limited)","Update the CLI if Instagram changed required API headers","Check the reported status code: 401/403 = auth, 429 = throttle, 5xx = Instagram-side"],"exampleFix":"// before: raw throw in evaluate\nif (!res.ok) throw new Error('HTTP ' + res.status + ' - make sure you are logged in to Instagram');\n// after: caller-side retry for transient statuses\ntry { await explore(); } catch (e) {\n  if (String(e.message).startsWith('HTTP 429')) { await sleep(60000); return explore(); }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// before running explore, confirm the session is logged in\nconst loggedIn = await browserPage.evaluate(() => !!document.cookie.match(/sessionid=/));\nif (!loggedIn) throw new Error('Log in to Instagram in the browser session first');","typeGuard":null,"tryCatchPattern":"try {\n  await run(['instagram', 'explore']);\n} catch (e) {\n  const m = String(e.message).match(/^HTTP (\\d+)/);\n  if (m) {\n    const status = Number(m[1]);\n    if (status === 429) await sleep(60_000);        // retry after backoff\n    else if (status === 401 || status === 403) /* re-authenticate */;\n  } else throw e;\n}","preventionTips":["Log in to Instagram in the automation browser before using explore","Parse the status code in the message to pick auth vs backoff responses","Space out explore calls to avoid 429s","Update the CLI if Instagram changes required headers like X-IG-App-ID"],"tags":["instagram","http-error","authentication","rate-limit","explore"],"backgroundTag":"instagram-api-http-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}