npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@boruto_vk7/insta-fetcher

v0.2.3

Published

Cliente TypeScript para metadados do Instagram autenticado por cookie — versão corrigida para parecer um usuário de navegador real.

Downloads

571

Readme

@boruto_vk7/insta-fetcher — versão "navegador" (0.2.0)

Fork corrigido do pacote original, com foco em parecer um usuário real no navegador (anti-bloqueio/anti-fingerprint) — não apenas em "funcionar".

Cliente TypeScript para consultar metadados do Instagram usando exclusivamente um cookie de sessão já existente. Esta versão não recebe usuário, senha, getCookie() de login ou qualquer credencial: o cookie deve ser obtido pelo próprio usuário (DevTools → Application → Cookies) e armazenado de forma segura.


O que foi corrigido para parecer navegador

O pacote publicado (0.1.x) misturava sinais contraditórios que entregam "sou um bot de Node":

| Problema no original | Correção nesta versão | | --- | --- | | User-Agent de app móvel (iPhone/Android) em endpoints do frontend web (/graphql/query, /web/search/...) | Tudo em www.instagram.com usa um Chrome/Windows atual e coerente (UA + Sec-CH-UA + Sec-CH-UA-Platform + Sec-CH-UA-Mobile que batem entre si) | | Chrome 125 de 2024 (UA e CH-UA não acompanhavam o sec-ch-ua) | Chrome 152 (stable de set/2026), tripla de Client Hints consistente | | authority, origin e x-requested-with em toda requisição | Headers por tipo de requisição: GET XHR sem Origin (navegador só manda em POST/CORS), navegação HTML com Sec-Fetch-Dest: document, upload com app-id próprio | | Sem Sec-Fetch-* nem Sec-CH-UA-* (impressão digital clássica de bot/axios) | Sec-Fetch-Site/Mode/Dest coerentes (same-origin/cors/empty) + Priority: u=1, i | | Accept-Language: pt-BR... fixo, sem relação com a sessão | Accept-Language derivado do locale (configurável) | | Sem X-ASBD-ID/X-Web-Session-ID (o frontend envia nos XHR do www) | Enviados nos XHR web (129477 + id de sessão aleatório por instância) | | Sem Sec-CH-UA-* | Tríade de Client Hints incluída | | Referer sempre https://www.instagram.com/ | Referer contextual: página do perfil, da story, do highlight, do post, de /reels/... como quem clica | | Cookie sessionid=abc%3Adef era URL-decodificado antes de enviar | Valores enviados verbatim, como o navegador faz — decodificar altera o fio e pode invalidar a sessão | | Ritmo de robô (chamadas em rajada) | Pacing opcional entre chamadas encadeadas (off/light/human ou intervalo custom) | | Headers de app (i.instagram.com) usados contra sessão web e vice-versa sem critério | Dois perfis coerentes: web (Chrome/Windows × www) e android/iphone (app × i.instagram.com), nunca misturados na mesma chamada | | Upload/publicação com data em UTC | Data/hora local (timezone_offset em segundos), como o app do usuário |

URLs auditadas ao vivo (0.2.2)

Auditoria método-a-método contra o Instagram real (sessão autenticada). As rotas corrigidas foram validadas respondendo 200 com dados:

| Método | URL correta (host) | Status ao vivo | | --- | --- | --- | | fetchPost / fetchPostByMediaId | www/api/v1/media/{media_id}/info/ | ✅ | | fetchPostByShortcode | converte shortcode→media_id e usa /media/{id}/info/ | ✅ (antes: rota /media/{shortcode}/info/ dava 400) | | fetchUserV2 / getIdByUsername | www/api/v1/users/web_profile_info/?username= → fallback www/api/v1/web/search/topsearch/ | ✅ própria conta; terceiros limitados por IP (429/checkpoint) | | fetchUserIDPostsV2 | www/api/v1/feed/user/{id}/ | ✅ | | fetchStories / fetchUserIDStories | i.instagram.com/api/v1/feed/user/{id}/reel_media/ (app) | ✅ | | fetchHighlights (tray) | www/api/v1/highlights/{id}/highlights_tray/ → fallback app | ✅ | | fetchHighlights (mídia) | página HTML www/stories/highlights/{id}/ (extrai xdt_api__v1__feed__reels_media__connection) | ✅ (0.2.3: 210 mídias ao vivo) | | fetchUserReel (aba Reels) | www/api/v1/clips/user/ → fallback doc_id → fallback feed filtrando clips | ✅ (0.2.3) | | getReelData | página www/reel/{code}/ (navegação HTML) | ⚠️ login wall/recaptcha por IP | | searchFollower/Following | www/api/v1/friendships/{id}/followers\|following/ | ✅ rota responde |

Notas do mundo real (não são bugs do pacote):

  • /api/v1/users/{username}/usernameinfo/ (www e app) está descontinuada (volta 200 com corpo vazio/erro) — por isso o módulo não a usa.
  • /users/{id}/info/ só traz corpo completo para a própria conta; para terceiros volta vazio (o módulo segue com web_profile_info/topsearch).
  • Ids de highlight vêm como highlight:12345… — o módulo remove o prefixo antes de pedir a mídia.
  • web_profile_info de terceiros, HTML de perfil e reels_media podem cair em 429/checkpoint/recaptcha dependendo do IP e do volume — são limitações de ambiente, não de headers. Use com calma (pacing) e em IP residencial limpo.

O que mudou em 0.2.3 (pós-captcha)

  • Mídia de highlights: o Instagram hoje carrega a mídia na página HTML /stories/highlights/{id}/ (JSON xdt_api__v1__feed__reels_media__connection com os itens completos). O pacote extrai esse JSON com parse balanceado — antes a rota /feed/reels_media/ voltava vazia para highlights e o resultado era highlights: []. Validado ao vivo: 7 destaques / 210 mídias com covers.
  • Cover dos destaques: lê cover_media.cropped_image_version / full_image_version (shape real do tray).
  • Aba Reels (fetchUserReel): agora tenta clips/user (XDT do frontend) → doc_id GraphQL (legado) → fallback filtrando os clips do feed — nunca mais devolve vazio por causa de um doc_id desatualizado (403). Validado ao vivo.
  • Perfil de terceiro: com a sessão limpa, /users/{id}/info/ volta a responder com corpo completo — fetchUser entrega bio + contagens + foto.

Stories corrigidos (0.2.1)

  • Bug: o endpoint "web" /api/v1/feed/reels_media/ vinha retornando reels_media: [] mesmo quando o perfil tinha story ativo (rota morta para consulta por usuário).
  • Fix: fetchStories usa o endpoint que o app realmente preenche — i.instagram.com/api/v1/feed/user/{id}/reel_media/ — com impressão digital de app Android coerente. Funciona para qualquer perfil público (seguido ou não).
  • Novo método fetchUserIDStories(userId) para quando a resolução de username estiver limitada na sessão mas o ID já for conhecido.
  • Highlights (fetchHighlights) agora tentam web e caem para o app automaticamente (tray e mídia) se a rota web vier vazia.

Além do fingerprint

  • Perfil agora usa web_profile_info (/api/v1/users/web_profile_info/?username=…), o endpoint que o frontend React chama de verdade (antes: usernameinfo de app).
  • Stories e highlights usam os fluxos do navegador: /api/v1/feed/reels_media/ e /api/v1/highlights/{id}/highlights_tray/.
  • Fallback automático: se uma rota /api/v1/… do www responder 404/405 (rota removida pelo Instagram), a mesma chamada é repetida em i.instagram.com trocando a impressão digital para Android — nunca mistura os dois perfis.
  • Captura de reel pela página HTML (/reel/{code}/) mais robusta.
  • Retries com backoff com jitter e respeito ao Retry-After do 429; 401/403 não são re-tentados e geram mensagens claras (cookie expirado / checkpoint).

Instalação

Via arquivo local (pasta ou tarball desta versão corrigida):

npm install /caminho/para/insta-fetcher-fixed
# ou, mantendo o mesmo nome de pacote nos imports:
npm install "@boruto_vk7/insta-fetcher@file:/caminho/para/insta-fetcher-fixed.tgz"

Uso

import { InstagramEngine } from '@boruto_vk7/insta-fetcher';

const instagram = new InstagramEngine({
  cookiesFile: './cookies.txt',   // export Netscape ou JSON ou header
  pacing: 'light',                // 'off' | 'light' | 'human' (+ pacingRange)
  locale: 'en_US',                // espelha no Accept-Language
  timeoutMs: 20_000,
});
// API pública idêntica à versão 0.1.x:
const id      = await instagram.getIdByUsername('instagram');
const post    = await instagram.fetchPost('https://www.instagram.com/p/SHORTCODE/');
const posts   = await instagram.fetchUserPostsV2('instagram');
const reels   = await instagram.fetchUserReel('instagram');
const stories = await instagram.fetchStories('instagram');
const hl      = await instagram.fetchHighlights('instagram');
const account = await instagram.accountInfo();

IgApi, igApi e createInstagramClient continuam como aliases. Helpers de cookie e de shortcode também.

Opções novas

| Opção | Padrão | Descrição | | --- | --- | --- | | surface | 'web' | web (navegador desktop) · android/iphone (app) | | pacing | 'light' | ritmo entre chamadas: light (~120–450 ms), human (~700–2200 ms), off | | pacingRange | – | intervalo próprio { minMs, maxMs } | | acceptLanguage | derivado de locale | header Accept-Language | | locale | 'en_US' | usado para derivar o Accept-Language | | mobileFallback | true | repete rota www removida no host do app com perfil Android | | appId / asbdId | do frontend | sobrescreve X-IG-App-ID / X-ASBD-ID | | debug | false | logs de diagnóstico (nunca imprime o cookie) |


Avisos

  • O Instagram muda endpoints, headers e respostas sem aviso. Rotas marcadas como legadas (ex.: fetchUserPosts) podem deixar de existir — prefira as variantes V2.
  • Use somente em contas e dados para os quais você tenha autorização. Este pacote não contorna CAPTCHA, checkpoint, desafios ou limites — e não deve ser usado para isso.
  • Nunca publique cookies, não os coloque no Git nem em logs.

Build e testes

npm install
npm run typecheck
npm run build
npm test

Os testes rodam contra um servidor HTTP local e verificam os headers reais (UA, Client Hints, Sec-Fetch-*, ausência de Origin em GET, presença em POST, referers, fallback de host) — ou seja, a "cara de navegador" fica travada por testes, não só por boas intenções.

Rotas Express

O exemplo em examples/instagram.routes.ts (do upstream) não faz parte do pacote publicado; se precisar, o padrão de uso continua o mesmo.